Understand the startService() startup process of the four components Service (based on Android10)

1. Overview

The startup process learned in the previous article activitywill continue to analyze startService() the startup process this time. Compared to activities, services can provide long-running operations in the background without an interface. Even after switching to the background, the service continues to run in the background.

1.1 Three types of services

  1. 前台服务No interface, the notification bar must be set (within 5s, if startForground() is not called, ANR will be thrown). Actions that the user can directly perceive and notice, such as using audio playback

  2. 后台服务No interface, actions that the user won't notice directly.

  3. 绑定服务No interface. In the bound state (similar to the C/S architecture), the component can interact with the service at this time, such as: RPC call, must be unbind to unbind, the service will be terminated. A service can be bound to multiple components. As long as one component binds the service, the service is in a bound state. The service will be destroyed only after all bound components are unbind.

1.2 Service Lifecycle

The life cycle of a service is as follows:

image.png

1.3 The difference between startService and bindService

The lifecycle distinctions have been shown in the lifecycle diagram above. The former is used to do a long single job and run it alone after startup. The latter is suitable for RPC interaction scenarios that require multiple calls to the interface, and focuses on interaction.

Although two ways are distinguished, a service can support binding operations on it when it is started. That is, 同时支持两种方式运行.

1.4 Subclasses provided by system services

  • serviceDirectly inherit service, write onCreate(), and other optional lifecycle callback methods. All callbacks run on the main thread by default
  • IntentServiceThe handlerThread object is encapsulated internally, and all lifecycle callbacks are switched to the child thread.

1.5 Selection of services and threads

Services are generally applicable 长时间后台工作, such as network transactions, playing music, file I/O, etc. Threads are suitable for performing time-consuming operations. For example, if a service follows the life cycle of a component such as an activity, you can select a thread.

Activity inherits ContextWrapper:

2. StartService() on the App side

2.1 ContextImpl.startService()

ContextWrapper.java

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

    // 前台服务
    @Override
    public ComponentName startForegroundService(Intent service) {
        return mBase.startForegroundService(service);
    }

ContextWrapper内部有代理了 ContextImpl,所以我们看看 ContextImpl的 startService():

2.2 ContextImpl.startService()

ContextImpl.java

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

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

2.2.1 startServiceCommon()


 private ComponentName startServiceCommon(Intent service, boolean requireForeground,
            UserHandle user) {
        try {
            validateServiceIntent(service);
            service.prepareToLeaveProcess(this);
            // 直接调用 AMS的 startService方法 , 返回一个 ComponentName 对象。
            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();
        }
    }

直接调用 AMS的 startService方法 , 返回一个 ComponentName 对象。

三、AMS 端 startService

3.1 startService()

ActivityManagerService.java

 @Override
    public ComponentName startService(IApplicationThread caller, Intent service,
            String resolvedType, boolean requireForeground, String callingPackage, int userId)
            throws TransactionTooLargeException {
            // requireForeground 是否是前台服务 
        enforceNotIsolatedCaller("startService");
       ...
        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 {
            // 调用  startServiceLocked
                res = mServices.startServiceLocked(caller, service,
                        resolvedType, callingPid, callingUid,
                        requireForeground, callingPackage, userId);
            } finally {
                Binder.restoreCallingIdentity(origId);
            }
            return res;
        }
    }

调用 ActiveServices的 startServiceLocked()。

allowBackgroundActivityStarts属性传入false,再内部继续调用同名的方法startServiceLocked():

3.2 ActiveServices.startServiceLocked()

ActiveServices.java

ActiveServices 是系统用来管理服务的类。内部有一系列的集合list,用来存储ServiceRecord 对象。 也就是系统所有的service都由 ActiveServices 来管理。

 ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType,
            int callingPid, int callingUid, boolean fgRequired, String callingPackage,
            final int userId, boolean allowBackgroundActivityStarts)
            throws TransactionTooLargeException {
            
            // fgRequired 是否是前台服务 
            //  allowBackgroundActivityStarts 为false。
            
            
            final boolean callerFg;
            // 获取当前进程对象 ProcessRecord 
            if (caller != null) {
                final ProcessRecord callerApp = mAm.getRecordForAppLocked(caller);
                if (callerApp == null) {
                    throw new SecurityException(
                            "Unable to find app for caller " + caller
                            + " (pid=" + callingPid
                            + ") when starting service " + service);
                }
                callerFg = callerApp.setSchedGroup != ProcessList.SCHED_GROUP_BACKGROUND;
            } else {
                callerFg = true;
            }
            
            // 内部通过PMS解析得到 serviceRecord 对象信息 
            ServiceLookupResult res =
            retrieveServiceLocked(service, null, resolvedType, callingPackage,
                    callingPid, callingUid, userId, true, callerFg, false, 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;

}

retrieveServiceLocked()方法内部最终通过PMS来解析得到 ServiceRecord对象,返回ServiceLookupResult。ServiceLookupResult 内部封装了 ServiceRecord 对象。

3.2.1 startServiceInnerLocked()

ActiveServices.java

ComponentName startServiceInnerLocked(ServiceMap smap, Intent service, ServiceRecord r,
            boolean callerFg, boolean addToStarting) throws TransactionTooLargeException {
        ServiceState stracker = r.getTracker();
        if (stracker != null) {
            stracker.setStarted(true, mAm.mProcessStats.getMemFactorLocked(), r.lastActivity);
        }
        r.callStart = false;
        StatsLog.write(StatsLog.SERVICE_STATE_CHANGED, r.appInfo.uid, r.name.getPackageName(),
                r.name.getClassName(), StatsLog.SERVICE_STATE_CHANGED__STATE__START);
        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;
    }

3.2.2 bringUpServiceLocked()

ActiveServices.java

 private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,
            boolean whileRestarting, boolean permissionsReviewRequired)
            throws TransactionTooLargeException {
        if (r.app != null && r.app.thread != null) {
            // 1 调用 service.onStartCommand()
            sendServiceArgsLocked(r, execInFg, false);
            return null;
        }

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

       //...

        // We are now bringing the service up, so no longer in the
        // restarting state.
        if (mRestartingServices.remove(r)) {
            clearRestartingIfNeededLocked(r);
        }

        // Make sure this service is no longer considered delayed, we are starting it now.
        if (r.delayed) {
             
            getServiceMapLocked(r.userId).mDelayedStartList.remove(r);
            r.delayed = false;
        }

        // Make sure that the user who owns this service is started.  If not,
        // we don't want to allow it to run.
        if (!mAm.mUserController.hasStartedUserState(r.userId)) {
            String msg = "Unable to launch app "
                    + r.appInfo.packageName + "/"
                    + r.appInfo.uid + " for service "
                    + r.intent.getIntent() + ": user " + r.userId + " is stopped";
            Slog.w(TAG, msg);
            bringDownServiceLocked(r);
            return msg;
        }

          //....
        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) {
            app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false);
               // 如果进程已经启动
            if (app != null && app.thread != null) {
                try {
                    app.addPackage(r.appInfo.packageName, r.appInfo.longVersionCode, mAm.mProcessStats);
                    
                    // 启动服务 
                    realStartServiceLocked(r, app, execInFg);
                    
                    return null;
                } catch (TransactionTooLargeException e) {
                    throw e;
                } catch (RemoteException e) {
                    Slog.w(TAG, "Exception when starting service " + r.shortInstanceName, e);
                }

                // If a dead object exception was thrown -- fall through to
                // restart the application.
            }
        } else {
            // If this service runs in an isolated process, then each time
            // we call startProcessLocked() we will get a new isolated
            // process, starting another process if we are currently waiting
            // for a previous process to come up.  To deal with this, we store
            // in the service any current isolated process it is running in or
            // waiting to have come up.
            app = r.isolatedProc;
            if (WebViewZygote.isMultiprocessEnabled()
                    && r.serviceInfo.packageName.equals(WebViewZygote.getPackageName())) {
                hostingRecord = HostingRecord.byWebviewZygote(r.instanceName);
            }
            if ((r.serviceInfo.flags & ServiceInfo.FLAG_USE_APP_ZYGOTE) != 0) {
                hostingRecord = HostingRecord.byAppZygote(r.instanceName, r.definingPackageName,
                        r.definingUid);
            }
        }

        // Not running -- get it started, and enqueue this service record
        // to be executed when the app comes up.
        if (app == null && !permissionsReviewRequired) {
            //如果进程没有启动,那么开启进程,等进程拉起后,会调用AMS.attacthApplication(),再次调用 ActiveServices.attachApplicationLocked(),内部再次调用 realStartServiceLocked()
            if ((app=mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,
                    hostingRecord, 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 (isolated) {
                r.isolatedProc = app;
            }
        }

        if (r.fgRequired) {
            
            mAm.tempWhitelistUidLocked(r.appInfo.uid,
                    SERVICE_START_FOREGROUND_TIMEOUT, "fg-service-launch");
        }

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

        if (r.delayedStop) {
            // Oh and hey we've already been asked to stop!
            r.delayedStop = false;
            if (r.startRequested) {
               
                stopServiceLocked(r);
            }
        }

        return null;
    }
  • 服务如果已经启动过了,则调用 service.onStartCommand()
  • 如果进程存在,则直接调用 realStartServiceLocked() 启动服务
  • 如果进程不存在,那么久拉起进程。等进程拉起后,会调用AMS.attacthApplication(),内部调用 ActiveServices.attachApplicationLocked(),内部再次调用 realStartServiceLocked()

因此,我们继续看 realStartServiceLocked():

3.2.3 realStartServiceLocked()

/Users/avengong/Library/Android/sdk/sources/android-29/com/android/server/am/ActiveServices.java

注意: 不要被startService开头的方法名字迷惑了。这里的start意思是 拉起app端的service 实例。bindService()启动方式也会调用到这里。

 private final void realStartServiceLocked(ServiceRecord r,
            ProcessRecord app, boolean execInFg) throws RemoteException {
        ....
        r.setProcess(app);
        r.restartTime = r.lastActivity = SystemClock.uptimeMillis();

        final boolean newService = app.services.add(r);
        // 发送ANR 检测消息 
        bumpServiceExecutingLocked(r, execInFg, "create");
        // 更新AMS中的 processRecord Lru集合
        mAm.updateLruProcessLocked(app, false, null);
        updateServiceForegroundLocked(r.app, /* oomAdj= */ false);
        mAm.updateOomAdjLocked(OomAdjuster.OOM_ADJ_REASON_START_SERVICE);

        boolean created = false;
        try {
            ...
         
            synchronized (r.stats.getBatteryStats()) {
                r.stats.startLaunchedLocked();
            }
            mAm.notifyPackageUse(r.serviceInfo.packageName,
                                 PackageManager.NOTIFY_PACKAGE_USE_SERVICE);
            app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE);
            // 执行 服务的onCreate() 流程
            app.thread.scheduleCreateService(r, r.serviceInfo,
                    mAm.compatibilityInfoForPackage(r.serviceInfo.applicationInfo),
                    app.getReportedProcState());
            r.postNotification();
            // 至此,表示系统侧的 service 创建完毕。 
            created = true;
            
        } catch (DeadObjectException e) {
            Slog.w(TAG, "Application dead when creating service " + r);
            mAm.appDiedLocked(app);
            throw e;
        } finally {
            if (!created) {
                // Keep the executeNesting count accurate.
                final boolean inDestroying = mDestroyingServices.contains(r);
                serviceDoneExecutingLocked(r, inDestroying, inDestroying);

                // Cleanup.
                if (newService) {
                    app.services.remove(r);
                    r.setProcess(null);
                }

                // Retry. 如果没有启动,会再次尝试
                if (!inDestroying) {
                    scheduleServiceRestartLocked(r, false);
                }
            }
        }

        if (r.whitelistManager) {
            app.whitelistManager = true;
        }

        requestServiceBindingsLocked(r, execInFg);

        updateServiceClientActivitiesLocked(app, null, true);

        if (newService && created) {
            app.addBoundClientUidsOfNewService(r);
        }

        // 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));
        }
        // 回调onStartCommand()方法 
        sendServiceArgsLocked(r, execInFg, true);

        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);
            }
        }
    }
  • 发送ANR延迟检测消息
  • 执行onCreate()流程,回调App端 scheduleCreateService()
  • 执行onStartCommand()流程

3.2.4 bumpServiceExecutingLocked(r, execInFg, "create")

ActiveServices.java

private final void bumpServiceExecutingLocked(ServiceRecord r, boolean fg, String why) {
    // ... 
    boolean timeoutNeeded = true;
    if ((mAm.mBootPhase < SystemService.PHASE_THIRD_PARTY_APPS_CAN_START)
            && (r.app != null) && (r.app.pid == android.os.Process.myPid())) {

        timeoutNeeded = false;
    }

    long now = SystemClock.uptimeMillis();
    if (r.executeNesting == 0) {
        r.executeFg = fg;
        ServiceState stracker = r.getTracker();
        if (stracker != null) {
            stracker.setExecuting(true, mAm.mProcessStats.getMemFactorLocked(), now);
        }
        if (r.app != null) {
            r.app.executingServices.add(r);
            r.app.execServicesFg |= fg;
            if (timeoutNeeded && r.app.executingServices.size() == 1) {
                scheduleServiceTimeoutLocked(r.app);
            }
        }
    } else if (r.app != null && fg && !r.app.execServicesFg) {
        r.app.execServicesFg = true;
        // 发送超时ANR检测消息
        if (timeoutNeeded) {
            scheduleServiceTimeoutLocked(r.app);
        }
    }
    r.executeFg |= fg;
    r.executeNesting++;
    r.executingStart = now;
}

3.2.5 ActiveServices.scheduleServiceTimeoutLocked()

ActiveServices.java


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);
}
  • 如果超时还没有移除这个消息,那么就判定为启动service ANR了,执行SERVICE_TIMEOUT_MSG消息逻辑,内部会调用ActiveServices.serviceTimeout() 方法。
  • 前台服务超时时间:SERVICE_TIMEOUT=10s
  • 后天服务超时时间:200s

3.2.6 ActiveServices.serviceTimeout()

ActiveServices.java

void serviceTimeout(ProcessRecord proc) {
    String anrMessage = null;
    synchronized(mAm) {
        ...
        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)) {
            Slog.w(TAG, "Timeout executing service: " + timeout);
            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));
        }
    }
    // 直接执行app的 ANR 流程 
    if (anrMessage != null) {
        proc.appNotResponding(null, null, null, null, false, anrMessage);
    }
}

如果发生ANR,则直接执行app的 ANR 流程,具体怎么执行后续再分析~

疑问,既然发送了ANR判定消息,那么什么时候去移除这个消息呢?

答:在app端创建完service后,会再次告知AMS端执行完成。 这里先看app端如何处理。

四、App 端 scheduleCreateService()

AMS通过Binder跨进程调用到app端,接收的对象为 ActivityThread的静态内部类 ApplicationThread。我们先看onCreate()执行流程。

4.1 ApplicationThread.scheduleCreateService

ActivityThread.java

 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);
        }
  • IBinder token: 对应 ServiceRecord
  • ServiceInfo info:服务信息
  • CompatibilityInfo compatInfo:
  • int processState:进程状态

发送了CREATE_SERVICE一个消息到主线程。

4.2 H.CREATE_SERVICE 消息

ActivityThread.java

 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;

4.3 ActivityThread.handleCreateService()

ActivityThread.java

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 表示已安装的apk的所有信息
        LoadedApk packageInfo = getPackageInfoNoCheck(
                data.info.applicationInfo, data.compatInfo);
        Service service = null;
        try {
            ///  反射 service实例
            java.lang.ClassLoader cl = packageInfo.getClassLoader();
            service = packageInfo.getAppFactory()
                    .instantiateService(cl, data.info.name, data.intent);
        }
        //...

        try {
            if (localLOGV) Slog.v(TAG, "Creating service " + data.info.name);
            // 创建service 的context 对象
            ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
            context.setOuterContext(service);
            
            Application app = packageInfo.makeApplication(false, mInstrumentation);
            // attach app信息到service
            service.attach(context, this, data.info.name, data.token, app,
                    ActivityManager.getService());
            // 调用 service的 onCreate()方法
            service.onCreate();
            // 把token作为key,存入到 mServices map中
            mServices.put(data.token, service);
            
            try {
                // 告知 AMS service已经启动完毕 
                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);
            }
        }
    }

  • 通过反射创建 service 实例对象
  • 创建context,并且attach到service
  • 调用service的onCreate()方法
  • 调用 serviceDoneExecuting() 通知AMS,service已经启动完毕,注意传入的是 SERVICE_DONE_EXECUTING_ANON = 0

五、AMS端 serviceDoneExecuting()

ActivityManagerService.java

public void serviceDoneExecuting(IBinder token, int type, int startId, int res) {
    synchronized(this) {
        if (!(token instanceof ServiceRecord)) {
            Slog.e(TAG, "serviceDoneExecuting: Invalid service token=" + token);
            throw new IllegalArgumentException("Invalid service token");
        }
        mServices.serviceDoneExecutingLocked((ServiceRecord)token, type, startId, res);
    }
}

调用了 ActiveServices 的方法:

5.1 ActiveServices.serviceDoneExecutingLocked()

void serviceDoneExecutingLocked(ServiceRecord r, int type, int startId, int res) {
    boolean inDestroying = mDestroyingServices.contains(r);
    if (r != null) {
        if (type == ActivityThread.SERVICE_DONE_EXECUTING_START) {
          ...
        } else if (type == ActivityThread.SERVICE_DONE_EXECUTING_STOP) {
          ...
        }
        final long origId = Binder.clearCallingIdentity();
        // 继续调用方法
        serviceDoneExecutingLocked(r, inDestroying, inDestroying);
        Binder.restoreCallingIdentity(origId);
    } else {
        Slog.w(TAG, "Done executing unknown service from pid "
                + Binder.getCallingPid());
    }
}

5.2 serviceDoneExecutingLocked()

ActiveServices.java

private void serviceDoneExecutingLocked(ServiceRecord r, boolean inDestroying,
        boolean finishing) {
    
    r.executeNesting--;
    if (r.executeNesting <= 0) {
        if (r.app != null) {
            if (DEBUG_SERVICE) Slog.v(TAG_SERVICE,
                    "Nesting at 0 of " + r.shortInstanceName);
            r.app.execServicesFg = false;
            r.app.executingServices.remove(r);
            if (r.app.executingServices.size() == 0) {
                // 移除 ANR超时消息 
                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) {
                if (DEBUG_SERVICE) Slog.v(TAG_SERVICE,
                        "doneExecuting remove destroying " + r);
                mDestroyingServices.remove(r);
                r.bindings.clear();
            }
            mAm.updateOomAdjLocked(r.app, true, OomAdjuster.OOM_ADJ_REASON_UNBIND_SERVICE);
        }
        r.executeFg = false;
        if (r.tracker != null) {
            final int memFactor = mAm.mProcessStats.getMemFactorLocked();
            final long now = SystemClock.uptimeMillis();
            r.tracker.setExecuting(false, memFactor, now);
            r.tracker.setForeground(false, memFactor, now);
            if (finishing) {
                r.tracker.clearCurrentOwner(r, false);
                r.tracker = null;
            }
        }
        if (finishing) {
            if (r.app != null && !r.app.isPersistent()) {
                r.app.services.remove(r);
                r.app.updateBoundClientUids();
                if (r.whitelistManager) {
                    updateWhitelistManagerLocked(r.app);
                }
            }
            r.setProcess(null);
        }
    }
}

