【Android】 Framework笔记——Service 启动流程

Service 同样是 Android 四大组件之一,它主要用于在后台执行一些耗时的逻辑以及一些长期运行的任务。它的启动方式主要有两种:startService 以及 bindService,我们分别对这两者的启动流程进行分析。

startService

我们的 startService 往往都是通过 ContextImpl.startService 调用:

@Override
public ComponentName startService(Intent service) {
   warnIfCallingFromSystemProcess();
   return startServiceCommon(service, false, mUser);
}

转调到 startServiceCommon

private ComponentName startServiceCommon(Intent service, boolean requireForeground,
        UserHandle user) {
    try {
        // 验证 Service Intent
        validateServiceIntent(service);
        service.prepareToLeaveProcess(this);
        // 通过 ActivityMananger 获取到 AMS 本地代理,调用 startService 方法
        ComponentName cn = ActivityManager.getService().startService(
            mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded(
                        getContentResolver()), requireForeground,
                        getOpPackageName(), user.getIdentifier());
        // ...
        return cn;
    } catch (RemoteException e) {
        throw e.rethrowFromSystemServer();
    }
}

这里首先调用 validateServiceIntentIntent 进行了验证,之后通过 ActivityManager.getService() 获取到了 AMS 的本地代理并调用其 startService

private void validateServiceIntent(Intent service) {
    if (service.getComponent() == null && service.getPackage() == null) {
        if (getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.LOLLIPOP) {
            IllegalArgumentException ex = new IllegalArgumentException(
                    "Service Intent must be explicit: " + service);
            throw ex;
        } else {
            Log.w(TAG, "Implicit intents with startService are not safe: " + service
                    + " " + Debug.getCallers(2, 3));
        }
    }
}

validateServiceIntent 中实际上就是检查了 targetSdkVersion

之后通过 Binder 来到了 ActivityManagerService.startService 方法:

@Override
public ComponentName startService(IApplicationThread caller, Intent service,
        String resolvedType, boolean requireForeground, String callingPackage, int userId)
        throws TransactionTooLargeException {
    // ...
    synchronized(this) {
        // ...
        try {
            // mServices 为 ActiveServices
            res = mServices.startServiceLocked(caller, service,
                    resolvedType, callingPid, callingUid,
                    requireForeground, callingPackage, userId);
        } finally {
            Binder.restoreCallingIdentity(origId);
        }
        return res;
    }
}

服务信息的查询

startService 中实际上转调到了 ActiveServices.startServiceLocked 方法:

ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType,
int callingPid, int callingUid, boolean fgRequired, String callingPackage, final int userId)
        throws TransactionTooLargeException {
    // ...
    // 查询 Service 的信息
    ServiceLookupResult res =
        retrieveServiceLocked(service, resolvedType, callingPackage,
                callingPid, callingUid, userId, true, callerFg, false, false);
    // ...
    ServiceRecord r = res.record;
    // ...
    // 将 Service 的启动参数添加到 pendingStarts,它会传递给 onStartCommand
    r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),
            service, neededGrants, callingUid));
        // ...
    // 如果并非前台服务
    final ServiceMap smap = getServiceMap(r.userId);
    boolean addToStarting = false;
    if (!callerFg && !fgRequired && r.app == null
            && mAm.mUserController.hasStartedUserState(r.userId)) {
        ProcessRecord proc = mAm.getProcessRecordLocked(r.processName, r.appInfo.uid, false);
        if (proc == null || proc.curProcState > ActivityManager.PROCESS_STATE_RECEIVER) {
            // 若 Service 启动的进程还未创建
            // ...
            if (r.delayed) {
                // 如果该 Service 已经延迟启动,则先返回
                return r.name;
            }
            if (smap.mStartingBackground.size() >= mMaxStartingBackground) {
                // 如果后台 Service 数已经超出阈值,将该 Service 延迟启动
                smap.mDelayedStartList.add(r);
                r.delayed = true;
                return r.name;
            }
            addToStarting = true;
        } else if (proc.curProcState >= ActivityManager.PROCESS_STATE_SERVICE) {
            // 若 Service 的进程已经创建
            addToStarting = true;
        }
        // ...

    ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting);
    return cmp;
}

