Service启动流程分析

引言

Service的启动流程已经有许多前辈们写过,并且很多文章都写得很清楚、透彻。但是,纸上得来终觉浅,趁着不忙的时候,我也写一篇记录一下。

1. Context及其常用子类的关系

为了容易理解,我们首先要先了解一下Context及其常用子类的关系,我们可以用类图来描述一下:


Context及其常用子类的类图.png

造福一下有些可能忘记了UML类图的童鞋:
a. 带封闭空心三角箭头的有向实线表示泛化关系,即继承关系,箭头指向父类。
b. 带开放箭头的有向虚线表示依赖关系,箭头从使用者指向提供者。
c. 斜体表示抽象,斜体类名表示抽象类,斜体方法表示抽象方法。
d. 可见性修饰符:加号(+)表示public;减号(-)表示private;井号(#)表示protected;省略修饰符表示package。
更多UML类图知识可以参考:https://baike.baidu.com/item/%E7%B1%BB%E5%9B%BE/4670826?fr=aladdin

上面类图中的继承关系可以参考API:https://developer.android.google.cn/reference/android/content/ContextWrapper
来确定,依赖关系则需要结合源码,但很简单,基本上捋一遍就清楚了。

2. 调用堆栈的打印

2.1 打印方法

为了准确能准确的跟踪系统源码,我们需要知道的各个类的各个方法之间的调用顺序和逻辑。一般有三种方法:

  • 加Log
    因为系统代码庞大、而且逻辑复杂,所以这种方法工作量很大,并且有些时候容易跟错,Log是最基本的方法,但也是最笨的方法。

  • TraceView
    使用TraceView抓取一段时间的调用堆栈。这种方法有完整的函数调用栈,是一种比较好的方法,但是需要能确定相关方法的大概的调用时间,否则,调用栈很庞大,可能会很难找。

  • 抛异常
    抛出异常,打印函数调用栈。这种方法也比较好,而且比较灵活,可以加在任意位置。
    使用上也很简单,只要在怀疑的位置抛个异常,再catch该异常就可以了,为了使用方便我们可以把它封装成一个方法:
    StackTraceUtils.java:

    public static void printStackTraceByException() {
        try {
            throw new Exception("Just for print stack trace");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

然后就可以到处使用了。当然,如果觉得logcat日志中一堆System.err看了很烦,我们也可以将异常打印堆栈的代码稍微提取、封装一下:

    public static String getStackTrace() {
        StringBuilder builder = new StringBuilder();
        for (StackTraceElement e : Thread.currentThread().getStackTrace()) {
            builder.append(e.toString() + "\n");
        }
        return builder.toString();
    }

    public static void printStackTrace() {
        Log.d(TAG, getStackTrace());
    }

然后再用printStackTrace去打印调用栈。
了解了Context及其常用子类的关系和怎么打印函数调用栈,我们就可以来分析Service的启动流程了。

2.2 打印前的准备工作

我们先来做一下准备工作,写个demo创建三个Service:

  • 第一个用startService方法启动;
  • 第二个用bindService方法在与Activity的同一进程中启动;
  • 第三个用bindService方法在与Activity的不同进程中启动,即在AndroidManifest.xml中为该Service配置属性android:process=":remote_service"。

另外,我们还需要有一份android系统的源码,并且可以随时编译、调试看日志。

2021/04/23 更新
这里不再推荐通过加日志或者抛异常打印调用栈的方式来跟系统代码了,因为这样反复编译、push,效率比较低。如有条件,请将系统源码导入到Android Studio中(可参考:Android Studio导入系统源码),然后用userdebug/eng版本软件的样机USB连上电脑后,可以直接选择系统进程,在需要的位置打断点进行调试。这样跟代码的效率会更高。

2.3 实战打印调用堆栈

接下来我们以分析startService时的onCreate的流程举例。

2.3.1 StartService.java

为了了解onCreate的流程,我们直接在Service的onCreate方法中加个堆栈打印:

public class StartService extends Service {
    //省略了无关代码
    @Override
    public void onCreate() {
        super.onCreate();
        StackTraceUtils.printStackTraceByException();
    }
}

加完堆栈打印后我们直接在Activity中startService:
MainActivity.java:startService(new Intent(this, StartService.class));
然后我们查看logcat,我们会得到这样一段日志:

2020-09-11 19:53:54.669 5690-5690/com.qxt.servicelifecycle W/System.err: java.lang.Exception: Just for print stack trace
2020-09-11 19:53:54.669 5690-5690/com.qxt.servicelifecycle W/System.err:     at com.qxt.servicelifecycle.StackTraceUtils.printStackTraceByException(StackTraceUtils.java:22)
2020-09-11 19:53:54.669 5690-5690/com.qxt.servicelifecycle W/System.err:     at com.qxt.servicelifecycle.StartService.onCreate(StartService.java:21)
2020-09-11 19:53:54.669 5690-5690/com.qxt.servicelifecycle W/System.err:     at android.app.ActivityThread.handleCreateService(ActivityThread.java:3573)
2020-09-11 19:53:54.669 5690-5690/com.qxt.servicelifecycle W/System.err:     at android.app.ActivityThread.access$1400(ActivityThread.java:206)
2020-09-11 19:53:54.670 5690-5690/com.qxt.servicelifecycle W/System.err:     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1704)
2020-09-11 19:53:54.670 5690-5690/com.qxt.servicelifecycle W/System.err:     at android.os.Handler.dispatchMessage(Handler.java:106)
2020-09-11 19:53:54.670 5690-5690/com.qxt.servicelifecycle W/System.err:     at android.os.Looper.loop(Looper.java:193)
2020-09-11 19:53:54.670 5690-5690/com.qxt.servicelifecycle W/System.err:     at android.app.ActivityThread.main(ActivityThread.java:6718)
2020-09-11 19:53:54.670 5690-5690/com.qxt.servicelifecycle W/System.err:     at java.lang.reflect.Method.invoke(Native Method)
2020-09-11 19:53:54.670 5690-5690/com.qxt.servicelifecycle W/System.err:     at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
2020-09-11 19:53:54.671 5690-5690/com.qxt.servicelifecycle W/System.err:     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:911)

如果调试样机的软件和源码是对应的,即软件就是用该源码编译出来的。那就非常简单了,直接看堆栈中的文件名和行号,都是可以准确对应的。不过即使对应不上,我们只要结合源码稍微分析一下,这个堆栈也提供了足够多的信息了。
a. 我们通过堆栈信息,可以直接定位到ActivityThread.handleCreateService方法。
b. 再往上跟,就可以定位到ActivityThread$H.handleMessage方法,msg是CREATE_SERVICE。
c. 再往上跟,就定位到了ActivityThread$ApplicationThread$scheduleCreateService方法。到这里看到ApplicationThread的定义:private class ApplicationThread extends IApplicationThread.Stub,我们基本可以猜测它是通过binder被调用的。为了验证我们的猜想,我们在scheduleCreateService中再加一个堆栈打印。

2.3.2 ActivityThread.java
public final class ActivityThread extends ClientTransactionHandler {
    private class ApplicationThread extends IApplicationThread.Stub {

        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);
            try {
                throw new Exception("Just for print stack trace");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

重新编译源码,push frameworks.jar,杀掉demo进程,再次启动一下Service,除了上面的日志,我们还会得到这样一段日志:

2020-09-11 19:53:54.649 5690-5781/com.qxt.servicelifecycle W/System.err: java.lang.Exception: Just for print stack trace
2020-09-11 19:53:54.649 5690-5781/com.qxt.servicelifecycle W/System.err:     at android.app.ActivityThread$ApplicationThread.scheduleCreateService(ActivityThread.java:831)
2020-09-11 19:53:54.650 5690-5781/com.qxt.servicelifecycle W/System.err:     at android.app.IApplicationThread$Stub.onTransact(IApplicationThread.java:118)
2020-09-11 19:53:54.650 5690-5781/com.qxt.servicelifecycle W/System.err:     at android.os.Binder.execTransact(Binder.java:731)

可以确定了,它确实是通过binder被调用的。跨进程的时候,打印调用栈就无能为力了。所以我们只能去源码里面搜一搜了:

frameworks/base/services/core/java/com/android/server/am/ActiveServices.java:2494:            app.thread.scheduleCreateService(r, r.serviceInfo,
frameworks/base/core/java/android/app/ActivityThread.java:821:        public final void scheduleCreateService(IBinder token,
frameworks/base/core/java/android/app/IApplicationThread.aidl:60:    void scheduleCreateService(IBinder token, in ServiceInfo info,
frameworks/base/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java:393:        public void scheduleCreateService(IBinder iBinder, ServiceInfo serviceInfo,

运气还不错,两处函数定义,一处测试代码,可以直接确定是在ActiveServices中通过binder跨进程调用scheduleCreateService的。接下来故技重施,继续打印调用栈。

2.3.3 ActiveServices.java
    private final void realStartServiceLocked(ServiceRecord r,
            ProcessRecord app, boolean execInFg) throws RemoteException {

            //......省略了部分无关代码
            app.thread.scheduleCreateService(r, r.serviceInfo,
                    mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
                    app.repProcState);
            r.postNotification();
            created = true;
            try {
                throw new Exception("Just for print stack trace");
            } catch (Exception e) {
                e.printStackTrace();
            }
            //......省略了部分无关代码
    }

重新编译源码,push frameworks.jar,杀掉demo进程,再次启动一下Service,除了上面的日志,我们还会得到这样一段日志:

2020-09-11 19:53:54.646 892-11375/system_process W/System.err: java.lang.Exception: Just for print stack trace
2020-09-11 19:53:54.647 892-11375/system_process W/System.err:     at com.android.server.am.ActiveServices.realStartServiceLocked(ActiveServices.java:2500)
2020-09-11 19:53:54.647 892-11375/system_process W/System.err:     at com.android.server.am.ActiveServices.bringUpServiceLocked(ActiveServices.java:2365)
2020-09-11 19:53:54.647 892-11375/system_process W/System.err:     at com.android.server.am.ActiveServices.startServiceInnerLocked(ActiveServices.java:675)
2020-09-11 19:53:54.647 892-11375/system_process W/System.err:     at com.android.server.am.ActiveServices.startServiceLocked(ActiveServices.java:617)
2020-09-11 19:53:54.647 892-11375/system_process W/System.err:     at com.android.server.am.ActivityManagerService.startService(ActivityManagerService.java:20584)
2020-09-11 19:53:54.647 892-11375/system_process W/System.err:     at android.app.IActivityManager$Stub.onTransact$startService$(IActivityManager.java:10247)
2020-09-11 19:53:54.647 892-11375/system_process W/System.err:     at android.app.IActivityManager$Stub.onTransact(IActivityManager.java:429)
2020-09-11 19:53:54.647 892-11375/system_process W/System.err:     at com.android.server.am.ActivityManagerService.onTransact(ActivityManagerService.java:3350)
2020-09-11 19:53:54.647 892-11375/system_process W/System.err:     at android.os.Binder.execTransact(Binder.java:731)

从日志可以看到,已经可以直接定位到ActivityManagerService.startService方法了,并且它还是通过binder被调用的。只能继续搜一搜源码了,frameworks代码中startService的地方很多,但跨进程binder调用ActivityManagerService.startService的地方只有这一处:

public class ContextImpl extends Context {
    private ComponentName startServiceCommon(Intent service, boolean requireForeground,
            UserHandle user) {
            //......省略了部分无关代码
            ComponentName cn = ActivityManager.getService().startService(
                mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded(
                            getContentResolver()), requireForeground,
                            getOpPackageName(), user.getIdentifier());
    
            //......省略了部分无关代码
}

到这里,还可以继续打印堆栈一直反推到ContextImpl.startService,再到ContextWrapper.startService,但这个调用很简单,结合源码一眼就可以看出来,就没必要再打印调用栈了。
最后,我们按顺序来总结一下onCreate的流程:
ContextWrapper.startService -> ContextImpl.startService -> ContextImpl.startServiceCommon -> ActivityManagerService.startService -> ActiveServices.startServiceLocked -> ActiveServices.startServiceInnerLocked ->
ActiveServices.bringUpServiceLocked -> ActiveServices.realStartServiceLocked -> ActivityThread$ApplicationThread.scheduleCreateService -> ActivityThread$H.handleMessage -> ActivityThread.handleCreateService -> StartService.onCreate
这就是一个完整的onCreate的流程。
接下来章节中的时序图也是基于这种方法确定调用顺序来画的。

3. startService

3.1 startService时序图

startService时序图.png

3.2 startService源码分析

ContextWrapper.java:

public class ContextWrapper extends Context {
    @UnsupportedAppUsage
    Context mBase;//注:如第1节类图所示,mBase是实际上是ContextImpl类的实例。

    public ContextWrapper(Context base) {
        mBase = base;
    }

    /**
     * Set the base context for this ContextWrapper.  All calls will then be
     * delegated to the base context.  Throws
     * IllegalStateException if a base context has already been set.
     * 
     * @param base The new base context for this wrapper.
     */
    protected void attachBaseContext(Context base) {
        if (mBase != null) {
            throw new IllegalStateException("Base context already set");
        }
        mBase = base;
    }

    //......省略了部分无关代码

    @Override
    public ComponentName startService(Intent service) {
        return mBase.startService(service);
    }
}

ContextImpl.java:

public class ContextImpl extends Context {

    @Override
    public ComponentName startService(Intent service) {
        warnIfCallingFromSystemProcess();
        return startServiceCommon(service, false, mUser);
    }
    
    //......省略了部分无关代码
    
    private ComponentName startServiceCommon(Intent service, boolean requireForeground,
            UserHandle user) {
        try {
            validateServiceIntent(service);
            service.prepareToLeaveProcess(this);
            //注:通过binder调用ActivityManagerService的startService方法
            ComponentName cn = ActivityManager.getService().startService(
                mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded(
                            getContentResolver()), requireForeground,
                            getOpPackageName(), user.getIdentifier());
            if (cn != null) {
                if (cn.getPackageName().equals("!")) {
                    throw new SecurityException(
                            "Not allowed to start service " + service
                            + " without permission " + cn.getClassName());
                } else if (cn.getPackageName().equals("!!")) {
                    throw new SecurityException(
                            "Unable to start service " + service
                            + ": " + cn.getClassName());
                } else if (cn.getPackageName().equals("?")) {
                    throw new IllegalStateException(
                            "Not allowed to start service " + service + ": " + cn.getClassName());
                }
            }
            return cn;
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }
    
    //......省略了部分无关代码
}

ActivityManagerService.java:

public class ActivityManagerService extends IActivityManager.Stub
        implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
    final ActiveServices mServices;

    //......省略了部分无关代码

    @Override
    public ComponentName startService(IApplicationThread caller, Intent service,
            String resolvedType, boolean requireForeground, String callingPackage, int userId)
            throws TransactionTooLargeException {
        enforceNotIsolatedCaller("startService");
        // Refuse possible leaked file descriptors
        if (service != null && service.hasFileDescriptors() == true) {
            throw new IllegalArgumentException("File descriptors passed in Intent");
        }

        if (callingPackage == null) {
            throw new IllegalArgumentException("callingPackage cannot be null");
        }

        if (DEBUG_SERVICE) Slog.v(TAG_SERVICE,
                "*** startService: " + service + " type=" + resolvedType + " fg=" + requireForeground);
        synchronized(this) {
            final int callingPid = Binder.getCallingPid();
            final int callingUid = Binder.getCallingUid();
            final long origId = Binder.clearCallingIdentity();
            ComponentName res;
            try {
                //注:调用ActiveServices.startServiceLocked
                res = mServices.startServiceLocked(caller, service,
                        resolvedType, callingPid, callingUid,
                        requireForeground, callingPackage, userId);
            } finally {
                Binder.restoreCallingIdentity(origId);
            }
            return res;
        }
    }

    //......省略了部分无关代码
}

ActiveServices.java:

public final class ActiveServices {
    ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType,
            int callingPid, int callingUid, boolean fgRequired, String callingPackage, final int userId)
            throws TransactionTooLargeException {

        //......省略了部分无关代码
        ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting);
        return cmp;
    }
    
    ComponentName startServiceInnerLocked(ServiceMap smap, Intent service, ServiceRecord r,
            boolean callerFg, boolean addToStarting) throws TransactionTooLargeException {
        //......省略了部分无关代码

        String error = bringUpServiceLocked(r, service.getFlags(), callerFg, false, false);
        if (error != null) {
            return new ComponentName("!!", error);
        }

        //......省略了部分无关代码

        return r.name;
    }
    
    private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,
            boolean whileRestarting, boolean permissionsReviewRequired)
            throws TransactionTooLargeException {
        //Slog.i(TAG, "Bring up service:");
        //r.dump("  ");

        if (r.app != null && r.app.thread != null) {
            //注:已经创建过了,调用sendServiceArgsLocked走onStartCommand流程
            sendServiceArgsLocked(r, execInFg, false);
            return null;
        }

        if (!whileRestarting && mRestartingServices.contains(r)) {
            // If waiting for a restart, then do nothing.
            return null;
        }

        //......省略了部分无关代码

        final boolean isolated = (r.serviceInfo.flags&ServiceInfo.FLAG_ISOLATED_PROCESS) != 0;
        final String procName = r.processName;
        String hostingType = "service";
        ProcessRecord app;

        if (!isolated) {
            app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false);
            if (DEBUG_MU) Slog.v(TAG_MU, "bringUpServiceLocked: appInfo.uid=" + r.appInfo.uid
                        + " app=" + app);
            if (app != null && app.thread != null) {
                try {
                    app.addPackage(r.appInfo.packageName, r.appInfo.longVersionCode, mAm.mProcessStats);
                    //注:调用realStartServiceLocked走onCreate -> onStartCommand流程
                    realStartServiceLocked(r, app, execInFg);
                    return null;
                } catch (TransactionTooLargeException e) {
                    throw e;
                } catch (RemoteException e) {
                    Slog.w(TAG, "Exception when starting service " + r.shortName, e);
                }

                // If a dead object exception was thrown -- fall through to
                // restart the application.
            }
        }
        //......省略了部分无关代码
        return null;
    }
    
    private final void realStartServiceLocked(ServiceRecord r,
            ProcessRecord app, boolean execInFg) throws RemoteException {

            //......省略了部分无关代码
            //注:调用ActivityThread.scheduleCreateService方法,通知ActivityThread去创建Service实例以及回调onCreate方法
            app.thread.scheduleCreateService(r, r.serviceInfo,
                    mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
                    app.repProcState);
            r.postNotification();
            created = true;
            //......省略了部分无关代码

        // If the service is in the started state, and there are no
        // pending arguments, then fake up one so its onStartCommand() will
        // be called.
        if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
            r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),
                    null, null, 0));
        }

        //注:调用sendServiceArgsLocked方法,再调用ActivityThread.scheduleServiceArgs回调onStartCommand方法
        sendServiceArgsLocked(r, execInFg, true);
        //......省略了部分无关代码
    }
    
    private final void sendServiceArgsLocked(ServiceRecord r, boolean execInFg,
            boolean oomAdjusted) throws TransactionTooLargeException {
        //......省略了部分无关代码

        ParceledListSlice<ServiceStartArgs> slice = new ParceledListSlice<>(args);
        slice.setInlineCountLimit(4);
        Exception caughtException = null;
        try {
            //注:调用ActivityThread.scheduleServiceArgs回调onStartCommand方法
            r.app.thread.scheduleServiceArgs(r, slice);
        } catch (TransactionTooLargeException e) {
            if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Transaction too large for " + args.size()
                    + " args, first: " + args.get(0).args);
            Slog.w(TAG, "Failed delivering service starts", e);
            caughtException = e;
        } catch (RemoteException e) {
            // Remote process gone...  we'll let the normal cleanup take care of this.
            if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Crashed while sending args: " + r);
            Slog.w(TAG, "Failed delivering service starts", e);
            caughtException = e;
        } catch (Exception e) {
            Slog.w(TAG, "Unexpected exception", e);
            caughtException = e;
        }

        //......省略了部分无关代码
    }
}