整个流程:

  1. app端开始发起启动服务请求,发往AMS。
  2. AMS端执行创建serviceRecord,同时发送一个ANR延迟消息。通知app端可以创建service。
  3. The app side creates the service, executes onCreate(), notifies the AMS side again, and removes the ANR message.

So far, the whole onCreate()流程执行完毕.

Remember the realStartServiceLocked() method in the summary of 3.2.3 on the AMS side, after executing onCreate() internally, it will call sendServiceArgsLocked()to execute the onStartCommand()method:

5.3 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) {
        ServiceRecord.StartItem si = r.pendingStarts.remove(0);
        if (DEBUG_SERVICE) {
            Slog.v(TAG_SERVICE, "Sending arguments to: "
                    + r + " " + r.intent + " args=" + si.intent);
        }
        if (si.intent == null && N > 1) {
            // If somehow we got a dummy null intent in the middle,
            // then skip it.  DO NOT skip a null intent when it is
            // the only one in the list -- this is to support the
            // onStartCommand(null) case.
            continue;
        }
        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));
        bumpServiceExecutingLocked(r, execInFg, "start");
        if (!oomAdjusted) {
            oomAdjusted = true;
            mAm.updateOomAdjLocked(r.app, true, OomAdjuster.OOM_ADJ_REASON_START_SERVICE);
        }
        if (r.fgRequired && !r.fgWaiting) {
            if (!r.isForeground) {
                if (DEBUG_BACKGROUND_CHECK) {
                    Slog.i(TAG, "Launched service must call startForeground() within timeout: " + r);
                }
                scheduleServiceForegroundTransitionTimeoutLocked(r);
            } else {
                if (DEBUG_BACKGROUND_CHECK) {
                    Slog.i(TAG, "Service already foreground; no new timeout: " + r);
                }
                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.add(new ServiceStartArgs(si.taskRemoved, si.id, flags, si.intent));
    }

    ParceledListSlice<ServiceStartArgs> slice = new ParceledListSlice<>(args);
    slice.setInlineCountLimit(4);
    Exception caughtException = null;
    try {
        // 执行 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;
    }

    if (caughtException != null) {
        // Keep nesting count correct
        final boolean inDestroying = mDestroyingServices.contains(r);
        for (int i = 0; i < args.size(); i++) {
            serviceDoneExecutingLocked(r, inDestroying, inDestroying);
        }
        if (caughtException instanceof TransactionTooLargeException) {
            throw (TransactionTooLargeException)caughtException;
        }
    }
}

Execute scheduleServiceArgs(), and finally call the onStartCommand() method.

5. ScheduleServiceArgs() on the App side

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;
        // 发送消息 SERVICE_ARGS
        sendMessage(H.SERVICE_ARGS, s);
    }
}

HSERVICE_ARGSWhen the message is received , the handleServiceArgs()method is called:

5.1 handleServiceArgs() message

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

            QueuedWork.waitToFinish();

            try {
            // 通知AMS start阶段完成
                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);
            }
        }
    }
}
  • The onStartCommand() method is called, and the onStart() method is called internally (deprecated)
  • Notify AMS that the start phase is complete. Finally, on the AMS side, serviceDoneExecuting() will be called, and serviceDoneExecutingLocked() will be called internally, the same logic as before.

5.1.1 Service.onStartCommand

Service.java

public @StartResult int onStartCommand(Intent intent, @StartArgFlags int flags, int startId) {
    //调用onStart() 方法。
    onStart(intent, startId);
    return mStartCompatibility ? START_STICKY_COMPATIBILITY : START_STICKY;
}

onStartCommand()and onStart()are also called. At this point, the servicestartup is complete.

6. Summary

A brief summary of the entire process:

  1. The app side initiates a service start request to the AMS side
  2. The AMS side executes the creation of serviceRecord and sends an ANR delay message at the same time. Notify the app that the service can be created, and then call the onStartCommand() method
  3. The app side creates the service, executes onCreate(), notifies the AMS side again, and removes the ANR message. Subsequently, the onStartCommand() method is processed, and the AMS is notified again to remove the ANR message.

おすすめ

転載: juejin.im/post/7116830797562118158