这里分为以下几步:

  1. 调用 retrieveServiceLocked 查询 Service 的信息获得 ServiceLookupResult
  2. Service 解析出来的 ServiceLookupResult 中获取 Service 对应的 ServiceRecord
  3. Service 的启动参数添加到 ServiceRecord.pendingStarts 中,它会最终交给 onStartCommand
  4. Service 并非前台服务,若 Service 启动的进程还未创建,如果启动的后台任务已经到达阈值,将该 Service 延迟启动,否则将 addToStarting 设置为 true 表示该 Service 作为后台 Service 启动。
  5. Service 启动的进程已创建,则将 addToStarting 设置为 true。
  6. 调用 startServiceInnerLocked 方法。

我们先看到 retrieveServiceLocked 是如何查询 Service 的信息的:

private ServiceLookupResult retrieveServiceLocked(Intent service,
        String resolvedType, String callingPackage, int callingPid, int callingUid, int userId,
        boolean createIfNeeded, boolean callingFromFg, boolean isBindExternal,
        boolean allowInstant) {
    ServiceRecord r = null;
    // ...
    ServiceMap smap = getServiceMapLocked(userId);
    final ComponentName comp = service.getComponent();
    // ...
    if (r == null) {
        try {
            // ...
            // 通过 PMS 对 Intent 进行解析
            ResolveInfo rInfo = mAm.getPackageManagerInternalLocked().resolveService(service,
                    resolvedType, flags, userId, callingUid);
            ServiceInfo sInfo =
                rInfo != null ? rInfo.serviceInfo : null;
            //...
            ComponentName name = new ComponentName(
                    sInfo.applicationInfo.packageName, sInfo.name);


            r = smap.mServicesByName.get(name);
            // ...
            if (r == null && createIfNeeded) {
                // ...
                // 构建 ServiceRecord
                r = new ServiceRecord(mAm, ss, name, filter, sInfo, callingFromFg, res);
                res.setService(r);
                smap.mServicesByName.put(name, r);
                smap.mServicesByIntent.put(filter, r);
                                // ...
        } catch (RemoteException ex) {
            // pm is in same process, this will never happen.
        }
    }
    if (r != null) {
        // ...
        // 构造返回 ServiceLookupResult
        return new ServiceLookupResult(r, null);
    }
    return null;
}

可以看到,这里首先通过 PMS.resolveService 方法对 Intent 的信息进行了解析获取了 ServiceInfo,之后若没有对应的 ServiceRecord 则根据它构建了一个 ServiceRecord。最后根据 ServiceRecord 构建了 ServiceLookupResult

服务的启动

接着我们看到 startServiceInnerLocked

ComponentName startServiceInnerLocked(ServiceMap smap, Intent service, ServiceRecord r,
        boolean callerFg, boolean addToStarting) throws TransactionTooLargeException {
    // ...
    // 拉起 Service
    String error = bringUpServiceLocked(r, service.getFlags(), callerFg, false, false);
    // ...
    return r.name;
}

这里调用了 bringUpServiceLocked 拉起服务:

private final String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg, boolean whileRestarting) throws TransactionTooLargeException {
    if (r.app != null && r.app.thread != null) {
        // 传递启动 Service 的参数
        sendServiceArgsLocked(r, execInFg, false);
        return null;
    }
    // service正在启动,将delayed设置为false
    if (r.delayed) {
        getServiceMap(r.userId).mDelayedStartList.remove(r);
        r.delayed = false;
    }

    // 查询服务运行的进程
    final boolean isolated = (r.serviceInfo.flags&ServiceInfo.FLAG_ISOLATED_PROCESS) != 0;
    final String procName = r.processName;
    ProcessRecord app;
    if (!isolated) {
        // 根据进程名和 uid,查询 ProcessRecord
        app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false);
        if (app != null && app.thread != null) {
            try {
                app.addPackage(r.appInfo.packageName, r.appInfo.versionCode, mAm.mProcessStats);
                // 若进程已存在,start Service
                realStartServiceLocked(r, app, execInFg);
                return null;
            } catch (TransactionTooLargeException e) {
                throw e;
            } catch (RemoteException e) {
                Slog.w(TAG, "Exception when starting service " + r.shortName, e);
            }
        }
    } else {
        app = r.isolatedProc;
    }

    if (app == null) {
        // 若 Service 运行的进程不存在,启动进程
        if ((app=mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,
                "service", r.name, false, isolated, false)) == null) {
                // ...
        }
            // ...
    }
    return null;
}