ActivityThread.java:

public final class ActivityThread extends ClientTransactionHandler {
    private class ApplicationThread extends IApplicationThread.Stub {

        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);
        }

        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);
            }
        }
    }
    
    class H extends Handler {
        //......省略了部分无关代码
        public static final int CREATE_SERVICE          = 114;
        public static final int SERVICE_ARGS            = 115;
        public static final int STOP_SERVICE            = 116;
        public static final int BIND_SERVICE            = 121;
        public static final int UNBIND_SERVICE          = 122;
        //......省略了部分无关代码
        
        public void handleMessage(Message msg) {
            if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
            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;

                //......省略了部分无关代码

                case SERVICE_ARGS:
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, ("serviceStart: " + String.valueOf(msg.obj)));
                    handleServiceArgs((ServiceArgsData)msg.obj);
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                    break;
                //......省略了部分无关代码
            }
            //......省略了部分无关代码
        }
    }
    
    private void handleCreateService(CreateServiceData data) {
        // If we are getting ready to gc after going to the background, well
        // we are back active so skip it.
        unscheduleGcIdler();

        LoadedApk packageInfo = getPackageInfoNoCheck(
                data.info.applicationInfo, data.compatInfo);
        Service service = null;
        try {
            //注:通过AppComponentFactory加载并实例化Service
            java.lang.ClassLoader cl = packageInfo.getClassLoader();
            service = packageInfo.getAppFactory()
                    .instantiateService(cl, data.info.name, data.intent);
        } catch (Exception e) {
            if (!mInstrumentation.onException(service, e)) {
                throw new RuntimeException(
                    "Unable to instantiate service " + data.info.name
                    + ": " + e.toString(), e);
            }
        }

        try {
            if (localLOGV) Slog.v(TAG, "Creating service " + data.info.name);

            ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
            context.setOuterContext(service);

            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);
            try {
                ActivityManager.getService().serviceDoneExecuting(
                        data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
        } catch (Exception e) {
            if (!mInstrumentation.onException(service, e)) {
                throw new RuntimeException(
                    "Unable to create service " + data.info.name
                    + ": " + e.toString(), e);
            }
        }
    }

    private void handleServiceArgs(ServiceArgsData data) {
        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();

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

AppComponentFactory.java:

public class AppComponentFactory {
    public @NonNull Service instantiateService(@NonNull ClassLoader cl,
            @NonNull String className, @Nullable Intent intent)
            throws InstantiationException, IllegalAccessException, ClassNotFoundException {
        //注:加载Service类及创建实例
        return (Service) cl.loadClass(className).newInstance();
    }
}

4. 同进程bindService

4.1 同进程bindService时序图

bindService时序图.png

4.2 同进程bindService源码分析

ContextWrapper.java:

public class ContextWrapper extends Context {
    @UnsupportedAppUsage
    Context mBase;//如第1节类图所述,mBase是实际上是ContextImpl类的实例。

    public ContextWrapper(Context base) {
        mBase = base;
    }

    /**
     * Set the base context for this ContextWrapper.  All calls will then be
     * delegated to the base context.  Throws
     * IllegalStateException if a base context has already been set.
     * 
     * @param base The new base context for this wrapper.
     */
    protected void attachBaseContext(Context base) {
        if (mBase != null) {
            throw new IllegalStateException("Base context already set");
        }
        mBase = base;
    }

    //......省略了部分无关代码
    
    @Override
    public boolean bindService(Intent service, ServiceConnection conn,
            int flags) {
        return mBase.bindService(service, conn, flags);
    }
}

ContextImpl.java:

public class ContextImpl extends Context {
    //......省略了部分无关代码
    @Override
    public boolean bindService(Intent service, ServiceConnection conn,
            int flags) {
        warnIfCallingFromSystemProcess();
        return bindServiceCommon(service, conn, flags, mMainThread.getHandler(), getUser());
    }

    //......省略了部分无关代码

    private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags, Handler
            handler, UserHandle user) {
            //......省略了部分无关代码
            //通过binder调用ActivityManagerService的bindService方法
            int res = ActivityManager.getService().bindService(
                mMainThread.getApplicationThread(), getActivityToken(), service,
                service.resolveTypeIfNeeded(getContentResolver()),
                sd, flags, getOpPackageName(), user.getIdentifier());
            if (res < 0) {
                throw new SecurityException(
                        "Not allowed to bind to service " + service);
            }
            //......省略了部分无关代码
}

ActivityManagerService.java:

public class ActivityManagerService extends IActivityManager.Stub
        implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
    final ActiveServices mServices;

    //......省略了部分无关代码

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

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

        if (callingPackage == null) {
            throw new IllegalArgumentException("callingPackage cannot be null");
        }

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

    //......省略了部分无关代码
}

ActiveServices.java

public final class ActiveServices {
    int bindServiceLocked(IApplicationThread caller, IBinder token, Intent service,
            String resolvedType, final IServiceConnection connection, int flags,
            String callingPackage, final int userId) throws TransactionTooLargeException {

            //......省略了部分无关代码
            //注:仅bindServiceLocked执行,更新ServiceRecord的bindings
            AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);

            //......省略了部分无关代码

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

            //......省略了部分无关代码
    }
    
    private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,
            boolean whileRestarting, boolean permissionsReviewRequired)
            throws TransactionTooLargeException {
        //......省略了部分无关代码

        final boolean isolated = (r.serviceInfo.flags&ServiceInfo.FLAG_ISOLATED_PROCESS) != 0;
        final String procName = r.processName;
        String hostingType = "service";
        ProcessRecord app;

        if (!isolated) {
            app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false);
            if (DEBUG_MU) Slog.v(TAG_MU, "bringUpServiceLocked: appInfo.uid=" + r.appInfo.uid
                        + " app=" + app);
            if (app != null && app.thread != null) {
                try {
                    app.addPackage(r.appInfo.packageName, r.appInfo.longVersionCode, mAm.mProcessStats);
                    //注: 调用realStartServiceLocked走onCreate -> onBind流程
                    realStartServiceLocked(r, app, execInFg);
                    return null;
                } catch (TransactionTooLargeException e) {
                    throw e;
                } catch (RemoteException e) {
                    Slog.w(TAG, "Exception when starting service " + r.shortName, e);
                }

                // If a dead object exception was thrown -- fall through to
                // restart the application.
            }
        }

        //......省略了部分无关代码

        return null;
    }
    
    private final void realStartServiceLocked(ServiceRecord r,
            ProcessRecord app, boolean execInFg) throws RemoteException {

            //......省略了部分无关代码
            //注:调用ActivityThread.scheduleCreateService方法,通知ActivityThread去创建Service实例以及回调onCreate方法
            app.thread.scheduleCreateService(r, r.serviceInfo,
                    mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
                    app.repProcState);
            

        //注:调用requestServiceBindingsLocked
        requestServiceBindingsLocked(r, execInFg);
        //......省略了部分无关代码
    }
    
    private final void requestServiceBindingsLocked(ServiceRecord r, boolean execInFg)
            throws TransactionTooLargeException {
        //注: 只有bindService的ServiceRecord的bindings中有Binder实例,即只有bindService才会执行requestServiceBindingLocked方法,最终回调Service的onBind方法。
        for (int i=r.bindings.size()-1; i>=0; i--) {
            IntentBindRecord ibr = r.bindings.valueAt(i);
            if (!requestServiceBindingLocked(r, ibr, execInFg, false)) {
                break;
            }
        }
    }

    private final boolean requestServiceBindingLocked(ServiceRecord r, IntentBindRecord i,
            boolean execInFg, boolean rebind) throws TransactionTooLargeException {
                //......省略了部分无关代码
                r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind,
                        r.app.repProcState);
                if (!rebind) {
                    i.requested = true;
                }
                i.hasBound = true;
                i.doRebind = false;
                //......省略了部分无关代码
    }    
}

