Service启动流程

一 概述

Service 的启动流程还是比较简单的,不像 Activity 那么复杂,相关联的类和方法也少了很多,不像 Activity 启动流程里面走着走着就会迷失方向,在之前两篇文章我们主要分析了 Activity 的启动流程,今天我们主要来探索 Service 的启动过程。

Service 是 Android 四大组件,地位仅次于 Activity,Activity 位于前台向用户展示界面;Service 位于后台不可见,但是它承担了大部分的的数据处理工作,主要为其他组件提供后台服务,监控其他组件的运行状态。下面我们来具体分析。

分析的系统源码为 android 12 。

时序图

时序图中最后一个类为抽象类Service不是ActivityThread

 涉及代码:

frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
frameworks/base/services/core/java/com/android/server/am/ActiveServices.java
frameworks/base/services/core/java/com/android/server/am/ProcessRecord.java
frameworks/base/services/core/java/com/android/server/am/ServiceRecord.java

frameworks/base/core/java/android/app/ContextImpl.java
frameworks/base/core/java/android/app/ActivityThread.java
frameworks/base/core/java/android/app/Service.java

二 APP发起启动请求

2.1 ContextImpl.startService

@Override
public ComponentName startService(Intent service) {
    warnIfCallingFromSystemProcess();// 系统进程启动 service 的话,打印 log
    // 第二个参数为 requireForeground,默认为 false 表示启动非前台服务,
    // 区别于 startForegroundService
    return startServiceCommon(service, false, mUser);
}

@Override
public ComponentName startForegroundService(Intent service) {
     warnIfCallingFromSystemProcess();
     return startServiceCommon(service, true, mUser);
}
 
private ComponentName startServiceCommon(Intent service,
        boolean requireForeground, UserHandle user) {
    validateServiceIntent(service);// 对 Intent 的属性进行检查和准备
    service.prepareToLeaveProcess(this);
    // Binder 跨进程调用到 AMS
    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;
}
  • 需要注意的是 startService 和 startForegroundService 差别是入参 requireForeground 的值,其他代码逻辑完全一样。
  • 默认情况下目标 Service 会以后台服务的方式进行启动。与前台服务相比,后台服务不会在下拉通知栏显示通知,同时优先级较低,当系统出现内存不足情况时容易被回收。
  • validateServiceIntent() 对参数 Intent 进行合法性检查,确保其中与 Service 启动的相关属性值不为 null。此外,Android 5.0 后强制要求 Service 必须通过显式 Intent 启动,否则会直接抛出异常
  • 当由于权限、安全性等问题导致 Service 无法正常启动时,返回值 cn 的成员变量 mPackage 会被设置为 “!”、“?” 等特殊值,此时应用进程会进行处理并抛出对应的异常。

三 AMS处理启动请求

3.1 ActivityManagerService.startService

frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

@Override
public ComponentName startService(IApplicationThread caller, Intent service,
        String resolvedType, boolean requireForeground, String callingPackage,
                int userId) throws TransactionTooLargeException {
    enforceNotIsolatedCaller("startService");
    synchronized(this) {
        final int callingPid = Binder.getCallingPid();
        final int callingUid = Binder.getCallingUid();
        final long origId = Binder.clearCallingIdentity();
        ComponentName res;
        try {
            res = mServices.startServiceLocked(caller, service,
                    resolvedType, callingPid, callingUid,
                    requireForeground, callingPackage, userId);
        } finally {
            Binder.restoreCallingIdentity(origId);
        }
        return res;
    }
}

startService() 获取客户端进程的 callingPid 与 callingUid,然后将它们连同其它参数传递给 ActiveServices 对象的 startServiceLocked() 进行处理。

  • ActivityManagerService 把 Service 的所有事务都交给 ActiveServices 处理。

3.2 ActiveServices.startServiceLocked

frameworks/base/services/core/java/com/android/server/am/ActiveServices.java

ComponentName startServiceLocked(IApplicationThread caller, Intent service,
		String resolvedType, int callingPid, int callingUid, boolean fgRequired, 
		String callingPackage, final int userId)
        throws TransactionTooLargeException {
	// 倒数第二个参数是 allowBackgroundActivityStarts,默认
	// 为 false, 表示不允许后台 Activity 启动 Service
	return startServiceLocked(caller, service, resolvedType, callingPid, callingUid, 
	fgRequired, callingPackage, callingFeatureId, userId, false, null);
}

继续调用 startServiceLocked,倒数第二个参数 allowBackgroundActivityStarts,默认为 false,表示不允许后台 Activity 启动 Service。