这里主要分为三步:

  1. Service 启动的进程已存在,调用 sendServiceArgsLocked 传递 Service 启动的参数,会导致 onStartCommand 的调用
  2. Service 启动的进程已存在,则调用 realStartServiceLocked 方法启动服务。
  3. Service 启动的进程不存在,先调用 mAm.startProcessLocked 启动进程。进程启动后会调用 realStartServiceLocked 启动服务。

启动参数的传递

我们先看到 sendServiceArgsLocked 看看 Service 的启动参数是如何传递的:

private final void sendServiceArgsLocked(ServiceRecord r, boolean execInFg,
        boolean oomAdjusted) throws TransactionTooLargeException {
    final int N = r.pendingStarts.size();
    ArrayList<ServiceStartArgs> args = new ArrayList<>();

    while (r.pendingStarts.size() > 0) {
        ServiceRecord.StartItem si = r.pendingStarts.remove(0);
        // ...
        args.add(new ServiceStartArgs(si.taskRemoved, si.id, flags, si.intent));
    }

    ParceledListSlice<ServiceStartArgs> slice = new ParceledListSlice<>(args);
    slice.setInlineCountLimit(4);
    Exception caughtException = null;
    try {
        // 调用 ApplicationThread.scheduleServiceArgs
        r.app.thread.scheduleServiceArgs(r, slice);
    } // ...
}

它会遍历 pendingStarts,构建一个 List<ServiceStartArgs> 启动参数列表,之后通过 ApplicationThread 的代理类调用 ApplicationThread.scheduleServiceArgs 回到客户端进程。关于回去以后做的事我们之后再看。

启动 Service

之后我们看看 realStartService 方法如何启动了 Service

private final void realStartServiceLocked(ServiceRecord r,
        ProcessRecord app, boolean execInFg) throws RemoteException {
    // ...
    r.app = app;
    // 尝试在 Services 中添加该 ServiceRecord,若成功则说明是新 Service
    final boolean newService = app.services.add(r);
    // ...
    boolean created = false;
    try {
        // ...
        // 调用 ApplicationThread.scheduleCreateService
        app.thread.scheduleCreateService(r, r.serviceInfo,
                mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
                app.repProcState);
        // 发送 Notification
        r.postNotification();
        created = true;
    } 
    // ...
    // 传递 Service 参数
    sendServiceArgsLocked(r, execInFg, true);
    // ...
}

这里步骤如下:

  1. 首先尝试在 Services 列表中添加该 Service,若添加成功则说明它是新 Service
  2. 通过 ApplicationThread 的代理类调用 ApplicationThread.scheduleCreateService 回到客户端进程。此处会导致 onCreate 的调用
  3. 调用 sendServiceArgsLocked 传递参数,会导致 onStartCommand 的调用。(前面调用是在进程已启动的情况下)

Service 的创建

服务端调用 ApplicationThread.scheduleCreateService 后会来到客户端,最终导致 Service 的创建:

