您的位置:首页 > 移动开发 > Android开发

Android Gems — AMS的Service生命周期管理

2016-11-22 19:11 316 查看
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,ConnectionRecord

Service和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技术经理、视频云技术总监

欢迎关注微信公众号 磨剑石,定期推送技术心得以及源码分析等文章,谢谢

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  android service