继续调用:

 ComponentName startServiceLocked(IApplicationThread caller, Intent service, 
            String resolvedType, int callingPid, int callingUid, boolean fgRequired,
            String callingPackage, @Nullable String callingFeatureId, final int userId,
            boolean allowBackgroundActivityStarts, 
            @Nullable IBinder backgroundActivityStartsToken)
            throws TransactionTooLargeException {

    final boolean callerFg;
    if (caller != null) {
        // 从 mLruProcesses 列表中找出指定进程
        final ProcessRecord callerApp = mAm.getRecordForAppLocked(caller);
   // 关键点1:callerFg 用于标记发起端进程是前台还是后台,
   // 当发起方进程不等于SCHED_GROUP_BACKGROUND
   // 或者发起方为空,则 callerFg= true,否则为 false
        callerFg = callerApp.setSchedGroup != ProcessList.SCHED_GROUP_BACKGROUND;
    } else {
        callerFg = true;
    } 
    // 关键点2:从 ServiceMap 中根据 ComponentName 查找 ServiceRecord,不存在的话就创建
    // 并封装成 ServiceLookupResult, 见 # 3.2.1
    ServiceLookupResult res = retrieveServiceLocked(service, null, resolvedType,
		    callingPackage, callingPid, callingUid, userId, true, callerFg, 
		    false, false); 
    // 获取 ServiceRecord,并构建
    ServiceRecord r = res.record; 
    ......
    // 是否后台启动, Android 8.0+ 有后台启动限制
    final boolean bgLaunch = !mAm.isUidActiveLOSP(r.appInfo.uid);
    boolean forcedStandby = false;
    // 如果后台启动 Service,且 app 有后台启动限制,则 forcedStandby 设置为 true
    if (bgLaunch && appRestrictedAnyInBackground(r.appInfo.uid, r.packageName)) {
        forcedStandby = true;
    }
    // 如果是 startForegroundService 启动前台服务,检查前台启动操作权限是否允许
    if (fgRequired) {
        final int mode = mAm.mAppOpsService.checkOperation(
                AppOpsManager.OP_START_FOREGROUND, r.appInfo.uid, r.packageName);
        switch (mode) {
            case AppOpsManager.MODE_ALLOWED:
            case AppOpsManager.MODE_DEFAULT:
                // All okay.
                break;
            case AppOpsManager.MODE_IGNORED:
                // Not allowed, fall back to normal start service
                // failing siliently. if background check restricts that.
                fgRequired = false;
                forceSilentAbort = true;
                break;
        }
    }
    // 如果是后台启动或者启动非前台服务,检查是否允许后台启动,如果不能的话返回 null
    if (forcedStandby || (!r.startRequested && !fgRequired)) {
    final int allowed = mAm.getAppStartModeLocked(r.appInfo.uid, r.packageName,
         r.appInfo.targetSdkVersion, callingPid, false, false, forcedStandby);
        if (allowed != ActivityManager.APP_START_MODE_NORMAL) {
            if (allowed == ActivityManager.APP_START_MODE_DELAYED ||
                forceSilentAbort) {
                // In this case we are silently disabling the app, to disrupt as
                // little as possible existing apps.
                return null;
            }
            if (forcedStandby) {
                if (fgRequired) {
                    return null;
                }
            }
            // This app knows it is in the new model where this operation is not
            // allowed, so tell it what has happened.
            UidRecord uidRec = mAm.mProcessList.getUidRecordLocked(r.appInfo.uid);
            return new ComponentName("?", "app is in background uid " + uidRec);
        }
    }
// Android 8.0 之前启动前台服务不需要调用 startForegroundService(), 即 fgRequired 为 false
    if (r.appInfo.targetSdkVersion < Build.VERSION_CODES.O && fgRequired) {
        fgRequired = false;
    } 
NeededUriGrants neededGrants = mAm.mUgmInternal.checkGrantUriPermissionFromIntent(
     callingUid, r.packageName, service, service.getFlags(), null, r.userId); 
    // 权限检查 permission review
    if (!requestStartTargetPermissionsReviewIfNeededLocked(r, callingPackage,
            callingUid, service, callerFg, userId)) {
        return null;
    } 
    ......
    // 设置 ServiceRecord 启动参数, pendingStarts 中添加启动项 StartItem
    r.lastActivity = SystemClock.uptimeMillis();
    // startRequested 是 ServiceRecord 类的一个 boolean 类型的成员变量,该值为 true 表示 Service
    // 是通过 startService 方式(而不是 bindService 方式)启动的
    r.startRequested = true;
    r.delayedStop = false;
    r.fgRequired = fgRequired;
    r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),
            service, neededGrants, callingUid));
 
    if (fgRequired) {
        // 如果是 Android 8.0+ 调用的 startForegroundService() 启动前台服务的话,
        // 更新 ServiceState
        ServiceState stracker = r.getTracker();
        if (stracker != null) {
            stracker.setForeground(true, mAm.mProcessStats.getMemFactorLocked(),
                    r.lastActivity);
        }
     mAm.mAppOpsService.startOperation(AppOpsManager.getToken(mAm.mAppOpsService),
           AppOpsManager.OP_START_FOREGROUND, r.appInfo.uid, r.packageName, true);
    }
    // 获取 ServiceMap
    final ServiceMap smap = getServiceMapLocked(r.userId);
    boolean addToStarting = false;//重点变量
    // 如果“ caller app 不是前台应用”、“目标 Service 不是前台服务”
    // “目标 Service 处于未运行状态”
    // “发起请求的用户已经启动”,以上条件均满足则进入此分支,判断目标 Service 是否需要
    // 延迟启动,否则,将调用 startServiceInnerLocked() 立即启动目标 Service
    if (!callerFg && !fgRequired && r.app == null &&
            mAm.mUserController.hasStartedUserState(r.userId)) {
        // 从进程列表中获取启动 Service 所在的进程
        ProcessRecord proc = mAm.getProcessRecordLocked(r.processName,
                r.appInfo.uid, false);
        // 当目标 Service 所属的进程尚未创建,或者已创建但优先级较低时
        //(即 proc.curProcState 的值
        // 大于常量10,注意它的取值越小反而表示进程优先级越高
        if (proc == null ||
                proc.getCurProcState() > ActivityManager.PROCESS_STATE_RECEIVER) {
            // 如果 delayed 为 true,延迟启动
            if (r.delayed) {
                return r.name;
            }
            // 如果后台启动服务数超过 mMaxStartingBackground,则延迟启动
            if (smap.mStartingBackground.size() >= mMaxStartingBackground) {
                // Something else is starting, delay!
                smap.mDelayedStartList.add(r);
                r.delayed = true;
                return r.name;
            }
            // addToStarting 设置为 true
            addToStarting = true;
        } else if (proc.getCurProcState() >= ActivityManager.PROCESS_STATE_SERVICE) {
        // 当目标 Service 所属的进程已经创建且优先级较高时(即 proc.curProcState 的值大于或等于常量9)
        // 目标 Service 的启动不受 mStartingBackground 列表的容量限制,一定可以立即启动
            addToStarting = true;
        }
    } 
    // Called when the service is started with allowBackgroundActivityStarts set.
    if (allowBackgroundActivityStarts) {
        r.whitelistBgActivityStartsOnServiceStart();
    } 
	// 启动服务
    ComponentName cmp = startServiceInnerLocked(smap, service, r,
            callerFg, addToStarting);
    return cmp;
}
  • startRequested 是 ServiceRecord 类的一个 boolean 类型的成员变量,该值为 true 表示 Service 是通过 startService 方式(而不是 bindService 方式)启动的
  • pendingStarts 是 ServiceRecord 类的一个 ArrayList<StartItem> 类型的成员变量,它保存着所有尚未处理的 Service 启动参数,这些参数最终会在回调 Service 的 onStartCommand() 时传递给应用进程进行处理
  • addToStarting 是一个 boolean 类型的局部变量,该值为 true 表示目标 Service 可以作为后台服务立即启动,并且它对应的 ServiceRecord 将被添加到 ServiceMap 对象的 mStartingBackground 列表中。此处它的值被初始化为 false,后续的执行流程将根据目标 Service 是否为后台服务以及是否需要延迟启动来对其进行赋值
3.2.1 ActiveServices.retrieveServiceLocked

retrieveServiceLocked() 根据 Intent 查询并返回一个 ServiceLookupResult 对象,其中封装了目标 Service 对应的 ServiceRecord。该方法首先尝试从 ServiceMap 中获取 ServiceRecord 缓存对象,而 ServiceMap 又是 ActiveServices 类的内部类,它为每个用户分别维护了 mServicesByName 和 mServicesByIntent 两个值类型为 ServiceRecord 的 ArrayMap。如果不存在缓存对象,该方法将调用 PackageManagerService 的 resolveService() 解析 Intent 并获得对应的 ResolveInfo 对象,然后利用它创建一个新的 ServiceRecord 对象。

总结一句话:retrieveServiceLocked() 最大的意义就是获取或创建 ServiceRecord 对象,并封装到 ServiceLookupResult 中,然后返回。
 

3.2.2 ActiveServices.getServiceMapLocked
private ServiceMap getServiceMapLocked(int callingUser) {
    ServiceMap smap = mServiceMap.get(callingUser);
    if (smap == null) {
        smap = new ServiceMap(mAm.mHandler.getLooper(), callingUser);
        mServiceMap.put(callingUser, smap);
    }
    return smap;
}

3.3 ActiveServices.startServiceInnerLocked

ComponentName startServiceInnerLocked(ServiceMap smap, Intent service,
    ServiceRecord r, boolean callerFg, boolean addToStarting) 
    throws TransactionTooLargeException {
	// 更新 ServiceState 状态为 started
    ServiceState stracker = r.getTracker();
    if (stracker != null) {
     stracker.setStarted(true, mAm.mProcessStats.getMemFactorLocked(),
         r.lastActivity);
    }
    r.callStart = false;
    synchronized (r.stats.getBatteryStats()) {
        r.stats.startRunningLocked();
    }
    // 关键点:拉起服务.
    String error = bringUpServiceLocked(r, service.getFlags(),
        callerFg, false, false);
    if (error != null) {
        return new ComponentName("!!", error);
    } 
    if (r.startRequested && addToStarting) {
        boolean first = smap.mStartingBackground.size() == 0;
        smap.mStartingBackground.add(r);
        r.startingBgTimeout =
            SystemClock.uptimeMillis() + mAm.mConstants.BG_START_TIMEOUT;
        if (first) {
            smap.rescheduleDelayedStartsLocked();
        }
    } else if (callerFg || r.fgRequired) {
        smap.ensureNotStartingBackgroundLocked(r);
    } 
    return r.name;
}

callStart 是 ServiceRecord 类的一个 boolean 类型的成员变量,该值为 true 表示(先前运行的)Service 由于内存不足被杀死后进行自动重启(一个典型的实例是 Service 的 onStartCommand() 返回 START_STICKY)。在本文分析的执行流程中,目标 Service 是通过 startService 方式进行“全新启动”而非自动重启,所以此处该值被设置为 false。

startServiceLocked() 接着调用 bringUpServiceLocked() “拉起”目标 Service,如果启动失败则会抛出对应的异常。

3.4 ActiveServices.bringUpServiceLocked

private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,
            boolean whileRestarting, boolean permissionsReviewRequired, 
            boolean packageFrozen, boolean enqueueOomAdj)
            throws TransactionTooLargeException {

    if (r.app != null && r.app.thread != null) {// 关键点1:判断条件
        // 如果目标 Service 的进程已经创建,并且已经启动过,则发送只启动服务消息
        sendServiceArgsLocked(r, execInFg, false);
        return null;
    } 
    ......
   
final boolean isolated = 
        (r.serviceInfo.flags&ServiceInfo.FLAG_ISOLATED_PROCESS) != 0;
    final String procName = r.processName;
HostingRecord hostingRecord = new HostingRecord("service", r.instanceName);
    ProcessRecord app; 
    if (!isolated) { // 非 isolated 进程
        // 从进程列表查找目标 Service 所属的进程是否存在
        app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false);
        // 表示目标 Service 所属的进程已经存在
        if (app != null) {
                final IApplicationThread thread = app.getThread();
                final int pid = app.getPid();
                final UidRecord uidRecord = app.getUidRecord();
                if (thread != null) {
                    try {
                        app.addPackage(r.appInfo.packageName, 
                        r.appInfo.longVersionCode, mAm.mProcessStats);
                         // 关键点2:真正启动服务. 它首先通过 IPC 回调
                         // Service 的 onCreate() 完成创建流程
                        realStartServiceLocked(r, app, thread, pid, uidRecord, execInFg,
                                enqueueOomAdj);
                        return null;
                    } catch (TransactionTooLargeException e) {
                        throw e;
                    } catch (RemoteException e) {
                       ......
                    }
                }
        }
    } else { // isolated进程
        ......
    } 
    // 如果进程为空,则启动进程并将 ServiceRecord 添加到服务队列中等待执行
    if (app == null && !permissionsReviewRequired) {
    // 关键点3:调用 AMS 的 startProcessLocked() 创建一个新的进程
        if ((app=mAm.startProcessLocked(procName, r.appInfo, true,
intentFlags, hostingRecord, false, isolated, false)) == null) {
            bringDownServiceLocked(r);
            return msg;
        }
        if (isolated) {
            r.isolatedProc = app;
        }
    } 
    if (r.fgRequired) {
         mAm.tempWhitelistUidLocked(r.appInfo.uid,
        SERVICE_START_FOREGROUND_TIMEOUT,"fg-service-launch");
    } 
    // 关键点4: mPendingServices 列表中添加服务,等新进程启动后根据这个列表查找然后启动
    if (!mPendingServices.contains(r)) {
        mPendingServices.add(r);
    } 
    ......
    return null;
}

bringUpServiceLocked() “拉起” 目标 Service,它根据其所属的进程是否已经创建执行相应的后续流程,并且在执行成功时返回 null(反之则返回错误消息)。

  • 如果目标 Service 已经创建并启动,则可以直接通过 sendServiceArgsLocked() 回调目标 Service 的 onStartCommand()
  • 如果目标 Service 尚未创建但所属的进程已经存在,则需要通过 realStartServiceLocked() 执行 Service 的 create 流程
  • 如果目标 Service 所属的进程尚未创建,则需要通过 AMS 的 startProcessLocked() 创建对应的进程
  • 如果目标 Service 所属的进程尚未创建,需要把 ServiceRecord 添加到 mPendingServices 中,等待进程启动后再行启动

为了更加全面地展示 Service 的启动流程,本文假定对应的进程尚未创建。

  • r.app 和 r.app.thread 分别是 ProcessRecord 和 IApplicationThread 类型的对象,当这两者不为 null 时表示目标 Service 此前已经执行过创建和初始化的流程。此时后续调用的 sendServiceArgsLocked() 会将 ServiceRecord(它本身是 AMS 进程的 Binder 实体类)和相关的启动参数通过 IPC 传递给应用进程,并最终回调目标 Service 的 onStartCommand() 对启动参数进行解析和处理
  • isolated 是一个 boolean 类型的局部变量,它对应于 Manifest 中 Service 的 android:isolatedProcess 属性,该值为 true 意味着 Service 会在一个特殊的进程下运行,该进程将与系统其它进程分开并且没有自己的权限
  • mPendingServices 是一个 ArrayList<ServiceRecord> 类型的成员变量,当 Service 所属的进程不存在时,会将对应的 ServiceRecord 保存在这个列表中。当进程创建完成后会调用 attachApplicationLocked(),该方法将遍历 mPendingServices 并调用 realStartServiceLocked() 执行目标 Service 的后续启动流程

四 创建 Service 所属的新进程

4.1 AMS.startProcessLocked

这个函数的分析,我们可以参考  Activity启动流程的 4.3 节内容。就是创建了一个新的进程。

五 应用进程启动Service

我们知道当创建一个新的进程的时候,会在进程中执行 ActivityThread 的 main 函数。并且我们知道会在这个 main 函数中执行 ActivityThread 的 attach 方法,在这个 attach 方法中,调用到 AMS 的 attachApplicationLocked。我们来看这个方法:

5.1 ActivityManagerService.attachApplication

public final void attachApplication(IApplicationThread thread, long startSeq) {
    synchronized (this) {
		// 通过 Binder 获取传入的 pid 信息
        int callingPid = Binder.getCallingPid();
        final int callingUid = Binder.getCallingUid();
        final long origId = Binder.clearCallingIdentity();
        attachApplicationLocked(thread, callingPid, callingUid, startSeq);
        Binder.restoreCallingIdentity(origId);
    }
}


private final boolean attachApplicationLocked(IApplicationThread thread,
        int pid, int callingUid, long startSeq) {
    ProcessRecord app;
    // 从 mPidsSelfLocked 列表根据 pid 查找进程
    if (pid != MY_PID && pid >= 0) {
        synchronized (mPidsSelfLocked) {
            app = mPidsSelfLocked.get(pid);
        }
        ........
    } else {
        app = null;
    }
    // 若上述查找 app 为空,则从 mPendingStarts 列表根据 startSeq 查找进程
    if (app == null && startSeq > 0) {
        final ProcessRecord pending = mProcessList.mPendingStarts.get(startSeq);
        if (pending != null && pending.startUid == callingUid 
                && pending.startSeq == startSeq
                && mProcessList.handleProcessStartedLocked(pending, pid,
                pending.isUsingWrapper(), startSeq, true)) {
            app = pending;
        }
    }
	........
    // 如果当前的 Application 记录仍然依附到之前的进程中,则清理掉
    if (app.thread != null) {
        handleAppDiedLocked(app, true, true);
    }
 
    // mProcessesReady 这个变量在 AMS 的 systemReady 中被赋值为 true,
    //  所以这里的 normalMode 也为 true
    boolean normalMode = mProcessesReady || isAllowedWhileBooting(app.info);
	........
	if (app.isolatedEntryPoint != null) { // isolated进程
        // This is an isolated process which should just call an entry point instead of
        // being bound to an application.
        thread.runIsolatedEntryPoint(app.isolatedEntryPoint, app.isolatedEntryPointArgs);
    } else if (instr2 != null) {
	    // 绑定 App 进程
        thread.bindApplication(processName, appInfo, providers,
                instr2.mClass,
                profilerInfo, instr2.mArguments,
                instr2.mWatcher,
                instr2.mUiAutomationConnection, testMode,
                mBinderTransactionTrackingEnabled, enableTrackAllocation,
                isRestrictedBackupMode || !normalMode, app.isPersistent(),
                new Configuration(app.getWindowProcessController().getConfiguration()),
                app.compat, getCommonServicesLocked(app.isolated),
                mCoreSettingsObserver.getCoreSettingsLocked(),
                buildSerial, autofillOptions, contentCaptureOptions);
    } else {
        thread.bindApplication(processName, appInfo, providers, null, profilerInfo,
                null, null, null, testMode,
                mBinderTransactionTrackingEnabled, enableTrackAllocation,
                isRestrictedBackupMode || !normalMode, app.isPersistent(),
                new Configuration(app.getWindowProcessController().getConfiguration()),
                app.compat, getCommonServicesLocked(app.isolated),
                mCoreSettingsObserver.getCoreSettingsLocked(),
                buildSerial, autofillOptions, contentCaptureOptions);
    }
    ........
    // 绑定应用程序后, 设置 app active, 并更新 lru 进程信息
    app.makeActive(thread, mProcessStats);// 给 ProcessRecord 的 thread 赋值,表示绑定成功
    mProcessList.updateLruProcessLocked(app, false, null);
    app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
 
    ......
 
    boolean didSomething = false;
    // See if the top visible activity is waiting to run in this process...
        if (normalMode) {
            try {
                didSomething = mAtmInternal.attachApplication(
                app.getWindowProcessController());
            } catch (Exception e) {
                Slog.wtf(TAG, "Exception thrown launching activities in " + app, e);
                badApp = true;
            }
        }
    // Find any services that should be running in this process...
        if (!badApp) {
            try {// 关键点:调用ActiveServices的attachApplicationLocked排查等待启动的Service
                didSomething |= mServices.attachApplicationLocked(app, processName);
                ......
            } catch (Exception e) {
                Slog.wtf(TAG, "Exception thrown starting services in " + app, e);
                badApp = true;
            }
        }

   // Check if a next-broadcast receiver is in this process...
        if (!badApp && isPendingBroadcastProcessLocked(pid)) {
            try { // 关键点:排查等待处理的广播
                didSomething |= sendPendingBroadcastsLocked(app);
            } catch (Exception e) {
                .......
                badApp = true;
            }
        }
        
    if (!didSomething) {
	    // 进程启动,更新 Adj
        updateOomAdjLocked(OomAdjuster.OOM_ADJ_REASON_PROCESS_BEGIN);
    }
	........
    return true;
}

5.2 ActiveServices.attachApplicationLocked

boolean attachApplicationLocked(ProcessRecord proc, String processName) 
        throws RemoteException {
        
    ......
    if (mPendingServices.size() > 0) {
        ServiceRecord sr = null;
        ......
        for (int i = 0; i < mPendingServices.size(); i++) {
            sr = mPendingServices.get(i);
            // 和当前进程信息不符合的 ServiceRecord 直接跳过
            if (proc != sr.isolatedProc && (proc.uid != sr.appInfo.uid 
                    || !processName.equals(sr.processName))) {
                continue;
             }
            ......            
            realStartServiceLocked(sr, proc, sr.createdFromFg); // 关键调用
            ......
        }
    }
    ......
}

attachApplicationLocked() 遍历 mPendingServices 中的每一项 ServiceRecord,当对应的进程恰好是目标 Service 所属的进程时,则调用 realStartServiceLocked() 执行 Service 的 create 流程。

5.3 ActiveServices.realStartServiceLocked

private void realStartServiceLocked(ServiceRecord r, ProcessRecord app,
            IApplicationThread thread, int pid, UidRecord uidRecord, boolean execInFg,
            boolean enqueueOomAdj) throws RemoteException { 
    r.setProcess(app);// 设置进程,ServiceRecord 和 ProcessRecord 绑定
    //可知ServiceRecord 的app参数的设置是启动前完成的,只要不为空,说明服务已经被启动过
    r.restartTime = r.lastActivity = SystemClock.uptimeMillis(); 
    // services 列表中添加服务
    ......
    try {
       ......
       // 关键调用:创建服务
            thread.scheduleCreateService(r, r.serviceInfo,
                    mAm.compatibilityInfoForPackage(r.serviceInfo.applicationInfo),
                    app.mState.getReportedProcState());
            r.postNotification();
            created = true;
        } catch (DeadObjectException e) {
            ......
        }
    ......
	// 下面这段代码是 bindService 相关逻辑,此处只分析 startService
    requestServiceBindingsLocked(r, execInFg); // 关键点:bind service 相关操作
    ......
    sendServiceArgsLocked(r, execInFg, true);
    // 关键点:发送参数给service,回调onStartCommand
    if (r.delayed) {
        getServiceMapLocked(r.userId).mDelayedStartList.remove(r);
        r.delayed = false;
    } 
    if (r.delayedStop) {
        // Oh and hey we've already been asked to stop!
        r.delayedStop = false;
        if (r.startRequested) {
            stopServiceLocked(r, enqueueOomAdj);
        }
    }
}

realStartServiceLocked 主要做的事情:

  • ActivityThread.scheduleCreateService:回调到 APP 端,执行 Service 的生命周期,并调用 onCreate 方法
  • requestServiceBindingsLocked() 处理 Service 的绑定过程,它最终会回调 Service 的 onBind()。事实上以 startService 方式启动 Service 时,原本并不需要处理绑定过程。但是上文中提到,当 Service 对应的进程尚未创建时,会将对应的 ServiceRecord 对象暂时保存在 mPendingServices 中。如果在进程创建的过程中,恰好又以 bindService 方式提交了其它启动请求,那么自然就需要额外处理 Service 的绑定过程
  • sendServiceArgsLocked:启动 Service,最终会调用 ApplicationThread.scheduleServiceArgs 最终调用到 onStartCommand​​​​​​​​​​

5.4 ActivityThread.scheduleCreateService

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

​​​​​​​​​​​​

5.5 ActivityThread.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);
        Service service = null;
        try {
            java.lang.ClassLoader cl = packageInfo.getClassLoader();
            // 通过类加载器构建 Service 对象
            service = packageInfo.getAppFactory()
                    .instantiateService(cl, data.info.name, data.intent);
        } catch (Exception 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) {
            ......
        }
}
  • getPackageInfoNoCheck() 的返回值类型为 LoadedApk,它是 APK 文件在内存中的表示,通过它可以获取 APK 文件中包含的代码和资源文件
  • Service 的 attach() 完成了 Service 对象的大部分成员变量的初始化流程,也就是说,此处传入的部分参数的引用会被 Service 所持有。例如,第二个参数 this 和第四个参数 data.token 分别用于初始化 Service 对象的成员变量 mThread 和 mToken
  • mServices 是 ActivityThread 类的一个 ArrayMap<IBinder, Service> 类型的成员变量,它的键是 AMS 进程的 ServiceRecord 在应用进程中的 Binder 代理对象,它的值是应用进程的 Service 对象。当 AMS 请求应用进程运行一个 Service 时,会将 ServiceRecord 通过 IPC 传递给应用进程,然后它对应的 Binder 代理对象会作为键保存在 mServices 中,从而维护同一个 Service 对象在 AMS 进程与应用进程之间的映射关系 

至此为止,需要启动的 Service 的 onCreate 流程终于分析完毕。

5.6 ActiveServices.sendServiceArgsLocked

private final void sendServiceArgsLocked(ServiceRecord r, boolean execInFg,
        boolean oomAdjusted) throws TransactionTooLargeException {
    final int N = r.pendingStarts.size();
    if (N == 0) {
        return;
    } 
    ArrayList<ServiceStartArgs> args = new ArrayList<>(); 
    while (r.pendingStarts.size() > 0) {
        // 从 pendingStarts 列表移除并取出 StartItem
        ServiceRecord.StartItem si = r.pendingStarts.remove(0); 
        // 当 intent=null 且 pendingStarts 列表存在多个待启动的 Service 时,直接跳过
        if (si.intent == null && N > 1) {
            continue;
        } 
        // 更新 deliver 信息
        si.deliveredTime = SystemClock.uptimeMillis();
        r.deliveredStarts.add(si);
        si.deliveryCount++;
        if (si.neededGrants != null) {
     mAm.mUgmInternal.grantUriPermissionUncheckedFromIntent(si.neededGrants,
                    si.getUriPermissionsLocked());
        }
     mAm.grantEphemeralAccessLocked(r.userId, si.intent,
            UserHandle.getAppId(r.appInfo.uid), UserHandle.getAppId(si.callingId));
        // 更新 ServiceRecord start 阶段各属性.
        bumpServiceExecutingLocked(r, execInFg, "start");
        // 更新 oomAdj
        if (!oomAdjusted) {
            oomAdjusted = true;
     mAm.updateOomAdjLocked(r.app, true, OomAdjuster.OOM_ADJ_REASON_START_SERVICE);
        }
        if (r.fgRequired && !r.fgWaiting) {
            if (!r.isForeground) {
                // 如果启动前台服务,在调用了 startForegroundService() 后若当前还没有调用
                // startForeground() 则要检查 startForeground() 是否在规定时间内调用
                // 超时时间为 10s 如果超时未调用则 stopService,同时抛出 ANR 异常
                scheduleServiceForegroundTransitionTimeoutLocked(r);
            } else { // 如果已经调用了 startForeground(), 则重置状态
                r.fgRequired = false;
            }
        }
        int flags = 0;
        if (si.deliveryCount > 1) {
            flags |= Service.START_FLAG_RETRY;
        }
        if (si.doneExecutingCount > 0) {
            flags |= Service.START_FLAG_REDELIVERY;
        }
        // args 列表中添加服务启动参数
        args.add(new ServiceStartArgs(si.taskRemoved, si.id, flags, si.intent));
    } 
    ParceledListSlice<ServiceStartArgs> slice = new ParceledListSlice<>(args);
    // 设置列表最大数为 4
    slice.setInlineCountLimit(4);
    Exception caughtException = null;
    try {      
        r.app.thread.scheduleServiceArgs(r, slice); 
        // 关键调用:启动 Service.onStartCommand.
    } catch (TransactionTooLargeException e) {
       ......
    } 
    ......
}

我们知道当 Service 的 create 流程执行完毕后,接下来会调用 sendServiceArgsLocked()。该方法对 Service 的启动参数进行检查和封装,然后通过 IPC 调用应用进程的 scheduleServiceArgs() 对启动参数进行处理。

  • 如果 r.pendingStarts 值为0,表示没有启动参数需要处理,此时方法会直接返回。上文中方法 startServiceLocked() 已经为目标 Service 创建并添加了一个 StartItem 对象,所以此处一定会执行后续的流程并最终回调 Service 的 onStartCommand()。同理,上文中方法 realStartServiceLocked() 之所以需要为自动重启且未传入启动参数的 Service 构造一个缺省的 StartItem 对象,也是为了确保能最终回调 onStartCommand()
  • ParceledListSlice 类是 Android 系统提供的一个利用 IPC 传输 Parcelable 对象列表的工具类,当列表中元素的数量足够多时,会自动将其拆分为多个 transaction 依次处理

5.7 ActivityThread.handleServiceArgs

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();
                }
            } catch (Exception e) {
                if (!mInstrumentation.onException(s, e)) {
                    throw new RuntimeException(
                            "Unable to start service " + s
                            + " with " + data.args + ": " + e.toString(), e);
                }
            }
        }
    }

至此 Service 的 onStartCommand 方法执行完毕。

5.8 ActivityManagerService.serviceDoneExecuting

frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

public void serviceDoneExecuting(IBinder token, int type, int startId, int res) {
    synchronized(this) {
        mServices.serviceDoneExecutingLocked((ServiceRecord)token, type, startId, res);
    }
}

5.9 ActiveServices.serviceDoneExecutingLocked

void serviceDoneExecutingLocked(ServiceRecord r, int type, int startId, int res) {
    boolean inDestroying = mDestroyingServices.contains(r);
    if (type == ActivityThread.SERVICE_DONE_EXECUTING_START) {
        // 若为启动服务,从 deliveredStarts 中查找指定服务,并设置服务 stopIfKilled 属性
        r.callStart = true;
        switch (res) {
            case Service.START_STICKY_COMPATIBILITY:
            case Service.START_STICKY: {
                // We are done with the associated start arguments.
                r.findDeliveredStart(startId, false, true);
                // Don't stop if killed.
                r.stopIfKilled = false;
                break;
            }
            case Service.START_NOT_STICKY: {
                // We are done with the associated start arguments.
                r.findDeliveredStart(startId, false, true);
                if (r.getLastStartId() == startId) {
                    r.stopIfKilled = true;
                }
                break;
            }
            case Service.START_REDELIVER_INTENT: {
     ServiceRecord.StartItem si = r.findDeliveredStart(startId, false, false);
                if (si != null) {
                    si.deliveryCount = 0;
                    si.doneExecutingCount++;
                    // Don't stop if killed.
                    r.stopIfKilled = true;
                }
                break;
            }
            case Service.START_TASK_REMOVED_COMPLETE: {
                r.findDeliveredStart(startId, true, true);
                break;
            }
        }
        if (res == Service.START_STICKY_COMPATIBILITY) {
            r.callStart = false;
        }
    } else if (type == ActivityThread.SERVICE_DONE_EXECUTING_STOP) {
        // destroy 服务
        ......
    } 
    // 做一些 Service 清理工作,具体实现看下面代码       
    serviceDoneExecutingLocked(r, inDestroying, inDestroying);
}

继续调用同名函数 serviceDoneExecutingLocked

private void serviceDoneExecutingLocked(ServiceRecord r,
        boolean inDestroying, boolean finishing) {
    r.executeNesting--;
    if (r.executeNesting <= 0) {
        if (r.app != null) {
            r.app.execServicesFg = false;
            r.app.executingServices.remove(r);
            if (r.app.executingServices.size() == 0) {
                // 如果当前没有正在执行的服务,则移除 SERVICE_TIMEOUT_MSG 消息
mAm.mHandler.removeMessages(ActivityManagerService.SERVICE_TIMEOUT_MSG, r.app);
            } else if (r.executeFg) {
   // Need to re-evaluate whether the app still needs to be in the foreground.
                for (int i=r.app.executingServices.size()-1; i>=0; i--) {
                    if (r.app.executingServices.valueAt(i).executeFg) {
                        r.app.execServicesFg = true;
                        break;
                    }
                }
            }
            if (inDestroying) { // 从 mDestroyingServices 列表移除服务
                mDestroyingServices.remove(r);
                r.bindings.clear();
            }
            // 更新 oomAdj
mAm.updateOomAdjLocked(r.app, true, OomAdjuster.OOM_ADJ_REASON_UNBIND_SERVICE);
        }
        // 重置前台执行标识位为 false
        r.executeFg = false;
        if (r.tracker != null) {
            final int memFactor = mAm.mProcessStats.getMemFactorLocked();
            final long now = SystemClock.uptimeMillis();
            // 更新 ServiceState 状态为非执行中和非前台
            r.tracker.setExecuting(false, memFactor, now);
            r.tracker.setForeground(false, memFactor, now);
            if (finishing) {
                r.tracker.clearCurrentOwner(r, false);
                r.tracker = null;
            }
        }
        if (finishing) {
            // 从 services 列表移除服务
            if (r.app != null && !r.app.isPersistent()) {
                r.app.services.remove(r);
                r.app.updateBoundClientUids();
                if (r.whitelistManager) {
                    updateWhitelistManagerLocked(r.app);
                }
            }
            // process 置空
            r.setProcess(null);
        }
    }
}

5.10 ServiceRecord.findDeliveredStart

frameworks/base/services/core/java/com/android/server/am/ServiceRecord.java

// 根据属性 id 和 taskRemoved 从 deliveredStarts 列表中匹配 Service
// 并根据 remove 标识决定要不要从列表移除
public StartItem findDeliveredStart(int id, boolean taskRemoved, boolean remove) {
    final int N = deliveredStarts.size();
    for (int i=0; i<N; i++) {
        StartItem si = deliveredStarts.get(i);
        if (si.id == id && si.taskRemoved == taskRemoved) {
            if (remove) deliveredStarts.remove(i);
            return si;
        }
    } 
    return null;
}

整个 Service 启动流程分析完毕。

六 注意事项

6.1 Service 执行时间限制

前台服务执行时间限制是 20 秒,后台服务执行时间限制是 200 秒,否则超时会报 ANR 异常。具体代码体现如下:

6.1.1 ActiveServices.scheduleServiceTimeoutLocked
void scheduleServiceTimeoutLocked(ProcessRecord proc) {
    if (proc.executingServices.size() == 0 || proc.thread == null) {
        return;
    }
    Message msg = mAm.mHandler.obtainMessage(
            ActivityManagerService.SERVICE_TIMEOUT_MSG);
    msg.obj = proc;
    mAm.mHandler.sendMessageDelayed(msg,
            proc.execServicesFg ? SERVICE_TIMEOUT : SERVICE_BACKGROUND_TIMEOUT);
}

// How long we wait for a service to finish executing.
// Build.HW_TIMEOUT_MULTIPLIER 系统属性,默认值为1
static final int SERVICE_TIMEOUT = 20 * 1000 * Build.HW_TIMEOUT_MULTIPLIER;
static final int SERVICE_BACKGROUND_TIMEOUT = SERVICE_TIMEOUT * 10;
6.1.2 MainHandler.SERVICE_TIMEOUT_MSG
final class MainHandler extends Handler {
    public MainHandler(Looper looper) {
        super(looper, null, true);
    } 
    @Override
    public void handleMessage(Message msg) {
        switch (msg.what) {
        ......
        case SERVICE_TIMEOUT_MSG: {
            mServices.serviceTimeout((ProcessRecord)msg.obj);
        } break;
        case SERVICE_FOREGROUND_TIMEOUT_MSG: {
            mServices.serviceForegroundTimeout((ServiceRecord)msg.obj);
        } break;
        ......
    }
}
6.1.3 ActiveServices.serviceTimeout
void serviceTimeout(ProcessRecord proc) {
    String anrMessage = null;
    synchronized(mAm) {
        if (proc.isDebugging()) {
            // The app's being debugged, ignore timeout.
            return;
        }
        if (proc.executingServices.size() == 0 || proc.thread == null) {
            return;
        }
        final long now = SystemClock.uptimeMillis();
        final long maxTime =  now - (proc.execServicesFg ?
                SERVICE_TIMEOUT : SERVICE_BACKGROUND_TIMEOUT);
        ServiceRecord timeout = null;
        long nextTime = 0;
        for (int i=proc.executingServices.size()-1; i>=0; i--) {
            ServiceRecord sr = proc.executingServices.valueAt(i);
            if (sr.executingStart < maxTime) {
                timeout = sr;
                break;
            }
            if (sr.executingStart > nextTime) {
                nextTime = sr.executingStart;
            }
        }
        if (timeout != null && mAm.mProcessList.mLruProcesses.contains(proc)) {
            StringWriter sw = new StringWriter();
            PrintWriter pw = new FastPrintWriter(sw, false, 1024);
            pw.println(timeout);
            timeout.dump(pw, "    ");
            pw.close();
            mLastAnrDump = sw.toString();
            mAm.mHandler.removeCallbacks(mLastAnrDumpClearer);
mAm.mHandler.postDelayed(mLastAnrDumpClearer, LAST_ANR_LIFETIME_DURATION_MSECS);
            anrMessage = "executing service " + timeout.shortInstanceName;
        } else {
            Message msg = mAm.mHandler.obtainMessage(
                    ActivityManagerService.SERVICE_TIMEOUT_MSG);
            msg.obj = proc;
mAm.mHandler.sendMessageAtTime(msg, proc.execServicesFg
       ? (nextTime+SERVICE_TIMEOUT) : (nextTime + SERVICE_BACKGROUND_TIMEOUT));
        }
    }
    if (anrMessage != null) {
        mAm.mAnrHelper.appNotResponding(proc, anrMessage);
    }
}

6.2 startService 和 startForegroundService

  • Android 8.0 之前一般通过 startService 启动后台服务,当系统内存紧张情况下后台 Service 可能会被杀死.如果希望 Service 能够长时间运行而不被杀死,可以在通过 startService 启动服务后,在 Service 的 onStartCommand 方法中调用 startForeground(id, notification) 将服务设置为前台服务.比如一般的音乐播放器都是这种做法.
  • Android 8.0 之后出于资源考虑对 Service 做了一些限制.比如不允许后台调用 startService,否则会报错.启动前台服务方式变成调用 startForegroundService,之后再在 Service 的 onStartCommand 方法中调用 startForeground(id, notification) 将服务设置为前台服务.
  • startService 和 startForegroundService 共用一套代码实现,都是调用 startServiceCommon,差别就是入参 requireForeground 前者为 false 后者为 true.
  • Android 8.0 之后启动前台服务,会检查调用 startForegroundService 方法后,是否在规定时间内调用了 startForeground.这个超时时间是10秒,如果超时未调用则会 stopService,同时抛出 ANR 异常.具体代码体现如下:
void scheduleServiceForegroundTransitionTimeoutLocked(ServiceRecord r) {
    ......
    Message msg = mAm.mHandler.obtainMessage(
            ActivityManagerService.SERVICE_FOREGROUND_TIMEOUT_MSG);
    msg.obj = r;
    r.fgWaiting = true;
    mAm.mHandler.sendMessageDelayed(msg, SERVICE_START_FOREGROUND_TIMEOUT);
}

void serviceForegroundTimeout(ServiceRecord r) {
    ProcessRecord app;
    synchronized (mAm) {
        if (!r.fgRequired || r.destroying) {
            return;
        } 
        app = r.app;
        if (app != null && app.isDebugging()) {
            // The app's being debugged; let it ride
            return;
        } 
        // startForeground()超时,stopService
        r.fgWaiting = false;
        stopServiceLocked(r);
    } 
    // ANR调用
    if (app != null) {
        mAm.mAnrHelper.appNotResponding(app,
                    "Context.startForegroundService() did not then 
                    call Service.startForeground(): "
                        + r);
    }
}

6.3 onStartCommand 返回值

frameworks/base/core/java/android/app/Service.java

public @StartResult int onStartCommand(Intent intent,
        @StartArgFlags int flags, int startId) {
    onStart(intent, startId);
    return mStartCompatibility ? START_STICKY_COMPATIBILITY : START_STICKY;
}
6.3.1 入参
  • intent:通过 startService 传进来的意图.如果 Service 重启时为 null
  • flags:Additional data about this start request
  • startId:A unique integer representing this specific request to start
6.3.2 返回值

描述了 Service 被杀后,应该怎么继续启动 Service.
具体体现在源码里,会影响 ServiceRecord 的 stopIfKilled 属性.

// 掩码
public static final int START_CONTINUATION_MASK = 0xf;
// 进程被杀后,不保证一定调用onStartCommand方法
public static final int START_STICKY_COMPATIBILITY = 0;
// Service启动后若所在进程被杀,则服务保留started状态但intent不保留
// 等进程启动后会自动重建Service实例并调用onStartCommand, 且此时intent为null
// 一般适用于音乐播放器等后台长时间运行场景
public static final int START_STICKY = 1;
// Service启动后若所在进程被杀,则不会自动重建Service, 需要外部主动调用
// startService才会新建Service实例. 适用场景:适用于当存在内存压力时允许
// 所在进程被杀死,且有机制主动调用startService拉起服务的场景.
// 如通过Alarm机制每隔N分钟启动一次服务这种场景.
public static final int START_NOT_STICKY = 2;
// Service启动后若所在进程被杀,则等进程启动后Service会被重建且intent
// 会被继续转发除非手动调用stopService或intent为null
public static final int START_REDELIVER_INTENT = 3;

七 总结

在整个 startService 过程,从进程角度看服务启动流程如下:

  • 应用进程向 AMS 发送 Service 启动请求
  • AMS 进行一系列准备工作,主要包括合法性检查和判断是否延迟启动
  • AMS 判断目标 Service 所属的进程是否已经存在。若进程尚未创建,则请求 Zygote 创建一个新进程,然后在其主线程中调用 ActivityThread.main() 完成进程的初始化
  • AMS 判断 Service 是否已经创建。若 Service 尚未创建,则执行相应的创建流程并最终回调 onCreate()
  • AMS 将 Service 的启动参数发送给应用进程
  • Service 所属的目标进程接收并解析启动参数,然后调用 onStartCommand(),从而完成启动流程

 

  • 30
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值