public final void scheduleCreateService(IBinder token,
        ServiceInfo info, CompatibilityInfo compatInfo, int processState) {
    updateProcessState(processState, false);
    CreateServiceData s = new CreateServiceData();
    s.token = token;
    s.info = info;
    s.compatInfo = compatInfo;

    sendMessage(H.CREATE_SERVICE, s);
}

它会发送信息给其外部类 ActivityThreadH

public void handleMessage(Message msg) {
        switch (msg.what) {
                // ...
                case CREATE_SERVICE:
                Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, ("serviceCreate: " + String.valueOf(msg.obj)));
                handleCreateService((CreateServiceData)msg.obj);
                Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                break;
        // ...

最终调用到了 ActivityThread.handleCreateService

private void handleCreateService(CreateServiceData data) {
    // ...
    try {
        // 通过反射构造 Service 对象
        java.lang.ClassLoader cl = packageInfo.getClassLoader();
        service = packageInfo.getAppFactory()
                .instantiateService(cl, data.info.name, data.intent);
    }
    // ...

    try {
        if (localLOGV) Slog.v(TAG, "Creating service " + data.info.name);
                // 构造 ContextImpl
        ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
        context.setOuterContext(service);

        // 若没有创建 Application,创建 Application
        Application app = packageInfo.makeApplication(false, mInstrumentation);
        // 调用 Service.attach
        service.attach(context, this, data.info.name, data.token, app,
                ActivityManager.getService());
        // 调用 Service.onCreate
        service.onCreate();
        mServices.put(data.token, service);
        // 通知 AMS
        try {
            ActivityManager.getService().serviceDoneExecuting(
                    data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }
    // ...
}

这里步骤如下:

  1. 通过反射构造 Service 对象
  2. 构造 ContextImpl 及尝试创建 Application
  3. 调用 Service.attach 进行初始化
  4. 调用 Service.onCreate 回调生命周期
  5. 通知 AMS

我们可以看看 Service.attach 做了什么:

public final void attach(
        Context context,
        ActivityThread thread, String className, IBinder token,
        Application application, Object activityManager) {
    attachBaseContext(context);
    mThread = thread;           // NOTE:  unused - remove?
    mClassName = className;
    mToken = token;
    mApplication = application;
    mActivityManager = (IActivityManager)activityManager;
    mStartCompatibility = getApplicationInfo().targetSdkVersion
            < Build.VERSION_CODES.ECLAIR;
}

实际上都是一些参数的初始化。

参数的传递

服务端调用 ApplicationThread.scheduleServiceArgs 从而进行 Service 启动参数的传递。

public final void scheduleServiceArgs(IBinder token, ParceledListSlice args) {
    List<ServiceStartArgs> list = args.getList();

    for (int i = 0; i < list.size(); i++) {
        ServiceStartArgs ssa = list.get(i);
        ServiceArgsData s = new ServiceArgsData();
        s.token = token;
        s.taskRemoved = ssa.taskRemoved;
        s.startId = ssa.startId;
        s.flags = ssa.flags;
        s.args = ssa.args;

        sendMessage(H.SERVICE_ARGS, s);
    }
}

这里将参数遍历后,对每个参数调用了 sendMessage 方法传递,在 handleMessage 中调用了 handleServiceArgs 方法:

private void handleServiceArgs(ServiceArgsData data) {
        // 获取对应 Service
    Service s = mServices.get(data.token);
    if (s != null) {
        try {
            if (data.args != null) {
                data.args.setExtrasClassLoader(s.getClassLoader());
                data.args.prepareToEnterProcess();
            }
            int res;
            if (!data.taskRemoved) {
                    // 调用 Service.onStartCommand 方法
                res = s.onStartCommand(data.args, data.flags, data.startId);
            } else {
                s.onTaskRemoved(data.args);
                res = Service.START_TASK_REMOVED_COMPLETE;
            }

            QueuedWork.waitToFinish();
                        // 通知 AMS
            try {
                ActivityManager.getService().serviceDoneExecuting(
                        data.token, SERVICE_DONE_EXECUTING_START, data.startId, res);
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
        } catch (Exception e) {
            if (!mInstrumentation.onException(s, e)) {
                throw new RuntimeException(
                        "Unable to start service " + s
                        + " with " + data.args + ": " + e.toString(), e);
            }
        }
    }
}

这里通过 Token 获取到了对应的 Service,之后调用了它的 onStartCommand 方法。同时需要注意的是,onStartCommand 是在主线程调用的。

bindService

接着我们来看看 bindService 是一个怎样的过程,实际上调用到了 ContextImpl.bindService

@Override
public boolean bindService(Intent service, ServiceConnection conn, int flags) {
    warnIfCallingFromSystemProcess();
    return bindServiceCommon(service, conn, flags, mMainThread.getHandler(), getUser());
}

它需要传入 ServiceConnection 这个接口,在连接建立或断开时会回调其中的方法。最后调用到了 bindServiceCommon

private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags, Handler
        handler, UserHandle user) {
    // 校验 Service 的 intent
    validateServiceIntent(service);
    try {
        // 调用 getActivityToken 获取对应的 Token
        IBinder token = getActivityToken();
        // 调用 AMS 的 bindService 方法
        int res = ActivityManager.getService().bindService(
            mMainThread.getApplicationThread(), getActivityToken(), service,
            service.resolveTypeIfNeeded(getContentResolver()),
            sd, flags, getOpPackageName(), user.getIdentifier());
        // ...
    } catch (RemoteException e) {
        throw e.rethrowFromSystemServer();
    }
}

这里首先调用了 validateServiceIntentIntent 进行了检查,之后调用了 getActivityToken 获取到了 token,最后通过 AMS 的本地代理调用了 AMS.bindService 方法。

我们先看看 getActivityToken 做了什么:

@Override
public IBinder getActivityToken() {
    return mActivityToken;
}

这里实际上就是 ActivtiyToken,它是由 ContextImpl 构造时传入的,若 token 不为空说明是由 Activity 进行的 bindService

查询服务相关信息

调用了 ActivityManagerService.bindService 后来到了 SystemServer 服务端:

public int bindService(IApplicationThread caller, IBinder token, Intent service,
            String resolvedType, IServiceConnection connection, int flags, String callingPackage, int userId) throws TransactionTooLargeException {
    enforceNotIsolatedCaller("bindService");

    // ...
    synchronized(this) {
        return mServices.bindServiceLocked(caller, token, service,
                resolvedType, connection, flags, callingPackage, userId);
    }
}

这里调用到了 ActiveServices.bindServiceLocked 方法:

int bindServiceLocked(IApplicationThread caller, IBinder token, Intent service,
        String resolvedType, final IServiceConnection connection, int flags,
        String callingPackage, final int userId) throws TransactionTooLargeException {
    // ...
    // 如果是由 Activity 启动的话,获取 bindService 的 ActivityRecord
    ActivityRecord activity = null;
    if (token != null) {
        activity = ActivityRecord.isInStackLocked(token);
        if (activity == null) {
            Slog.w(TAG, "Binding with unknown activity: " + token);
            return 0;
        }
    }

    // ...
    final boolean callerFg = callerApp.setSchedGroup != ProcessList.SCHED_GROUP_BACKGROUND;
    final boolean isBindExternal = (flags & Context.BIND_EXTERNAL_SERVICE) != 0;
    final boolean allowInstant = (flags & Context.BIND_ALLOW_INSTANT) != 0;
        // 调用 retrieveServiceLocked 获取要启动的 Service 的信息
    ServiceLookupResult res =
        retrieveServiceLocked(service, resolvedType, callingPackage, Binder.getCallingPid(),
                Binder.getCallingUid(), userId, true, callerFg, isBindExternal, allowInstant);
    // ...
    try {
        mAm.startAssociationLocked(callerApp.uid, callerApp.processName, callerApp.curProcState,
                s.appInfo.uid, s.name, s.processName);
        // 查找 service 对应的 AppBindRecord
        AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
        ConnectionRecord c = new ConnectionRecord(b, activity,
                connection, flags, clientLabel, clientIntent);

        IBinder binder = connection.asBinder();
        // 获取 connection 列表,将传入的 connection 加入
        ArrayList<ConnectionRecord> clist = s.connections.get(binder);
        if (clist == null) {
            clist = new ArrayList<ConnectionRecord>();
            s.connections.put(binder, clist);
        }
        clist.add(c);
        b.connections.add(c);
        // 将 Connection 也加入对应 ActivityRecord 的 connection 列表
        if (activity != null) {
            if (activity.connections == null) {
                activity.connections = new HashSet<ConnectionRecord>();
            }
            activity.connections.add(c);
        }
        b.client.connections.add(c);
        // 
        clist = mServiceConnections.get(binder);
        if (clist == null) {
            clist = new ArrayList<ConnectionRecord>();
            mServiceConnections.put(binder, clist);
        }
        clist.add(c);

        // 调用 bringUpServiceLocked
        if ((flags&Context.BIND_AUTO_CREATE) != 0) {
            s.lastActivity = SystemClock.uptimeMillis();
            if (bringUpServiceLocked(s, service.getFlags(), callerFg, false,
                    permissionsReviewRequired) != null) {
                return 0;
            }
        }

        // ...
        if (s.app != null && b.intent.received) {
            // Service 已经运行,调用 ConnectionRecord 中 ServiceConnection.connected
            try {
                c.conn.connected(s.name, b.intent.binder, false);
            } catch (Exception e) {
                Slog.w(TAG, "Failure sending service " + s.shortName
                        + " to connection " + c.conn.asBinder()
                        + " (in " + c.binding.client.processName + ")", e);
            }
        } else {

        }
        // ...
    } finally {
        Binder.restoreCallingIdentity(origId);
    }

    return 1;
}

这里主要是下面几步:

  1. 若是 Activity 启动,通过 token 获取到对应的 ActivityRecord
  2. 调用 retrieveServiceLocked 对要启动的 Intent 通过 PMS 进行查询获取 ServiceLookupResult,从而获取 ServiceRecord
  3. 查询 ServiceConnectionRecord 列表,并将当前 connection 转为对应的 ConnectionRecord
  4. 调用 bringUpServiceLocked 启动 Service,步骤与 startService 相同,会导致 Service 的创建,不过在 realStartServiceLocked 中会调用到 requestServiceBindingsLocked 方法,最终会导致 onBind 的调用

服务的启动

服务的启动与 startService 相同,通过 bringUpServiceLocked 实现,这里不具体去看了。

服务的绑定

我们主要看看 requestServiceBindingsLocked 方法的实现,它实现了服务的绑定:

private final void requestServiceBindingsLocked(ServiceRecord r, boolean execInFg)
        throws TransactionTooLargeException {
    for (int i=r.bindings.size()-1; i>=0; i--) {
        IntentBindRecord ibr = r.bindings.valueAt(i);
        if (!requestServiceBindingLocked(r, ibr, execInFg, false)) {
            break;
        }
    }
}

会导致 requestServiceBindingLocked 的调用:

private final boolean requestServiceBindingLocked(ServiceRecord r, IntentBindRecord i,
        boolean execInFg, boolean rebind) throws TransactionTooLargeException {
    if (r.app == null || r.app.thread == null) {
        // If service is not currently running, can't yet bind.
        return false;
    }
    if (DEBUG_SERVICE) Slog.d(TAG_SERVICE, "requestBind " + i + ": requested=" + i.requested
            + " rebind=" + rebind);
    if ((!i.requested || rebind) && i.apps.size() > 0) {
        try {
            bumpServiceExecutingLocked(r, execInFg, "bind");
            r.app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE);
            // scheduleBindService 的调用
            r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind,
                    r.app.repProcState);
            if (!rebind) {
                i.requested = true;
            }
            i.hasBound = true;
            i.doRebind = false;
        }// ...
    }
    return true;
}

这里调用了 ApplicationThread.scheduleBindService 方法,它最终会导致 ActivityThread.handleBindService 的调用:

private void handleBindService(BindServiceData data) {
    Service s = mServices.get(data.token);
    if (s != null) {
        try {
            // ...
            try {
                if (!data.rebind) {
                    // 调用 onBind 获取 binder 对象
                    IBinder binder = s.onBind(data.intent);
                    ActivityManager.getService().publishService(
                            data.token, data.intent, binder);
                } else {
                    s.onRebind(data.intent);
                    ActivityManager.getService().serviceDoneExecuting(
                            data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
                }
                //...
            }
        }
        // ...
    }
}

这里首先调用了 Service.onBind 方法获取到了对应的 IBinder 对象,之后调用了 AMS 本地代理对象的 publishService 方法:

public void publishService(IBinder token, Intent intent, IBinder service) {
    // Refuse possible leaked file descriptors
    if (intent != null && intent.hasFileDescriptors() == true) {
        throw new IllegalArgumentException("File descriptors passed in Intent");
    }

    synchronized(this) {
        if (!(token instanceof ServiceRecord)) {
            throw new IllegalArgumentException("Invalid service token");
        }
                // 调用 ActiveServices.publishServiceLocked
        mServices.publishServiceLocked((ServiceRecord)token, intent, service);
    }
}

它调用到了 ActiveServices.publishServiceLocked 方法:

void publishServiceLocked(ServiceRecord r, Intent intent, IBinder service) {
    final long origId = Binder.clearCallingIdentity();
    try {
        if (r != null) {
            Intent.FilterComparison filter
                    = new Intent.FilterComparison(intent);
            IntentBindRecord b = r.bindings.get(filter);
            if (b != null && !b.received) {
                b.binder = service;
                b.requested = true;
                b.received = true;
                for (int conni=r.connections.size()-1; conni>=0; conni--) {
                    ArrayList<ConnectionRecord> clist = r.connections.valueAt(conni);
                    for (int i=0; i<clist.size(); i++) {
                        ConnectionRecord c = clist.get(i);
                        if (!filter.equals(c.binding.intent.intent)) {
                            continue;
                        }

                        try {
                                                        // 这里会调用 ConnectionRecord.conn.connected 方法
                            c.conn.connected(r.name, service, false);
                        } 
                    }
                }
            }
            serviceDoneExecutingLocked(r, mDestroyingServices.contains(r), false);
        }
    } finally {
        Binder.restoreCallingIdentity(origId);
    }
}

这里主要是调用了对应 ConnectionRecord.conn.connected 方法,这会最终导致 ServiceConnection.onServiceConnected 的调用

ConnectionRecord.conn 实际上是 LoadApk.InnerConnection 在 SystemServer 进程的代理对象,从而回到了启动 Service 的进程:

private static class InnerConnection extends IServiceConnection.Stub {
    final WeakReference<LoadedApk.ServiceDispatcher> mDispatcher;

    public void connected(ComponentName name, IBinder service) throws RemoteException {
        LoadedApk.ServiceDispatcher sd = mDispatcher.get();
        if (sd != null) {
            sd.connected(name, service); //[见流程19]
        }
    }
}

它会调用到 ServiceDispatcher.connected

public void connected(ComponentName name, IBinder service) {
    if (mActivityThread != null) {
        mActivityThread.post(new RunConnection(name, service, 0));
    } else {
        doConnected(name, service);
    }
}

这里如果在主线程会尝试向主线程的 Handlerpost 一个 RunConnection,否则直接调用 doConnected 方法。

private final class RunConnection implements Runnable {
    final ComponentName mName;
    final IBinder mService;
    final int mCommand;

    public void run() {
        if (mCommand == 0) {
            doConnected(mName, mService);
        } else if (mCommand == 1) {
            doDeath(mName, mService);
        }
    }
}

这里实际上也是调用 doConnected 方法:

public void doConnected(ComponentName name, IBinder service, boolean dead) {
        // ...
        if (service != null) {
            // 调用 ServiceConnection.onServiceConnected
            mConnection.onServiceConnected(name, service);
        }
        // ...
}

这里最终导致了 mConnection.onServiceConnected 的调用。

总结

Service 的启动主要有两种方式:startServicebindService,它们的区别在于:

  • bindService 启动方与启动的 Service 存在关联。可以通过 ServiceonBind 中返回的匿名 Binder 实现启动 Service 一端与启动的 Service 的通信,匿名 Binder 通过 ServiceConnection 传递。需要调用 unbindService 来取消绑定。
  • startService 启动方与启动的 Service 之间不存在关联。仅仅启动了 Service

startServicebindService 的流程类似,只是 bindService 多了绑定 Service 传递匿名 Binder 的过程

**startService **

  1. 通过 ContextImpl 调用,之后调用到了 AMSstartService,它最终会调用 ActiveServices.startServiceLocked 从而开始启动 Service

  2. 首先会调用 retrieveServiceLocked 方法通过 PMS 查询对应的 ServiceRecord

  3. 之后会调用到 bringUpServiceLocked 方法拉起 Service,在该方法中,如果启动的 Service 进程已存在,则会首先调用 sendServiceArgsLocked 方法传递 Service 的启动参数,之后会调用 realStartServiceLocked 方法。若不存在对应进程则会首先会创建对应的进程,进程创建完毕后仍热会调用 realStartServiceLocked 方法。

  4. realStartServiceLocked 中会调用到 ApplicationThread.scheduleCreateService,它会最终调用到 ActivityThread.handleCreateService
  5. ActivityThread.handleCreateService 中会首先通过反射构造 Service 对象,之后进行 ContextImpl 等等的创建,最后**调用 Service.attach 以及 Service.onCreate **从而完成 Service 的创建。
  6. sendServiceArgsLocked 中会调用到 ApplicationThread.scheduleServiceArgs 最终导致 ActivityThread.handleServiceArgs 的调用,它会调用 Service.onStartCommand 方法

bindService

  1. 通过 ContextImpl 调用,之后调用到 AMSbindService,它会最终调用 ActiveServices.bindServiceLocked 方法。
  2. 在这个方法中首先会调用 retrieveServiceLocked 方法通过 PMS 查询对应的 ServiceRecord
  3. 之后会调用到 bringUpServiceLocked 从而拉起 Service,后续步骤与 startService 类似,不过在 realStartServiceLocked 方法中会调用requestServiceBindingsLocked 方法从而开始绑定的流程。
  4. requestServiceBindingsLocked 中会调用到 ApplicationThread.scheduleBindService 方法,它最终会调用到 ActivityThread.handleBindService 方法,这个方法会调用 Service.onBind 并获取其返回的匿名 Binder。获取到 Binder 后会调用到 AMSpublishService 方法,它会调用到 ActiveServices.publishServiceLocked 方法,从而将匿名 Binder 传递到 SystemServer 进程。
  5. ActiveServices.publishServiceLocked 方法中,会将这个匿名 Binder 通过 LoadApk.InnerConnection 的 SystemServer 端代理对象传递到启动 Service 的进程,最终会调用到对应 ServiceConnection.onServiceConnected

匿名 Binder 的传递

可以看出,匿名 Binder 实际上是通过 SystemServer 进程请求 Service 运行进程调用 Service.onBind 获取到,之后将其传递给了 SystemServer 进程,SystemServer 进程又将其传递回了启动 Service 的进程从而实现该匿名 Binder 的传递。

参考资料

bindService启动过程分析

android 9.0 bindService绑定Servcie的过程分析

点赞

发表评论

电子邮件地址不会被公开。必填项已用 * 标注

%d 博主赞过: