1. Service概述
Service作为Android四大组件之一,在开发过程中非常常用,它虽然没有ui,但是同样可以在后台做很多重要的事情,我们平时使用启动service主要通过startService以及bindService来启动service以便已经相关操作。本文将介绍startService的原理,后续将分别介绍bindService的原理,以及在Android O上对service的新增限制管控。
注:本文基于Android 8.1 2. Service分类从启动方式上,可以分别通过startService以及bindService启动,两者之间最重要的区别在于bindService可以建立binder连接,更加方便通信。
从运行方式上,可以分为前台service(foregroundService,下面简称fg-service)与后台service,两者的区别在于有前台service的进程对应的优先级会更高,不容易被系统清理掉,但是前台service需要在通知栏里面显示一个常驻的通知。3. startService时序图
startService的启动大致分为三种情况:
对应进程不存在(先启动进程然后启动service并执行onCreate和onStartCommand)
进程存在但是service不存在(启动service并执行onCreate和onStartCommand) 进程和service都存在(只执行onStartCommand)上面的时序图主要针对进程存在,但是service不存在的情况,其他两种在主要流程上没有太大区别,关键在于其中有一些特殊判断,在文章过程中也会提到。
4. 源码解析 4.1 ContextImpl.startServicepublic ComponentName startService(Intent service) {
warnIfCallingFromSystemProcess(); return startServiceCommon(service, false, mUser); } public ComponentName startForegroundService(Intent service) { warnIfCallingFromSystemProcess(); return startServiceCommon(service, true, mUser); } // 最终的入口都在这个方法中 // foreground service只是传参requireForeground为true,普通service为false private ComponentName startServiceCommon(Intent service, boolean requireForeground, UserHandle user) { try { validateServiceIntent(service); service.prepareToLeaveProcess(this); // binder call至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; } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } }
最终通过startServiceCommon调用至ams,注意这里返回值有进行特殊处理,然后抛出了一些异常,主要返回值的component的packageName有"!","!!","?"三种,后面在介绍源码过程中可以看到具体是哪里会返回这些异常。
"!":权限校验没通过,不允许启动 "!!":无法启动 "?":不允许启动 4.2 ActivityManagerService.startServicepublic ComponentName startService(IApplicationThread caller, Intent service,
String resolvedType, boolean requireForeground, String callingPackage, int userId) throws TransactionTooLargeException { enforceNotIsolatedCaller("startService"); // 进行一些简单的校验 if (service != null && service.hasFileDescriptors() == true) { throw new IllegalArgumentException("File descriptors passed in Intent"); } // callingPackage不能为空 if (callingPackage == null) { throw new IllegalArgumentException("callingPackage cannot be null"); } synchronized(this) { final int callingPid = Binder.getCallingPid(); final int callingUid = Binder.getCallingUid(); final long origId = Binder.clearCallingIdentity(); ComponentName res; try { // mService正是ActiveServices对象 res = mServices.startServiceLocked(caller, service, resolvedType, callingPid, callingUid, requireForeground, callingPackage, userId); } finally { Binder.restoreCallingIdentity(origId); } return res; } } 这块只是简单校验之后,就调用到了ActiveServices.startServiceLocked。 参数解析: caller:发起startService的进程对应的IApplicationThread对象 service:要启动的service的intent resolvedType:service类型,启动的时候可以设置data已经schema等 requireForeground:是否发起启动foregroundService callingPackage:发起startService的进程的packageName userId:当前用户id 4.3 ActiveServices.startServiceLockedComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType,
int callingPid, int callingUid, boolean fgRequired, String callingPackage, final int userId) throws TransactionTooLargeException { final boolean callerFg; // 获取发起binder call的caller进程,如果不存在则抛异常 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; } // 拿到要启动的service的信息 // 主要是从packageManagerService中查询,然后缓存起来 // 其中还进行了一些权限的校验,4.4小节详细介绍 ServiceLookupResult res = retrieveServiceLocked(service, resolvedType, callingPackage, callingPid, callingUid, userId, true, callerFg, false); // 没有查到要启动的service,直接return了 if (res == null) { return null; } // 这里就能看到前面提到的返回component的package为“!”的情况了 // 原因是没有对应的servicerecord,没有的原因会在下面4.4小节中进一步介绍 if (res.record == null) { return new ComponentName("!", res.permission != null ? res.permission : "private to package"); } // 拿到要启动的serviceRecord,这个就是我们在manifest中注册的service组件对应在系统中封装起来的对象 ServiceRecord r = res.record; // 判断user是否存在 if (!mAm.mUserController.exists(r.userId)) { return null; } // 是否要启动fg-service if (!r.startRequested && !fgRequired) { // 这块是校验如果要启动的service是一个后台service // 那么需要看是否拥有后台启动的权限,不允许就无法后台启动 final int allowed = mAm.getAppStartModeLocked(r.appInfo.uid, r.packageName, r.appInfo.targetSdkVersion, callingPid, false, false); if (allowed != ActivityManager.APP_START_MODE_NORMAL) { // 新升级到O的应用可能会遇到这问题,因为不允许后台情况下的app启动后台service Slog.w(TAG, "Background start not allowed: service " + service + " to " + r.name.flattenToShortString() + " from pid=" + callingPid + " uid=" + callingUid + " pkg=" + callingPackage); if (allowed == ActivityManager.APP_START_MODE_DELAYED) { return null; } // 不允许启动,此处封装component的packageName为“?”,对应前面提到的,会抛出相关异常 UidRecord uidRec = mAm.mActiveUids.get(r.appInfo.uid); return new ComponentName("?", "app is in background uid " + uidRec); } } ... // 如果这个service正在调度重启,那么取消重启,因为马上要启动了 if (unscheduleServiceRestartLocked(r, callingUid, false)) { if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "START SERVICE WHILE RESTART PENDING: " + r); } r.lastActivity = SystemClock.uptimeMillis(); r.startRequested = true; r.delayedStop = false; r.fgRequired = fgRequired; r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(), service, neededGrants, callingUid)); final ServiceMap smap = getServiceMapLocked(r.userId); boolean addToStarting = false; // 如果调用者在后台,且不是启动的前台service,判断是否需要delay if (!callerFg && !fgRequired && r.app == null && mAm.mUserController.hasStartedUserState(r.userId)) { ProcessRecord proc = mAm.getProcessRecordLocked(r.processName, r.appInfo.uid, false); if (proc == null || proc.curProcState > ActivityManager.PROCESS_STATE_RECEIVER) { if (r.delayed) { return r.name; } if (smap.mStartingBackground.size() >= mMaxStartingBackground) { smap.mDelayedStartList.add(r); r.delayed = true; return r.name; } addToStarting = true; } else if (proc.curProcState >= ActivityManager.PROCESS_STATE_SERVICE) { addToStarting = true; } } ... // 准备启动service了 ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting); return cmp; }小结:
校验caller
拿到serviceRecord,进一步校验 校验是否有可以后台启动 是否需要delay startServiceInnerLocked4.4 ActiveServices.retrieveServiceLocked
private ServiceLookupResult retrieveServiceLocked(Intent service,
String resolvedType, String callingPackage, int callingPid, int callingUid, int userId, boolean createIfNeeded, boolean callingFromFg, boolean isBindExternal) { ServiceRecord r = null; // 获取user userId = mAm.mUserController.handleIncomingUser(callingPid, callingUid, userId, false, ActivityManagerService.ALLOW_NON_FULL_IN_PROFILE, "service", null); // 根据userId获取ServiceMap // 有一个user为key,ServiceMap为v的map,保存了所有的service信息 // 每个user对应一个 // ServiceMap是一个handler对象,用的looper是ActivityManager线程 // 其中主要保存的都是存放service的各map,以不同的方式存储的Servicerecord ServiceMap smap = getServiceMapLocked(userId); final ComponentName comp = service.getComponent(); // 通过component从ServiceMap查询 if (comp != null) { r = smap.mServicesByName.get(comp); } ... if (r == null) { try { // 如果没能查到,那需要从PackageManager去查询了 ResolveInfo rInfo = mAm.getPackageManagerInternalLocked().resolveService(service, resolvedType, ActivityManagerService.STOCK_PM_FLAGS | PackageManager.MATCH_DEBUG_TRIAGED_MISSING, userId, callingUid); ServiceInfo sInfo = rInfo != null ? rInfo.serviceInfo : null; if (sInfo == null) { Slog.w(TAG_SERVICE, "Unable to start service " + service + " U=" + userId + ": not found"); return null; } // 封装ComponentName ComponentName name = new ComponentName( sInfo.applicationInfo.packageName, sInfo.name); // FLAG_EXTERNAL_SERVICE类型的service必须有人去bind // 这块就不贴具体实现了,startService过程中这个逻辑不会走到 ...if (userId > 0) {
if (mAm.isSingleton(sInfo.processName, sInfo.applicationInfo, sInfo.name, sInfo.flags) && mAm.isValidSingletonCall(callingUid, sInfo.applicationInfo.uid)) { userId = 0; smap = getServiceMapLocked(0); } sInfo = new ServiceInfo(sInfo); sInfo.applicationInfo = mAm.getAppInfoForUser(sInfo.applicationInfo, userId); } r = smap.mServicesByName.get(name); // 拿到ServiceRecord,如果没有需要新建 if (r == null && createIfNeeded) { ... // 这块主要就是ServiceRecord对象创建以及放入ServiceMap中 } } } if (r != null) { ... // 这块主要是做一些权限校验,包括export(manifest中指定是否允许其他进程启动) // 以及自己指定的service权限 if (!mAm.mIntentFirewall.checkService(r.name, service, callingUid, callingPid, resolvedType, r.appInfo)) { return null; } // 查找成功 return new ServiceLookupResult(r, null); } // 没有查找成功返回null // 上面一节有提到,如果这里返回null则会再进一步返回到ContextImpl中抛出异常 return null; }
这块做了两件事:
查找ServiceRecord,如果不存在则创建
权限检查4.5 ActiveServices.startServiceInnerLocked
ComponentName startServiceInnerLocked(ServiceMap smap, Intent service, ServiceRecord r,
boolean callerFg, boolean addToStarting) throws TransactionTooLargeException { ... r.callStart = false; synchronized (r.stats.getBatteryStats()) { r.stats.startRunningLocked(); } // bringUpServiceLocked这个是启动service的核心 String error = bringUpServiceLocked(r, service.getFlags(), callerFg, false, false); if (error != null) { return new ComponentName("!!", error); } // 下面主要是进行delay 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; }这里没做什么事,主要实现都在bringUpServiceLocked 4.6 ActiveServices.bringUpServiceLocked
private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,
boolean whileRestarting, boolean permissionsReviewRequired) throws TransactionTooLargeException { // 从上面的时序图可以知道sendServiceArgsLocked中主要是要调度执行service的onStartCommand // 这里怎么直接就执行了呢? // 原因在于判断条件,对于没有执行onCreate的service,r.app是null,所以不会执行这个流程 // 也就是没有启动过的service不会走这里,只有启动过的service才会 // 所以对于已经启动过的service,重复startService只会走onStartCommand,就是因为这里,然后return if (r.app != null && r.app.thread != null) { sendServiceArgsLocked(r, execInFg, false); return null; } // 如果不是调度重启,且已经在restart列表中,return // 只有调度重启的地方调用过来whileRestarting为true if (!whileRestarting && mRestartingServices.contains(r)) { return null; } // 从restart中移除,因为马上要执行启动了 if (mRestartingServices.remove(r)) { clearRestartingIfNeededLocked(r); } ... // 这中间是一些简单的状态判断,有兴趣可以自己查看源码final boolean isolated = (r.serviceInfo.flags&ServiceInfo.FLAG_ISOLATED_PROCESS) != 0;
final String procName = r.processName; String hostingType = "service"; ProcessRecord app; if (!isolated) { // 进程存在那就直接走真正启动service的逻辑了 app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false); if (app != null && app.thread != null) { try { app.addPackage(r.appInfo.packageName, r.appInfo.versionCode, mAm.mProcessStats); realStartServiceLocked(r, app, execInFg); return null; } catch (TransactionTooLargeException e) { throw e; } catch (RemoteException e) { Slog.w(TAG, "Exception when starting service " + r.shortName, e); } } } else { // isolated进程处理,O上webview进程属于这种类型,加以特殊处理,标记hostingType // hostingType主要用于启动进程的时候 app = r.isolatedProc; if (WebViewZygote.isMultiprocessEnabled() && r.serviceInfo.packageName.equals(WebViewZygote.getPackageName())) { hostingType = "webview_service"; } }// 进程不存在,那还得先启动进程
if (app == null && !permissionsReviewRequired) { 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 (isolated) { r.isolatedProc = app; } } ... // 因为要启动进程,所以需要记一下这次启动进程的原因是因为需要启动这个service // 等到进程启动成功之后,在进程attachApplicationLocked的时候会再去启动这个serivice if (!mPendingServices.contains(r)) { mPendingServices.add(r); } return null; }
小结:
如果service已经存在那么直接调度sendServiceArgsLocked(将会执行service.onStartCommand)
处理service重启相关数据结构 进程存在,则realStartServiceLocked 进程不存在则先启动进程并把service保存在mPendingServices4.7 ActiveServices.realStartServiceLocked
private final void realStartServiceLocked(ServiceRecord r,
ProcessRecord app, boolean execInFg) throws RemoteException { r.app = app; r.restartTime = r.lastActivity = SystemClock.uptimeMillis();final boolean newService = app.services.add(r);
// 这里主要是计算设置service的timeout // 因为service的执行是计算在ANR机制中的,这里就是开始计时 bumpServiceExecutingLocked(r, execInFg, "create"); mAm.updateLruProcessLocked(app, false, null); // 如果是前台service需要更新并记录当前前台serivice的状态 updateServiceForegroundLocked(r.app, /* oomAdj= */ false); // 更新进程优先级 mAm.updateOomAdjLocked();boolean created = false;
try { synchronized (r.stats.getBatteryStats()) { r.stats.startLaunchedLocked(); } mAm.notifyPackageUse(r.serviceInfo.packageName, PackageManager.NOTIFY_PACKAGE_USE_SERVICE); // 设置process的状态为start service // 这样在更新进程优先级的时候会有对应的处理,其实就是会提升优先级 app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE); // 到APP的进程中了,执行IApplicationThread.scheduleCreateService app.thread.scheduleCreateService(r, r.serviceInfo, mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo), app.repProcState); r.postNotification(); created = true; } catch (DeadObjectException e) { // 发现执行过程中进程挂掉了,需要处理后事,主要是进程中一些状态的清除 Slog.w(TAG, "Application dead when creating service " + r); mAm.appDiedLocked(app); throw e; } finally { if (!created) { final boolean inDestroying = mDestroyingServices.contains(r); serviceDoneExecutingLocked(r, inDestroying, inDestroying); if (newService) { app.services.remove(r); r.app = null; } if (!inDestroying) { scheduleServiceRestartLocked(r, false); } } }if (r.whitelistManager) {
app.whitelistManager = true; }requestServiceBindingsLocked(r, execInFg);
// 更新绑定的activity,这块主要针对bindService updateServiceClientActivitiesLocked(app, null, true); // 如果需要执行service的start则加入到pendingStarts // r.startRequested在startServiceLocked就标记了 // 且startServiceLocked时就已经加入到pendingStarts if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) { r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(), null, null, 0)); } // 这里将会执行service.onStartCommand sendServiceArgsLocked(r, execInFg, true); ... // delay相关 }
小结:
开始计算service “create”的ANR计时
调用到app进程创建并执行service的onCreate sendServiceArgsLocked4.8 ActiveServices.sendServiceArgsLocked
private final void sendServiceArgsLocked(ServiceRecord r, boolean execInFg,
boolean oomAdjusted) throws TransactionTooLargeException { // startServiceLocked时已经加入到pendingStarts 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 (si.intent == null && N > 1) { continue; } si.deliveredTime = SystemClock.uptimeMillis(); r.deliveredStarts.add(si); si.deliveryCount++; if (si.neededGrants != null) { mAm.grantUriPermissionUncheckedFromIntentLocked(si.neededGrants, si.getUriPermissionsLocked()); } mAm.grantEphemeralAccessLocked(r.userId, si.intent, r.appInfo.uid, UserHandle.getAppId(si.callingId)); // 再次开始ANR的计时,不过此处计时是“start” bumpServiceExecutingLocked(r, execInFg, "start"); if (!oomAdjusted) { oomAdjusted = true; mAm.updateOomAdjLocked(r.app, true); } // O上开始,调用startForegroundService需要5s内调用startForeground // 如果调用startForegroundService就处于r.fgRequired // 此处是如果发现需要调用startForeground但是没调,则认为超时了 if (r.fgRequired && !r.fgWaiting) { if (!r.isForeground) { scheduleServiceForegroundTransitionTimeoutLocked(r); } else { r.fgRequired = false; } } int flags = 0; if (si.deliveryCount > 1) { flags |= Service.START_FLAG_RETRY; } if (si.doneExecutingCount > 0) { flags |= Service.START_FLAG_REDELIVERY; } // 创建ServiceStartArgs args.add(new ServiceStartArgs(si.taskRemoved, si.id, flags, si.intent)); }ParceledListSlice<ServiceStartArgs> slice = new ParceledListSlice<>(args);
slice.setInlineCountLimit(4); Exception caughtException = null; try { // 调度到APP进程执行scheduleServiceArgs(将会执行service.onStartCommand) r.app.thread.scheduleServiceArgs(r, slice); } catch (TransactionTooLargeException e) { scheduleServiceArgs ... } // 如果发生了异常需要停掉service if (caughtException != null) { 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; } } }
小结:
开始service“start”的ANR计时
创建ServiceStartArgs 调度到app进程执行service的onStartCommand4.9 ActivityThread.handleCreateService
public final void scheduleCreateService(IBinder token,
ServiceInfo info, CompatibilityInfo compatInfo, int processState) { updateProcessState(processState, false); CreateServiceData s = new CreateServiceData(); s.token = token; s.info = info; s.compatInfo = compatInfo; sendMessage(H.CREATE_SERVICE, s); } public void handleMessage(Message msg) { switch (msg.what) { ... case CREATE_SERVICE: Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, ("serviceCreate: " + String.valueOf(msg.obj))); handleCreateService((CreateServiceData)msg.obj); Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); break; ... }private void handleCreateService(CreateServiceData data) {
unscheduleGcIdler();LoadedApk packageInfo = getPackageInfoNoCheck(
data.info.applicationInfo, data.compatInfo); Service service = null; try { java.lang.ClassLoader cl = packageInfo.getClassLoader(); service = (Service) cl.loadClass(data.info.name).newInstance(); } catch (Exception e) { if (!mInstrumentation.onException(service, e)) { throw new RuntimeException( "Unable to instantiate service " + data.info.name + ": " + e.toString(), e); } }try {
ContextImpl context = ContextImpl.createAppContext(this, packageInfo); context.setOuterContext(service); // 创建application Application app = packageInfo.makeApplication(false, mInstrumentation); // 执行service attach service.attach(context, this, data.info.name, data.token, app, ActivityManager.getService()); // 执行service的onCreate service.onCreate(); mServices.put(data.token, service); try { ActivityManager.getService().serviceDoneExecuting( data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } catch (Exception e) { if (!mInstrumentation.onException(service, e)) { throw new RuntimeException( "Unable to create service " + data.info.name + ": " + e.toString(), e); } } } app进程中binder线程调度过来之后,发送消息到主线程执行handleCreateService,在handleCreateService中终于看到了我们熟悉的onCreate了 处理完了service的生命周期,还要告诉ams,我处理完了,因为那边还在进行service的ANR计时呢 4.10 ActivityThread.handleServiceArgsprivate 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; } // 这里在前面讲解SharedPreferences的时候有提到,是在等待sp的任务写入完成 QueuedWork.waitToFinish(); try { ActivityManager.getService().serviceDoneExecuting( data.token, SERVICE_DONE_EXECUTING_START, data.startId, res); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } ensureJitEnabled(); } catch (Exception e) { if (!mInstrumentation.onException(s, e)) { throw new RuntimeException( "Unable to start service " + s + " with " + data.args + ": " + e.toString(), e); } } } }
scheduleServiceArgs中同样是发送消息到app主线程然后执行scheduleServiceArgs
scheduleServiceArgs中执行service.onStartCommand,然后告诉AMS执行完毕 4.11 ActivityManagerService.serviceDoneExecutingpublic 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"); } // ActiveSercices.serviceDoneExecutingLocked mServices.serviceDoneExecutingLocked((ServiceRecord)token, type, startId, res); } }
4.12 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) { r.callStart = true; // 这里的res是onStartCommand的返回值 switch (res) { case Service.START_STICKY_COMPATIBILITY: case Service.START_STICKY: { r.findDeliveredStart(startId, true); r.stopIfKilled = false; break; } case Service.START_NOT_STICKY: { r.findDeliveredStart(startId, true); if (r.getLastStartId() == startId) { r.stopIfKilled = true; } break; } case Service.START_REDELIVER_INTENT: { ServiceRecord.StartItem si = r.findDeliveredStart(startId, false); if (si != null) { si.deliveryCount = 0; si.doneExecutingCount++; r.stopIfKilled = true; } break; } case Service.START_TASK_REMOVED_COMPLETE: { r.findDeliveredStart(startId, true); break; } default: throw new IllegalArgumentException( "Unknown service start result: " + res); } if (res == Service.START_STICKY_COMPATIBILITY) { r.callStart = false; } } else if (type == ActivityThread.SERVICE_DONE_EXECUTING_STOP) { if (!inDestroying) { if (r.app != null) { Slog.w(TAG, "Service done with onDestroy, but not inDestroying: " + r + ", app=" + r.app); } } else if (r.executeNesting != 1) { Slog.w(TAG, "Service done with onDestroy, but executeNesting=" + r.executeNesting + ": " + r); r.executeNesting = 1; } } final long origId = Binder.clearCallingIdentity(); serviceDoneExecutingLocked(r, inDestroying, inDestroying); Binder.restoreCallingIdentity(origId); } else { Slog.w(TAG, "Done executing unknown service from pid " + Binder.getCallingPid()); } }
其中的res处理:
如果是START_STICKY_COMPATIBILITY或者START_STICKY那么如果进程挂掉了,service依旧会重启,很多app会利用这个进行保活。 在其中的serviceDoneExecutingLocked会把前面的计时消息给remove掉,如果service的生命周期在规定时间内执行完毕,就不会ANR了。总结
startService过程中如果进程不存在会创建进程
service不存在时默认情况下会先执行service的onCreate,再执行service的onStartCommand service存在时只会执行service的onStartCommand service的onCreate和onStartCommand都会被ANR计时监控,规定时间内没有处理完就会超时 onStartCommand处理之后还要等待sp写入完毕才会返回ams,所以不适合在onStartCommand中做大量的sp操作,即使是用的是apply异步进行 onStartCommand的返回值可以控制service是否在进程被kill之后依旧重启service