Service对于Android开发来说再熟悉不过了,不过大部分人对Service的了解也仅限于api,这篇文章,我们通过分析AMS的源码,从一个更高的高度来了解一下Service的整个生命周期。
Service的生命周期接口:
1. startService
2. bindService
3. stopService
4. unbindService
这几个接口在apk进程里调用,通过ActivityManagerNative这个Binder最后调用到ActivityManagerService里,而AMS管理Service的类是ActiveService,这个类接管了所有Service生命周期的函数,包括startServiceLocked、stopServiceLocked、bindServiceLocked、unbindServiceLocked等。
startServiceLocked:
该函数实现Service的启动,首先调用retrieveServiceLocked根据Intent查询ServiceLookupResult(主要字段ServiceRecord),查询是先在ServiceMap里找,没有就重新由PackageManager的resolveService来获得ResolveInfo,创建新的ServiceRecord。针对Service的case,startService分为下面三种case,1,caller app是前台应用或者Service所在的app的进程优先级较高(高于PROCESS_STATE_SERVICE), 那么无限制的start。2,其他情况的Service作为background service,会加入到mStartingBackground list里,如果starting list的size没有达到上限,那么直接启动。3,此时starting list已到上限,那么此Service的start会推迟,Service会加到mDelayedStartList里。
ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType, int callingPid, int callingUid, String callingPackage, int userId) throws TransactionTooLargeException { ...... ...... // 检查caller app是否是前台进程 final boolean callerFg; if (caller != null) { final ProcessRecord callerApp = mAm.getRecordForAppLocked(caller); if (callerApp == null) { throw new SecurityException( "Unable to find app for caller " + caller + " (pid=" + Binder.getCallingPid() + ") when starting service " + service); } callerFg = callerApp.setSchedGroup != Process.THREAD_GROUP_BG_NONINTERACTIVE; } else { callerFg = true; } // 查找ServiceRecord ServiceLookupResult res = retrieveServiceLocked(service, resolvedType, callingPackage, callingPid, callingUid, userId, true, callerFg); ...... ...... ServiceRecord r = res.record; ...... ...... r.lastActivity = SystemClock.uptimeMillis(); r.startRequested = true; r.delayedStop = false; r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(), service, neededGrants)); final ServiceMap smap = getServiceMap(r.userId); boolean addToStarting = false; if (!callerFg && r.app == null && mAm.mStartedUsers.get(r.userId) != null) { ProcessRecord proc = mAm.getProcessRecordLocked(r.processName, r.appInfo.uid, false); if (proc == null || proc.curProcState > ActivityManager.PROCESS_STATE_RECEIVER) { // 这个分支表示Service所在的进程不存在,或者进程优先级小于PROCESS_STATE_RECEIVER,说明这个Service是background service ...... // 如果Service在delayed start list,则直接返回 if (r.delayed) { if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE, "Continuing to delay: " + r); return r.name; } // 如果后starting background list超上限,则加到mDelayedStartList,暂时不startService,直接返回 if (smap.mStartingBackground.size() >= mMaxStartingBackground) { // Something else is starting, delay! Slog.i(TAG_SERVICE, "Delaying start of: " + r); smap.mDelayedStartList.add(r); r.delayed = true; return r.name; } if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE, "Not delaying: " + r); addToStarting = true; } else if (proc.curProcState >= ActivityManager.PROCESS_STATE_SERVICE) { // 这个分支表示Service所在的进程优先级小于PROCESS_STATE_SERVICE,但又比PROCESS_STATE_RECEIVER大,加到starting list里,并startService addToStarting = true; if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE, "Not delaying, but counting as bg: " + r); } else if (DEBUG_DELAYED_STARTS) { StringBuilder sb = new StringBuilder(128); sb.append("Not potential delay (state=").append(proc.curProcState) .append(' ').append(proc.adjType); String reason = proc.makeAdjReason(); if (reason != null) { sb.append(' '); sb.append(reason); } sb.append("): "); sb.append(r.toString()); Slog.v(TAG_SERVICE, sb.toString()); } } ...... ...... // 分支走到这里等于startService会成功,addToStarting表示是否加到StartingBackground List return startServiceInnerLocked(smap, service, r, callerFg, addToStarting); }Service的start是由函数startServiceInnerLocked完成,而startServiceInnerLocked则是调用bringUpServiceLocked完成Service的start,每次startService都会往ServiceRecord的pendingStarts里填加一项StartItem,即使是被放入Delayed List的Service启动。bringUpServiceLocked做的事就是拉起Service。
一,如果进程r.app和r.app.thread已经初始化(代表着Service之前已经Create过),那么bringUpServiceLocked只需要执行onStartCommand,这是通过调用sendServiceArgsLocked来实现,sendServiceArgsLocked就遍历之前pendingStarts的所有StartItem(每个startService都会对应一个StartItem),逐个调用app.thread.scheduleServiceArgs。app.thread是Service所在进程的IApplicationThread Binder对象,用于AMS的SystemServer进程到Client App端的跨进程调用,IApplicationThread的实现是在ActivityThread的内部类ApplicationThread,AMS -> ActivityThread的调用通过IApplicationThread,ActivityThread -> AMS的调用就是ActivityManagerNative,这样就打通了一条从AMS到ActivityThread的跨进程调用之路。scheduleServiceArgs在ActivityThread里的对应就是ActivityThread.handleServiceArgs,这就执行到了我们所熟悉的onStartCommand。至此可以解释两个我们对于Service的认知:1,每次startService,都会对应一次onStartCommand,就算Service已经onCreate成功。2,Service的回调函数都是在主线程,这个和ApplicationThread这个Binder Client的执行线程一致。sendServiceArgsLocked之后,pendingStarts里的StartItem就被加入到了deliveredStarts里,等待后续stopService或者Service restart的时候用。
二,如果Service所在的进程已经创建(ProcessRecord不空),那么会调用realStartServiceLocked来启动Service,这时的Service是还没有调用过onCreate。realStartServiceLocked会调用app.thread.scheduleCreateService来完成Service的启动,scheduleCreateService同scheduleServiceArgs一样,会调用到ActivityThread里,最终会执行Service的onCreate。之后同样执行sendServiceArgsLocked回调到onStartCommand。
三,如果Service所在的进程还未创建,那么bringUpServiceLocked做的事就是调用AMS的startProcessLocked创建进程,并将Service放进mPendingServices,等待进程创建成功,调用attachApplicationLocked的时候,会遍历所有的mPendingServices,继续调用realStartServiceLocked来完成Service的启动。
最后再看看bringUpServiceLocked的代码来加深一下印象
private final String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg, boolean whileRestarting) throws TransactionTooLargeException { // Service已经启动过了,直接调用sendServiceArgsLocked来执行onStartCommand if (r.app != null && r.app.thread != null) { sendServiceArgsLocked(r, execInFg, false); return null; } // Service正在restart,啥都不做,等restart定时器触发以后再start if (!whileRestarting && r.restartDelay > 0) { // If waiting for a restart, then do nothing. return null; } if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Bringing up " + r + " " + r.intent); // 从正在重启的Service列表里删除 if (mRestartingServices.remove(r)) { r.resetRestartCounter(); clearRestartingIfNeededLocked(r); } // 已经start了,从mDelayedStartList里删除 if (r.delayed) { if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE, "REM FR DELAY LIST (bring up): " + r); getServiceMap(r.userId).mDelayedStartList.remove(r); r.delayed = false; } ...... ...... final boolean isolated = (r.serviceInfo.flags&ServiceInfo.FLAG_ISOLATED_PROCESS) != 0; final String procName = r.processName; ProcessRecord app; if (!isolated) { app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false); if (DEBUG_MU) Slog.v(TAG_MU, "bringUpServiceLocked: appInfo.uid=" + r.appInfo.uid + " app=" + app); // 如果进程已经创建,那么可以执行startService了,先执行Service的onCreate,再执行onStartCommand if (app != null && app.thread != null) { try { app.addPackage(r.appInfo.packageName, r.appInfo.versionCode, mAm.mProcessStats); realStartServiceLocked(r, app, execInFg); return null; } catch (TransactionTooLargeException e) { throw e; } catch (RemoteException e) { Slog.w(TAG, "Exception when starting service " + r.shortName, e); } // If a dead object exception was thrown -- fall through to // restart the application. } } else { // 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; } // 如果进程还没创建,调用startProcessLocked来创建进程,并加入到mPendingServices,等待attachApplicationLocked后再startService if (app == null) { if (app=mAm.startProcessLocked(procName, r.appInfo, true, intentFlags, "service", 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; } } 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) { if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE, "Applying delayed stop (in bring up): " + r); stopServiceLocked(r); } } return null; }bindServiceLocked :bindServiceLocked比startService要复杂很多,主要是其多了Service和App之间的绑定关系:
1,AppBindRecord
retrieveServiceLocked查找到ServiceRecord之后,生成Service和Client(callerApp)之间的绑定关系AppBindRecord,AppBindRecord的字段包括service,client,intent,确定了他们之间的绑定关系。
final class AppBindRecord { final ServiceRecord service; // The running service. final IntentBindRecord intent; // The intent we are bound to. final ProcessRecord client; // Who has started/bound the service. } 2,ConnectionRecordService和Client之间一个绑定关系就会对应一个ConnectionRecord,ConnectionRecord字段里除了绑定关系等对象之外,还有一个比较重要的对象就是IServiceConnection,这是一个binder对象,用做Client端和Server端的桥接,IServiceConnection的定义在LoadedApk里,处理ServiceConnection的connected状态,并由ServiceDispatcher统一做Service连接分发,如果connected函数的第二个参数IBinder是空,那么就是调用回调函数onServiceDisconnected,不空则表示连接建立成功,调用onServiceConnected。在ServiceConnection创建成功时,ServiceDispatcher会注册这个Service的死亡通知,如果Service crash,也会马上调用onServiceDisconnected。
private static class InnerConnection extends IServiceConnect.Stub { final WeakReference<LoadedApk.ServiceDispatcher> mDispatcher; InnerConnection(LoadedApk.ServiceDispatcher sd) { this.mDispatcher = new WeakReference(sd); } public void connected(ComponentName name, IBinder service) throws RemoteException { LoadedApk.ServiceDispatcher sd = (LoadedApk.ServiceDispatcher)this.mDispatcher.get(); if(sd != null) { sd.connected(name, service); } } } static final class ServiceDispatcher { public void connected(ComponentName name, IBinder service) { if(this.mActivityThread != null) { this.mActivityThread.post(new LoadedApk.ServiceDispatcher.RunConnection(name, service, 0)); } else { this.doConnected(name, service); } } public void death(ComponentName name, IBinder service) { synchronized(this) { this.mDied = true; LoadedApk.ServiceDispatcher.ConnectionInfo old = (LoadedApk.ServiceDispatcher.ConnectionInfo)this.mActiveConnections.remove(name); if(old == null || old.binder != service) { return; } old.binder.unlinkToDeath(old.deathMonitor, 0); } if(this.mActivityThread != null) { this.mActivityThread.post(new LoadedApk.ServiceDispatcher.RunConnection(name, service, 1)); } else { this.doDeath(name, service); } } public void doConnected(ComponentName name, IBinder service) { LoadedApk.ServiceDispatcher.ConnectionInfo old; synchronized(this) { if(this.mForgotten) { return; } old = (LoadedApk.ServiceDispatcher.ConnectionInfo)this.mActiveConnections.get(name); if(old != null && old.binder == service) { return; } if(service != null) { this.mDied = false; LoadedApk.ServiceDispatcher.ConnectionInfo info = new LoadedApk.ServiceDispatcher.ConnectionInfo(); info.binder = service; info.deathMonitor = new LoadedApk.ServiceDispatcher.DeathMonitor(name, service); try { service.linkToDeath(info.deathMonitor, 0); this.mActiveConnections.put(name, info); } catch (RemoteException var8) { this.mActiveConnections.remove(name); return; } } else { this.mActiveConnections.remove(name); } if(old != null) { old.binder.unlinkToDeath(old.deathMonitor, 0); } } if(old != null) { this.mConnection.onServiceDisconnected(name); } if(service != null) { this.mConnection.onServiceConnected(name, service); } } public void doDeath(ComponentName name, IBinder service) { this.mConnection.onServiceDisconnected(name); } private final class DeathMonitor implements DeathRecipient { final ComponentName mName; final IBinder mService; DeathMonitor(ComponentName name, IBinder service) { this.mName = name; this.mService = service; } public void binderDied() { ServiceDispatcher.this.death(this.mName, this.mService); } }3,connections
AppBindRecord的connections字段则保存了这个client的所有ServiceConnection连接ConnectionRecord,ConnectionRecord和IServiceConnection对象是对应的。ServiceRecord也有个connections列表,但ServiceRecord的connections列表存储的是这个Service相关的所有ConnectionRecord,Service和Client之间是多对多的关系,所以其各自维护了一个connections。ConnectionRecord和AppBindRecord初始化完之后,就进入Service的主题,如果bindService的flag加上了BIND_AUTO_CREATE,那么将马上调用bringUpServiceLocked来启动Service,否则不会主动startService,这种情况如果之前Service并没有启动过,那么bind操作就会失败。之后检查Service是否绑定过,没有绑定过或者需要重新绑定的时候,由requestServiceBindingLocked来实际bindService,最后通过app.thread.scheduleBindService完成Service的绑定。并通过c.conn.connected调用,通知Client的IServiceConnection.onServiceConnected。从而完成Service和Client之间的Bind。
stopServiceLocked:
private void stopServiceLocked(ServiceRecord service) { // 如果Service还未start,那么置delayedStop为true,等startService结束以后调用stopServiceLocked if (service.delayed) { // If service isn't actually running, but is is being held in the // delayed list, then we need to keep it started but note that it // should be stopped once no longer delayed. if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE, "Delaying stop of pending: " + service); service.delayedStop = true; return; } synchronized (service.stats.getBatteryStats()) { service.stats.stopRunningLocked(); } service.startRequested = false; if (service.tracker != null) { service.tracker.setStarted(false, mAm.mProcessStats.getMemFactorLocked(), SystemClock.uptimeMillis()); } service.callStart = false; bringDownServiceIfNeededLocked(service, false, false); }stopServiceLocked是调用bringDownServiceLocked来停止Service。首先对这个Service的所有bind连接,都通知回调onServiceDisconnected,之后通过调用r.app.thread.scheduleStopService,通知Service进程stopService,Service的onDestroy会被调用。 private final void bringDownServiceLocked(ServiceRecord r) { // 对这个Service的每个绑定连接都通知client端回调onServiceDisconnected for (int conni=r.connections.size()-1; conni>=0; conni--) { ArrayList<ConnectionRecord> c = r.connections.valueAt(conni); for (int i=0; i<c.size(); i++) { ConnectionRecord cr = c.get(i); // There is still a connection to the service that is // being brought down. Mark it as dead. cr.serviceDead = true; try { cr.conn.connected(r.name, null); } catch (Exception e) { Slog.w(TAG, "Failure disconnecting service " + r.name + " to connection " + c.get(i).conn.asBinder() + " (in " + c.get(i).binding.client.processName + ")", e); } } } // 通过scheduleUnbindService,通知Service进程回调onBind if (r.app != null && r.app.thread != null) { for (int i=r.bindings.size()-1; i>=0; i--) { IntentBindRecord ibr = r.bindings.valueAt(i); if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Bringing down binding " + ibr + ": hasBound=" + ibr.hasBound); if (ibr.hasBound) { try { bumpServiceExecutingLocked(r, false, "bring down unbind"); mAm.updateOomAdjLocked(r.app); ibr.hasBound = false; r.app.thread.scheduleUnbindService(r, ibr.intent.getIntent()); } catch (Exception e) { Slog.w(TAG, "Exception when unbinding service " + r.shortName, e); serviceProcessGoneLocked(r); } } } } // 已经unbind了,mPendingServices的列表可以清空了 for (int i=mPendingServices.size()-1; i>=0; i--) { if (mPendingServices.get(i) == r) { mPendingServices.remove(i); if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Removed pending: " + r); } } r.cancelNotification(); r.isForeground = false; r.foregroundId = 0; r.foregroundNoti = null; // Clear start entries. r.clearDeliveredStartsLocked(); r.pendingStarts.clear(); if (r.app != null) { // 调用r.app.thread.scheduleStopService,通知Service进程stopService,Service的onDestroy会被调用 r.app.services.remove(r); if (r.app.thread != null) { updateServiceForegroundLocked(r.app, false); try { bumpServiceExecutingLocked(r, false, "destroy"); mDestroyingServices.add(r); r.destroying = true; mAm.updateOomAdjLocked(r.app); r.app.thread.scheduleStopService(r); } catch (Exception e) { Slog.w(TAG, "Exception when destroying service " + r.shortName, e); serviceProcessGoneLocked(r); } } else { if (DEBUG_SERVICE) Slog.v( TAG_SERVICE, "Removed service that has no process: " + r); } } else { if (DEBUG_SERVICE) Slog.v( TAG_SERVICE, "Removed service that is not running: " + r); } ...... ...... } unbindService:unbindService就比较简单了,把参数IServiceConnection对应的ConnectionRecord列表,逐个调用removeConnectionLocked移除连接,而removeConnectionLocked其实就是之前bindService时初始化AppBindRecord相关对象的逆过程,把和这个需要unbind的IServiceConnection连接从各个数据结构里删掉。移除完之后,如果发现这个Service已经没有任何Client绑定在其上面,就会调用s.app.thread.scheduleUnbindService,通知Service的进程执行onUnbind。
boolean unbindServiceLocked(IServiceConnection connection) { IBinder binder = connection.asBinder(); if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "unbindService: conn=" + binder); ArrayList<ConnectionRecord> clist = mServiceConnections.get(binder); if (clist == null) { Slog.w(TAG, "Unbind failed: could not find connection for " + connection.asBinder()); return false; } final long origId = Binder.clearCallingIdentity(); try { while (clist.size() > 0) { ConnectionRecord r = clist.get(0); // 移除ConnectionRecord removeConnectionLocked(r, null, null); if (clist.size() > 0 && clist.get(0) == r) { // In case it didn't get removed above, do it now. Slog.wtf(TAG, "Connection " + r + " not removed for binder " + binder); clist.remove(0); } if (r.binding.service.app != null) { // This could have made the service less important. if ((r.flags&Context.BIND_TREAT_LIKE_ACTIVITY) != 0) { r.binding.service.app.treatLikeActivity = true; mAm.updateLruProcessLocked(r.binding.service.app, r.binding.service.app.hasClientActivities || r.binding.service.app.treatLikeActivity, null); } // 重新更新各进程的oom_adj mAm.updateOomAdjLocked(r.binding.service.app); } } } finally { Binder.restoreCallingIdentity(origId); } return true; }至此,我们介绍了AMS是怎么管理Service的整个生命周期,之前文章 Android的LowMemoryKiller杀进程策略 介绍LMK杀进程的时候,有个foreground的oom_adj级别对应的case就是executingServices的size大于0的情况,在Service的startService、stopService、bindService、unBindService的时候都会将Service加入到executingServices里,通过ServiceRecord.app.thread回调到Service的Client进程之后,都会调用ActivityManagerNative.getDefault().serviceDoneExecuting,执行到AMS进程里,再将这个Service从executingServices里删除。加到executingServices里之后,会有个超时时间(callerApp是前台的话是20秒,后台是200秒),超时则触发ANR。executingServices不空就表示,Service的生命周期还未走完,Service的Client进程还未收到回调,此时把其oom_adj下调到前台App的级别,以保证Service生命周期的完整性也是很合理的策略。
Service还有个特点是杀掉后是可以重启的,最后我们简单介绍一下这个重启策略。Service的死分为两种,一种是自己crash,一种是被LMK kill。Android进程刚创建的时候,ActivityManagerService在attachApplication方法里会注册该进程的死亡通知,所以不论那种死法,AMS都会通过死亡通知获得回调,从而根据一定的策略来重启进程。
private final boolean attachApplicationLocked(IApplicationThread thread, int pid) { ...... ...... try { AppDeathRecipient adr = new AppDeathRecipient( app, pid, thread); thread.asBinder().linkToDeath(adr, 0); app.deathRecipient = adr; } catch (RemoteException e) { app.resetPackageList(mProcessStats); startProcessLocked(app, "link fail", processName); return false; } ...... ...... }AMS的死亡通知类定义如下:
private final class AppDeathRecipient implements IBinder.DeathRecipient { final ProcessRecord mApp; final int mPid; final IApplicationThread mAppThread; AppDeathRecipient(ProcessRecord app, int pid, IApplicationThread thread) { if (DEBUG_ALL) Slog.v( TAG, "New death recipient " + this + " for thread " + thread.asBinder()); mApp = app; mPid = pid; mAppThread = thread; } @Override public void binderDied() { if (DEBUG_ALL) Slog.v( TAG, "Death received in " + this + " for thread " + mAppThread.asBinder()); synchronized(ActivityManagerService.this) { appDiedLocked(mApp, mPid, mAppThread, true); } } }一旦进程死掉,就会调用appDiedLocked来处理,如果是Home App挂了的话,进程就会马上重启。 final void appDiedLocked(ProcessRecord app, int pid, IApplicationThread thread, boolean fromBinderDied) { // First check if this ProcessRecord is actually active for the pid. synchronized (mPidsSelfLocked) { ProcessRecord curProc = mPidsSelfLocked.get(pid); if (curProc != app) { Slog.w(TAG, "Spurious death for " + app + ", curProc for " + pid + ": " + curProc); return; } } BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics(); synchronized (stats) { stats.noteProcessDiedLocked(app.info.uid, pid); } if (!app.killed) { // 如果不是死亡通知调用的,那么就执行Process.killProcessQuiet杀死进程 if (!fromBinderDied) { Process.killProcessQuiet(pid); } killProcessGroup(app.info.uid, pid); app.killed = true; } // Clean up already done if the process has been re-started. if (app.pid == pid && app.thread != null && app.thread.asBinder() == thread.asBinder()) { boolean doLowMem = app.instrumentationClass == null; boolean doOomAdj = doLowMem; boolean homeRestart = false; if (!app.killedByAm) { // 桌面App死了,需马上重启 if (mHomeProcessName != null && app.processName.equals(mHomeProcessName)) { mHomeKilled = true; homeRestart = true; } Slog.i(TAG, "Process " + app.processName + " (pid " + pid + ") has died"); mAllowLowerMemLevel = true; } else { // Note that we always want to do oom adj to update our state with the // new number of procs. mAllowLowerMemLevel = false; doLowMem = false; } EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.userId, app.pid, app.processName); if (DEBUG_CLEANUP) Slog.v(TAG_CLEANUP, "Dying app: " + app + ", pid: " + pid + ", thread: " + thread.asBinder()); handleAppDiedLocked(app, false, true); if (doOomAdj) { updateOomAdjLocked(); } if (doLowMem) { doLowMemReportIfNeededLocked(app); } if (mHomeKilled && homeRestart) { // 立即重启Home App Intent intent = getHomeIntent(); ActivityInfo aInfo = mStackSupervisor.resolveActivity(intent, null, 0, null, 0); startProcessLocked(aInfo.processName, aInfo.applicationInfo, true, 0, "activity", null, false, false, true); homeRestart = false; } } else if (app.pid != pid) { // A new process has already been started. Slog.i(TAG, "Process " + app.processName + " (pid " + pid + ") has died and restarted (pid " + app.pid + ")."); EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.userId, app.pid, app.processName); } else if (DEBUG_PROCESSES) { Slog.d(TAG_PROCESSES, "Received spurious death notification for thread " + thread.asBinder()); } } handleAppDiedLocked会调用mServices.killServicesLocked,在killServicesLocked里会根据具体情况来实施重启策略, final void killServicesLocked(ProcessRecord app, boolean allowRestart) { // 清除进程的所有Service connection for (int i = app.connections.size() - 1; i >= 0; i--) { ConnectionRecord r = app.connections.valueAt(i); removeConnectionLocked(r, app, null); } ...... ...... // Now do remaining service cleanup. for (int i=app.services.size()-1; i>=0; i--) { ServiceRecord sr = app.services.valueAt(i); // 除了persistent进程,其他的Service都清除,persitent是个高优先级的进程,不管oom_adj很小,LMK不会杀, // 而且PackageManagerService在installApk的时候也不会杀掉,这样就会导致persistent的进程升级不了,必须要重启系统 if (!app.persistent) { app.services.removeAt(i); } // Sanity check: if the service listed for the app is not one // we actually are maintaining, just let it drop. final ServiceRecord curRec = smap.mServicesByName.get(sr.name); if (curRec != sr) { if (curRec != null) { Slog.wtf(TAG, "Service " + sr + " in process " + app + " not same as in map: " + curRec); } continue; } // Service crash超过两次之后,Service被stop,不会再restart if (allowRestart && sr.crashCount >= 2 && (sr.serviceInfo.applicationInfo.flags &ApplicationInfo.FLAG_PERSISTENT) == 0) { Slog.w(TAG, "Service crashed " + sr.crashCount + " times, stopping: " + sr); EventLog.writeEvent(EventLogTags.AM_SERVICE_CRASHED_TOO_MUCH, sr.userId, sr.crashCount, sr.shortName, app.pid); bringDownServiceLocked(sr); } else if (!allowRestart || !mAm.isUserRunningLocked(sr.userId, false)) { bringDownServiceLocked(sr); } else { // 准备重启Service,重启的时间在scheduleServiceRestartLocked里设置 boolean canceled = scheduleServiceRestartLocked(sr, true); // 如果stopIfKilled设为true,后续没有再调用startService的情况下,也不会再重启Service,调用bringDownServiceLocked停止Service if (sr.startRequested && (sr.stopIfKilled || canceled)) { if (sr.pendingStarts.size() == 0) { sr.startRequested = false; if (sr.tracker != null) { sr.tracker.setStarted(false, mAm.mProcessStats.getMemFactorLocked(), SystemClock.uptimeMillis()); } if (!sr.hasAutoCreateConnections()) { // Whoops, no reason to restart! bringDownServiceLocked(sr); } } } } } ...... ...... // Make sure we have no more records on the stopping list. int i = mDestroyingServices.size(); while (i > 0) { i--; ServiceRecord sr = mDestroyingServices.get(i); if (sr.app == app) { sr.forceClearTracker(); mDestroyingServices.remove(i); if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "killServices remove destroying " + sr); } } app.executingServices.clear(); }如果crash次数超过2次,那么进程死掉的时候,Service就不会进入restart状态。scheduleServiceRestartLocked是处理service restart的函数,确定每个要重启的service准备restart的时间点。可以看到persitent的进程的优先级非常高,除了没有crash超过2次的限制外,restartDelay的值也会被设为0,也就是说马上restart,所以一旦persistent进入循环重启状态的时候,就出现无限重启,根本听不下来。
Service的生命周期管理就介绍到这儿,代码主要分布在ActivityManagerService、ActiveService、ActivityThread、LoadedApk等类中,看完之后,对Service的原理的了解就更加深刻了。
作者简介:
田力,网易彩票Android端创始人,小米视频创始人,现任roobo技术经理、视频云技术总监
欢迎关注微信公众号 磨剑石,定期推送技术心得以及源码分析等文章,谢谢