Service跨进程启动流程源码探究

本文深入探讨了Android系统中跨进程启动Service的机制,详细分析了从客户端发起请求到目标进程创建Service实例的全过程,包括AMS的角色、Binder通信、主线程切换、Service实例创建及启动等关键环节。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

根据《Activity跨进程启动流程源码探究》我们可以清楚以下几点:
1)Context的通用实现是在ContextIml这个类中
2)Activity的启动过程需要借助ActivityManagerService(AMS)这个服务端来完成,其本质是借助于Binder通信。目标Activity的识别是通过ProcessRecord这个类存储的记录来完成的,如果首次启动进程,则通过提取Intent中携带进程信息完成启动。
3)Context作为客户端向AMS发起start请求,AMS持有IApplicationThread的实例完成最终的启动任务。
4)AMS通过H这个Handler切回了主线程。Application、Activity、ContextImpl等实例创建都在主线程中,那些耗时操作其实是在Binder线程完成的。
鉴于此,我们分析Service的启动过程从ContextImpl的startService方法开始。

1. 客户端发起启动service请求

ContextImpl中通过startService、startForegroundService、startServiceAsUser、startForegroundServiceAsUser四个方法启动服务,但是他们都把具体任务交给了startServiceCommon这个方法,下面给出startService的源码:

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

看一下startServiceCommon的核心代码吧,

    private ComponentName startServiceCommon(Intent service, boolean requireForeground,
            UserHandle user) {
        try {
            validateServiceIntent(service);
            service.prepareToLeaveProcess(this);
            ComponentName cn = ActivityManager.getService().startService(
                mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded(
                            getContentResolver()), requireForeground,
                            getOpPackageName(), user.getIdentifier());

跟启动Activity一样,它把任务交给了ActivityManager.getService(),也就是ActivityManagerService,AMS则是IActivityManager.Stub的具体实现,这么一来系统会单独开辟一个Binder线程完成服务的启动工作。
接着,我们看看AMS的启动情况,核心代码如下:

ComponentName res;
            try {
                res = mServices.startServiceLocked(caller, service,
                        resolvedType, callingPid, callingUid,
                        requireForeground, callingPackage, userId);
            }

它调用了mServices的startServiceLocked方法,mServices就是ActiveServices,startServiceLocked返回了组件名ComponentName,并未执行启动工作,service参数就是我们启动时传入的Intent。通过它可以拿到目标服务的记录ServiceRecord,核心代码如下:

    ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType,
            int callingPid, int callingUid, boolean fgRequired, String callingPackage, final int userId)
            throws TransactionTooLargeException {
        ......
        ServiceLookupResult res =
            retrieveServiceLocked(service, resolvedType, callingPackage,
                    callingPid, callingUid, userId, true, callerFg, false);
        if (res == null) {
            return null;
        }
        if (res.record == null) {
            return new ComponentName("!", res.permission != null ? res.permission : "private to package");
        }
        ServiceRecord r = res.record;
        ......
        ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting);
        return cmp;
    }

startServiceLocked通过调用retrieveServiceLocked方法获得服务记录信息存储在ServiceRecord的实例r中,r参数又传给了startServiceInnerLocked做进一步启动工作。
这里需要注意的是retrieveServiceLocked方法内部无法查询到目标进程的ServiceRecord的信息,因为我们假设目标进程还未启动。res.record是通过客户端源进程携带的模板进程信息封装的实例。
ServiceRecord实例
继续追踪会发现startServiceInnerLocked内部调用了bringUpServiceLocked方法,从字面意思就明白它是唤起Service的,该方法实现如下:

    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) {  //代码1-b-1
            sendServiceArgsLocked(r, execInFg, false);
            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); //代码1-b-2
            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.versionCode, mAm.mProcessStats);
                    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.
            }
        } else {
          ......
        }

        // Not running -- get it started, and enqueue this service record
        // to be executed when the app comes up.
        if (app == null && !permissionsReviewRequired) { //代码1-b-3
            if ((app=mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,
                    hostingType, r.name, false, isolated, false)) == null) {
                String msg = "Unable to launch app "
                        + r.appInfo.packageName + "/"
                        + r.appInfo.uid + " for service "
                        + r.intent.getIntent() + ": process is bad";
                Slog.w(TAG, msg);
                bringDownServiceLocked(r);
                return msg;
            }
            ...
        }

        if (!mPendingServices.contains(r)) {
            mPendingServices.add(r);
        }
        ...
        return null;
    }