ActivityThread.java

public final class ActivityThread extends ClientTransactionHandler {
    private class ApplicationThread extends IApplicationThread.Stub {

        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;
        }

        public final void scheduleBindService(IBinder token, Intent intent,
                boolean rebind, int processState) {
            updateProcessState(processState, false);
            BindServiceData s = new BindServiceData();
            s.token = token;
            s.intent = intent;
            s.rebind = rebind;

            if (DEBUG_SERVICE)
                Slog.v(TAG, "scheduleBindService token=" + token + " intent=" + intent + " uid="
                        + Binder.getCallingUid() + " pid=" + Binder.getCallingPid());
            sendMessage(H.BIND_SERVICE, s);
        }
    }
    
    class H extends Handler {
        public static final int CREATE_SERVICE          = 114;
        public static final int BIND_SERVICE            = 121;
        
        public void handleMessage(Message msg) {
            if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
            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;
                case BIND_SERVICE:
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceBind");
                    handleBindService((BindServiceData)msg.obj);
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                    break;
                //......省略了部分无关代码
            }
        }
    }
    
    
    private void handleCreateService(CreateServiceData data) {
        // If we are getting ready to gc after going to the background, well
        // we are back active so skip it.
        unscheduleGcIdler();

        LoadedApk packageInfo = getPackageInfoNoCheck(
                data.info.applicationInfo, data.compatInfo);
        Service service = null;
        try {
            //通过AppComponentFactory加载并实例化Service
            java.lang.ClassLoader cl = packageInfo.getClassLoader();
            service = packageInfo.getAppFactory()
                    .instantiateService(cl, data.info.name, data.intent);
        } catch (Exception e) {
            if (!mInstrumentation.onException(service, e)) {
                throw new RuntimeException(
                    "Unable to instantiate service " + data.info.name
                    + ": " + e.toString(), e);
            }
        }

        try {
            if (localLOGV) Slog.v(TAG, "Creating service " + data.info.name);

            ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
            context.setOuterContext(service);

            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);
            try {
                ActivityManager.getService().serviceDoneExecuting(
                        data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
        } catch (Exception e) {
            if (!mInstrumentation.onException(service, e)) {
                throw new RuntimeException(
                    "Unable to create service " + data.info.name
                    + ": " + e.toString(), e);
            }
        }
    }

    private void handleBindService(BindServiceData data) {
        Service s = mServices.get(data.token);
        if (DEBUG_SERVICE)
            Slog.v(TAG, "handleBindService s=" + s + " rebind=" + data.rebind);
        if (s != null) {
            try {
                data.intent.setExtrasClassLoader(s.getClassLoader());
                data.intent.prepareToEnterProcess();
                try {
                    if (!data.rebind) {
                        //注:回调Service的onBind方法
                        IBinder binder = s.onBind(data.intent);
                        ActivityManager.getService().publishService(
                                data.token, data.intent, binder);
                    } else {
                        //注:回调Service的onRebind方法
                        s.onRebind(data.intent);
                        ActivityManager.getService().serviceDoneExecuting(
                                data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
                    }
                    ensureJitEnabled();
                } catch (RemoteException ex) {
                    throw ex.rethrowFromSystemServer();
                }
            } catch (Exception e) {
                if (!mInstrumentation.onException(s, e)) {
                    throw new RuntimeException(
                            "Unable to bind to service " + s
                            + " with " + data.intent + ": " + e.toString(), e);
                }
            }
        }
    }
}

AppComponentFactory.java:

public class AppComponentFactory {
    public @NonNull Service instantiateService(@NonNull ClassLoader cl,
            @NonNull String className, @Nullable Intent intent)
            throws InstantiationException, IllegalAccessException, ClassNotFoundException {
        return (Service) cl.loadClass(className).newInstance();
    }
}

可以看到,同一进程bindService和startService onCreate流程都基本一致,区别只是onStartCommand和onBind。

5. 不同进程bindService

5.1 不同进程bindService时序图

bind remote service时序图.png

5.2 不同进程bindService源码分析

bindService启动的Service在不同进程时:
a. ContextWrapper.bindService ->ContextImpl.bindService -> ContextImpl.bindServiceCommon ->
ActivityManagerService.bindService -> ActiveServices.bindServiceLocked -> ActiveServices.bringUpServiceLocked 前面这部分的流程与同进程bindService的流程是一致的。

b. 但在ActiveServices.bringUpServiceLocked方法中会调用ActivityManagerService.startProcess启动一个新的进程。然后system_process进程通过socket通信告知zygote进程fork新的APP进程,创建新的APP进程时会执行ActivityThread的main方法。接着的具体流程为:
ActivityThread.main -> ActivityThread.attach -> ActivityManagerService.attachApplication -> ActivityManagerService.attachApplicationLocked -> ActiveServices.attachApplicationLocked -> ActiveServices.realStartServiceLocked

c. 自ActiveServices.realStartServiceLocked之后的流程与同进程bindService的流程一致。

6. 本文参考

https://www.jianshu.com/p/e65cfcbdd11e
https://blog.csdn.net/gs344937933/article/details/90121485
感谢两位原作者的辛勤付出。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,377评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,390评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,967评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,344评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,441评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,492评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,497评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,274评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,732评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,008评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,184评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,837评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,520评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,156评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,407评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,056评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,074评论 2 352