由于我们分析的是目标进程未启动的开启服务流程,代码1-b-1处r.app返回的ProcessRecord实例和代码1-b-1返回的ProcessRecord实例都是空的,代码1-b-3的开启目标进程逻辑会被执行,它通过调用mAm.startProcessLocked方法执行开启进程任务,mAm就是AMS。procName、r.appInfo、r.name均取自于我们刚刚创建的ServiceRecord实例,其中r.appInfo存储了我们要启动的目标应用的所有信息,它是ApplicationInfo的实例。startProcessLocked连续调用2次其重载方法,第1次调用获取ProcessRecord实例,核心代码如下:

   final ProcessRecord startProcessLocked(String processName, ApplicationInfo info,
            boolean knownToBeDead, int intentFlags, String hostingType, ComponentName hostingName,
            boolean allowWhileBooting, boolean isolated, int isolatedUid, boolean keepIfLarge,
            String abiOverride, String entryPoint, String[] entryPointArgs, Runnable crashHandler) {
            ...
        ProcessRecord app;
        if (!isolated) {
            app = getProcessRecordLocked(processName, info.uid, keepIfLarge); // 代码1-start-1
            checkTime(startTime, "startProcess: after getProcessRecord");
            ...
        } else {
            // If this is an isolated process, it can't re-use an existing process.
            app = null;
        }
        ...
        if (app == null) {
            checkTime(startTime, "startProcess: creating new process record");
            app = newProcessRecordLocked(info, processName, isolated, isolatedUid);// 代码1-start-2
            if (app == null) {
                Slog.w(TAG, "Failed making new process record for "
                        + processName + "/" + info.uid + " isolated=" + isolated);
                return null;
            }
            app.crashHandler = crashHandler;
            checkTime(startTime, "startProcess: done creating new process record");
        } else {
            ...
        }
        ...
        startProcessLocked(  // 代码1-start-3
                app, hostingType, hostingNameStr, abiOverride, entryPoint, entryPointArgs);
        return (app.pid != 0) ? app : null;
    }

可见,该方法首先在代码1-start-1处调用getProcessRecordLocked方法查询正在运行的进程中是否有相关记录,进入该方法代码如下:

    final ProcessRecord getProcessRecordLocked(String processName, int uid, boolean keepIfLarge) {
        if (uid == SYSTEM_UID) {
            ...
        }
        ProcessRecord proc = mProcessNames.get(processName, uid);
        ...
        return proc;
    }

该方法就是通过进程名和用户ID从mProcessNames获取进程记录,mProcessNames的定义如下:

    /**
     * All of the applications we currently have running organized by name.
     * The keys are strings of the application package name (as
     * returned by the package manager), and the keys are ApplicationRecord
     * objects.
     */
    final ProcessMap<ProcessRecord> mProcessNames = new ProcessMap<ProcessRecord>();

所有正在运行的应用的进程记录都在这儿,由于我们的目标应用及其进程都还没启动,getProcessRecordLocked方法自然返回null。startProcessLocked方法执行1-start-2逻辑,调用newProcessRecordLocked方法创建了一个新的ProcessRecord实例。看一下该方法的实现逻辑:

    final ProcessRecord newProcessRecordLocked(ApplicationInfo info, String customProcess,
            boolean isolated, int isolatedUid) {
        String proc = customProcess != null ? customProcess : info.processName;
        BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
        
        int uid = info.uid;
        if (isolated) {
            ...
        }
        final ProcessRecord r = new ProcessRecord(stats, info, proc, uid);
        ...
        addProcessNameLocked(r);
        return r;
    }

其内部实现特别干脆,直接将ApplicationInfo信息和进程名传入ProcessRecord构造方法,new了一个ProcessRecord实例返回。
函数startProcessLocked方法接着执行代码1-start-3逻辑,再次调用自己的重载方法,ProcessRecord实例作为其第一个参数传入,然后执行Process.start方法开启目标进程,核心代码如下:

    private final void startProcessLocked(ProcessRecord app, String hostingType,
            String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs) {
        ......
        try {
            ......
            // Start the process.  It will either succeed and return a result containing
            // the PID of the new process, or else throw a RuntimeException.
            boolean isActivityProcess = (entryPoint == null);
            if (entryPoint == null) entryPoint = "android.app.ActivityThread";
            ProcessStartResult startResult;
            if (hostingType.equals("webview_service")) {
                ...
            } else {
                startResult = Process.start(entryPoint,
                        app.processName, uid, uid, gids, debugFlags, mountExternal,
                        app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
                        app.info.dataDir, invokeWith, entryPointArgs);
            }
            ...
        } catch (RuntimeException e) {
            Slog.e(TAG, "Failure starting process " + app.processName, e);
            ...
        }
    }

我们要开启的是进程不是WebView服务,自然会调用Process.start方法,注意:app就是我们传入的ProcessRecord参数,启动目标进程全靠它了。entryPoint就是目标进程的主线程ActivityThread,一旦目标进程开启,首先执行ActivityThread的main方法。在ActivityThread.main方法内部,创建了目标进程主线程的mainLooper、mainHandler并将具体任务交给了ActivityThread.attach方法,在attach方法内部又将任务交给了AMS的attachApplication方法,核心代码如下:

    private void attach(boolean system) {
        sCurrentActivityThread = this;
        mSystemThread = system;
        if (!system) {
            ...
            final IActivityManager mgr = ActivityManager.getService();
            try {
                mgr.attachApplication(mAppThread);
            } catch (RemoteException ex) {
                ...
            }
            // Watch for getting close to heap limit.
            BinderInternal.addGcWatcher(new Runnable() {
                @Override public void run() {
                    if (!mSomeActivitiesChanged) {
                        return;
                    }
                    Runtime runtime = Runtime.getRuntime();
                    long dalvikMax = runtime.maxMemory();
                    long dalvikUsed = runtime.totalMemory() - runtime.freeMemory();
                    if (dalvikUsed > ((3*dalvikMax)/4)) {
                        ...
                        try {
                            mgr.releaseSomeActivities(mAppThread);
                        } catch (RemoteException e) {
                            ...
                        }
                    }
                }
            });
        } else {
          ...
        }
        ......
    }

by the way,当我们申请的内存大于最大允许内存的75%时,就会触发系统的内存回收机制。接下来我们看看mgr.attachApplication方法做了什么,这里的mgr就是AMS实例。它的内部调用了AMS的attachApplicationLocked方法,并将当前进程的ApplicationThread实例传入。attachApplicationLocked的具体实现如下:

    private final boolean attachApplicationLocked(IApplicationThread thread,
            int pid) {

        // Find the application record that is being attached...  either via
        // the pid if we are running in multiple processes, or just pull the
        // next app record if we are emulating process with anonymous threads.
        ProcessRecord app;
        if (pid != MY_PID && pid >= 0) {
            synchronized (mPidsSelfLocked) {
                app = mPidsSelfLocked.get(pid); // 代码1-aal-1
            }
        } else {
            app = null;
        }
        ...
	try {
            ...
                                       
            // Check if this is a secondary process that should be incorporated into some
            // currently active instrumentation.  (Note we do this AFTER all of the profiling
            // stuff above because profiling can currently happen only in the primary
            // instrumentation process.)
            if (mActiveInstrumentation.size() > 0 && app.instr == null) { // 代码1-aal-2-1
                   for (int i = mActiveInstrumentation.size() - 1; i >= 0 && app.instr == null; i--) {
                    ActiveInstrumentation aInstr = mActiveInstrumentation.get(i);
                    if (!aInstr.mFinished && aInstr.mTargetInfo.uid == app.uid) {
                        if (aInstr.mTargetProcesses.length == 0) {
                            // This is the wildcard mode, where every process brought up for
                            // the target instrumentation should be included.
                            if (aInstr.mTargetInfo.packageName.equals(app.info.packageName)) {
                                app.instr = aInstr;
                                ...
                            }
                        } else { 
                            for (String proc : aInstr.mTargetProcesses) {
                                if (proc.equals(app.processName)) {
                                    app.instr = aInstr;
                                    ....
                                    break;
                                }
                            }
                        }
                    }
                }
            }
            ...
            if (app.instr != null) { // 代码1-aal-2-2
                thread.bindApplication(processName, appInfo, providers,
                        app.instr.mClass,
                        profilerInfo, app.instr.mArguments,
                        app.instr.mWatcher,
                        app.instr.mUiAutomationConnection, testMode,
                        mBinderTransactionTrackingEnabled, enableTrackAllocation,
                        isRestrictedBackupMode || !normalMode, app.persistent,
                        new Configuration(getGlobalConfiguration()), app.compat,
                        getCommonServicesLocked(app.isolated),
                        mCoreSettingsObserver.getCoreSettingsLocked(),
                        buildSerial);
            } else { // 代码1-aal-3
                thread.bindApplication(processName, appInfo, providers, null, profilerInfo,
                        null, null, null, testMode,
                        mBinderTransactionTrackingEnabled, enableTrackAllocation,
                        isRestrictedBackupMode || !normalMode, app.persistent,
                        new Configuration(getGlobalConfiguration()), app.compat,
                        getCommonServicesLocked(app.isolated),
                        mCoreSettingsObserver.getCoreSettingsLocked(),
                        buildSerial);
            }
            ...
        } catch (Exception e) {
            ...
            startProcessLocked(app, "bind fail", processName);
            return false;
        }
        // Find any services that should be running in this process...
        if (!badApp) {
            try {
                didSomething |= mServices.attachApplicationLocked(app, processName); // 代码1-aal-4
                ...
            } catch (Exception e) {
                ...
            }
        }
        ...
        return true;
    }

代码1-aal-1处的mPidsSelfLocked就是当前已经运行的目标应用中的所有进程信息,其定义如下:

    /**
     * All of the processes we currently have running organized by pid.
     * The keys are the pid running the application.
     *
     * <p>NOTE: This object is protected by its own lock, NOT the global
     * activity manager lock!
     */
    final SparseArray<ProcessRecord> mPidsSelfLocked = new SparseArray<ProcessRecord>();

可见它是一个SparseArray内部以pid为键值存储,由于进程已经启动,通过mPidsSelfLocked.get(pid)就可拿到对应的ProcessRecord记录信息。
由于目标进程的Instrumentation还未创建,代码1-aal-2-1和代码1-aal-2-2处的条件都不满足,代码1-aal-3处逻辑开始执行。thread.bindApplication方法会完成创建Instrumentation、ContextImpl、Application、ContentProvider的任务,详细请参考《ContentProvider注册、启动流程源码解析》
接着,代码1-aal-4逻辑被执行,mServices.attachApplicationLocked内部会调用一个叫做realStartServiceLocked方法,调用核心代码如下:

    boolean attachApplicationLocked(ProcessRecord proc, String processName)
            throws RemoteException {
        boolean didSomething = false;
        // Collect any services that are waiting for this process to come up.
        if (mPendingServices.size() > 0) {
            ServiceRecord sr = null;
            try {
                for (int i=0; i<mPendingServices.size(); i++) {
                    sr = mPendingServices.get(i);
                    if (proc != sr.isolatedProc && (proc.uid != sr.appInfo.uid
                            || !processName.equals(sr.processName))) {
                        continue;
                    }
                    ...
                    realStartServiceLocked(sr, proc, sr.createdFromFg);
                    didSomething = true;
                    ...
                }
            } catch (RemoteException e) {
                ....
            }
        }
        ......
        return didSomething;
    }

其中,mPendingServices是一个列表,存储了目标进程所有将要被启动的服务记录,其定义如下:

    /**
     * List of services that we have been asked to start,
     * but haven't yet been able to.  It is used to hold start requests
     * while waiting for their corresponding application thread to get
     * going.
     */
    final ArrayList<ServiceRecord> mPendingServices = new ArrayList<>();

我们根据processName和proc.uid拿到目标ServiceRecord赋值给sr,将sr和proc作为参数传给realStartServiceLocked完成真正的服务启动工作。其中proc是ProcessRecord(Full information about a particular process that is currently running. 译文:当前正在运行的进程的所有信息。它内部存储了自己的Activity集合、Service集合等)的实例,sr是ServiceRecord(A running application service.译文:一个正在运行应用服务)的实例。realStartServiceLocked方法的具体实现如下:

 private final void realStartServiceLocked(ServiceRecord r,
            ProcessRecord app, boolean execInFg) throws RemoteException {
        if (app.thread == null) {
            throw new RemoteException();
        }
        ...
        r.app = app;
        ...
        boolean created = false;
        try {
            ...
            app.thread.scheduleCreateService(r, r.serviceInfo,
                    mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
                    app.repProcState); // 1-0
            ...
            created = true;
        } catch (DeadObjectException e) {
            ...
        } finally {
            if (!created) {
            	...
            }
        }
        ...
        sendServiceArgsLocked(r, execInFg, true);  // 1-1
        ...
    }

其核心实现只有1-0和1-1两处,1-0处调用了app.thread.scheduleCreateService方法。这里的app.thread就是IApplicationThread,依赖这个引用调用目标进程主线程的scheduleCreateService接口创建服务实例。

2. 目标进程创建service实例

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

感兴趣的话,可以进入CreateServiceData看一下,你应该能学到些什么。

3. Service的创建任务

Service的创建任务通过H.CREATE_SERVICE这个消息切换给了主线程来完成。通过fn+option+F7可以在handleMessage内部找到该消息对应的处理方法handleCreateService:

	public void handleMessage(Message msg) {
		switch (msg.what) {
			case CREATE_SERVICE:
				handleCreateService((CreateServiceData)msg.obj);
				break;
			}
            ...
	}

   // handleCreateService实现
   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);
        // 3-0 通过ClassLoader创建Service实例
        Service service = null;
        try {
            java.lang.ClassLoader cl = packageInfo.getClassLoader();
            service = (Service) cl.loadClass(data.info.name).newInstance();
        } catch (Exception e) {
        	...
        }

        try {
            if (localLOGV) Slog.v(TAG, "Creating service " + data.info.name);
            // 3-1 通过createAppContext方法创建ContextImpl实例
            ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
            context.setOuterContext(service);

            // 3-2 通过makeApplication方法创建Application实例,内部会调用Application的onCreate方法,
            // mInstrumentation在刚刚的bindApplication方法中已经创建过
            Application app = packageInfo.makeApplication(false, mInstrumentation);
            // 3-3 通过attach方法将Service与Context关联起来
            service.attach(context, this, data.info.name, data.token, app,
                    ActivityManager.getService());
            // 3-4 调用Service的onCreate方法。
            service.onCreate();
            ...
        } catch (Exception e) {
            ...
        }
    }

在主线程中,依次执行如下步骤:
1)通过ClassLoader类加载器创建Service实例
2)通过createAppContext方法创建ContextImpl实例
3)通过makeApplication方法创建Application实例,内部会调用Application的onCreate方法
4)通过attach方法将Service与Context关联起来
5)调用Service的onCreate方法。

3. Service的onStartCommand任务

Service的启动周期,当然代码要执行到onStartCommand才能处于暂态,这时需要回到第1节源进程 客户端ActiveServices#realStartServiceLocked方法的1-1处,它调用了ActiveServices#sendServiceArgsLocked方法,该方法核心代码如下:

    private final void sendServiceArgsLocked(ServiceRecord r, boolean execInFg,
            boolean oomAdjusted) throws TransactionTooLargeException {
        final int N = r.pendingStarts.size();
        if (N == 0) {
            return;
        }
        ...
        try {
            r.app.thread.scheduleServiceArgs(r, slice);
        } catch (TransactionTooLargeException e) {
            ...
        } catch (RemoteException e) {
            // Remote process gone...  we'll let the normal cleanup take care of this.
            ...
        } catch (Exception e) {
            ...
        }
        ...
    }

它会首先检测是否有等待启动的服务,如果没有就返回。否则,就调用r.app.thread.scheduleServiceArgs方法并传入ServiceRecord信息。同样,这里的r.app.thread就是IApplicationThread的具体实现ActivityThread.ApplicationThread,看一下代码:

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

在IApplicationThread这个Binder线程中完成了初始化和切换主线程两个任务,搜索H.SERVICE_ARGS这条消息会找到handleMessage中的handleServiceArgs方法,该方法实现相对于handleCreateService简单了不少,如下:

private void handleServiceArgs(ServiceArgsData data) {
        Service s = mServices.get(data.token);
        if (s != null) {
            try {
                ...
                int res;
                if (!data.taskRemoved) {
                    res = s.onStartCommand(data.args, data.flags, data.startId);  //代码3-0
                } else {
                    ...
                }
                ...
            } catch (Exception e) {
                ...
            }
        }
    }

我们想看到的代码只有一行,代码3-0处的s.onStartCommand方法的调用。这样整个服务的启动工作就完成了,做一下总结吧~

4. Service的启动总结

首先,Context通过startService调用ContextImpl的startService方法,ContextImpl作为客户端,或者叫Binder代理向AMS(ActivityManagerService)发起start service的请求
接着,AMS这个服务端,或者叫做Binder.Stub存根的派生类,通过桥接的方式,先调用thread.bindApplication方法创建Instrumentation实例、App实例、安装ContentProvider等进行 模板进程 Application 初始化工作。
然后,AMS 继续通过目标进程的IApplicationThread引用执行createService任务,并借助于H在目标进程完成切回到主线程处理CREATE_SERVICE消息工作。该消息对应的handleCreateService方法依次完成如下任务:
4-1 获取Service实例创建的必备信息
4-2 创建ContextImpl实例
4-3 通过ClassLoader创建Service实例
4-4 通过LoadedApk的makeApplication方法,最终由classLoader创建Application实例。其内部还调用了instrumentation.callApplicationOnCreate()方法
4-5 通过Service的attach方法,将Service和ContextImpl关联起来,有一个叫mBase的Context实例其实就是ContextImpl。
4-6 调用 service.onCreate()方法,可见从源码上决定了Application的onCreate方法先于Service的onCreate方法执行。
一言以蔽之,就是创建service实例并调用onCreate方法。
最终,在这些工作完成后,源进程客户端调用了app.thread.scheduleServiceArgs方法,在ActivityThread.ApplicationThread这个Binder进程中,通过H.SERVICE_ARGS切换到主线程,该消息对应的handleServiceArgs被执行,在handleServiceArgs方法中完成Service#onStartCommand的调用任务。
这样服务就启动起来了。

诗云:

朝辞白帝彩云间,千里江陵一日还。
两岸猿声啼不住,轻舟已过万重山。


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值