文中的源代码版本为api23
Service销毁流程
stopService流程
流程简图如下
Context.stopService
,该方法会经历以下方法调用 Context.stopService
-> ContextImpl.stopService
-> ContextImpl.stopServiceCommon
-> ActivityManagerService.stopServcie
-> ActiveServcie.stopServiceLocked
ActiveServcie.stopServiceLocked
int stopServiceLocked(IApplicationThread caller, Intent service, String resolvedType, int userId) { //... // If this service is active, make sure it is stopped. ServiceLookupResult r = retrieveServiceLocked(service, resolvedType, null, Binder.getCallingPid(), Binder.getCallingUid(), userId, false, false); if (r != null) { if (r.record != null) { final long origId = Binder.clearCallingIdentity(); try { stopServiceLocked(r.record); } finally { Binder.restoreCallingIdentity(origId); } return 1; } return -1; } return 0;}private void stopServiceLocked(ServiceRecord service) { //... //设置startRequested为false,在后面的流程中有用 service.startRequested = false; //... service.callStart = false; bringDownServiceIfNeededLocked(service, false, false);}复制代码
该方法逻辑比较简单,通过retrieveServiceLocked
方法找到服务记录,然后调用重载方法stopServiceLocked
继续下面的流程,该方法内部直接调用了bringDownServiceIfNeededLocked
ActiveServices.bringDownServiceIfNeededLocked
private final void bringDownServiceIfNeededLocked(ServiceRecord r, boolean knowConn/*false*/, boolean hasConn/*false*/) { //... //判断是否有bind if (isServiceNeeded(r, knowConn, hasConn)) { return; } // Are we in the process of launching? if (mPendingServices.contains(r)) { return; } bringDownServiceLocked(r);}复制代码
该方法做了三件事情
- 调用
isServiceNeeded
方法判断服务是否还有必要存在,如果有则直接返回 - 查看服务是否存在于待启动服务列表中,如果是则直接返回
- 上面的条件都不满足的话则会调用
bringDownServiceLocked
继续停止服务的流程
ActiveServices.isServiceNeeded
private final boolean isServiceNeeded(ServiceRecord r, boolean knowConn, boolean hasConn) { // 该字段在stopServiceLocked方法中已经被置为false if (r.startRequested) { return true; } // knowConn此时为false,所以会走这个if流程 if (!knowConn) { hasConn = r.hasAutoCreateConnections(); } if (hasConn) { return true; } return false;}//ServiceRecord.javapublic boolean hasAutoCreateConnections() { // XXX should probably keep a count of the number of auto-create // connections directly in the service. for (int conni=connections.size()-1; conni>=0; conni--) { ArrayListcr = connections.valueAt(conni); for (int i=0; i
isServiceNeeded
内部又调用了hasAutoCreateConnections
hasAutoCreateConnections
会检测当前服务的绑定记录(bindService
记录),在这些记录中只要有使用了带有BIND_AUTO_CREATE
标志的Intent
则返回true,表示不允许关闭服务。从这点可以看出,调用stopService
之后并不一定会真正的关闭服务。 假设服务未被绑定,我们继续下面的流程
ActiveServices.bringDownServiceLocked
private final void bringDownServiceLocked(ServiceRecord r) { for (int conni=r.connections.size()-1; conni>=0; conni--) { ArrayListc = r.connections.valueAt(conni); for (int i=0; i =0; i--) { IntentBindRecord ibr = r.bindings.valueAt(i); //... if (ibr.hasBound) { try { //... ibr.hasBound = false; //通过IPC触发Service.onUnbind方法 r.app.thread.scheduleUnbindService(r, ibr.intent.getIntent()); } catch (Exception e) { //... } } } } //... //清理服务记录 final ServiceMap smap = getServiceMap(r.userId); smap.mServicesByName.remove(r.name); smap.mServicesByIntent.remove(r.intent); r.totalRestartCount = 0; unscheduleServiceRestartLocked(r, 0, true); //从待启动流程中移除 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.clearDeliveredStartsLocked(); r.pendingStarts.clear(); if (r.app != null) { //... r.app.services.remove(r); if (r.app.thread != null) { //... try { //... mDestroyingServices.add(r); r.destroying = true; mAm.updateOomAdjLocked(r.app); //通过IPC触发Service.onDestory r.app.thread.scheduleStopService(r); } catch (Exception e) { //... } } else { //... } } else { //... } //...}复制代码
停止服务的逻辑还是挺清晰的
- 关闭所有的客户端连接,这个阶段就是通过IPC触发客户端的
ServiceConnection.onServiceDisconnected
- 通过IPC触发服务的
onUnbind
生命周期方法 - 清理一些资源
- 通过IPC触发服务的
onDestory
生命周期方法
此时服务就真正走向了生命的终点了。
unbindService流程
流程简图如下
Context.unbindService
方法会经历以下调用链 Context.unbindService
-> ContextImpl.unbindService
-> ActivityManagerService.unbindService
-> ActiveService.unbindServiceLocked
ActiveService.unbindServiceLocked
boolean unbindServiceLocked(IServiceConnection connection) { //对应于客户端的ServiceConnection IBinder binder = connection.asBinder(); //可以使用同一个ServiceConnection连接多个Service //因此这里拿出来是一个List ArrayListclist = mServiceConnections.get(binder); //... final long origId = Binder.clearCallingIdentity(); try { while (clist.size() > 0) { ConnectionRecord r = clist.get(0); removeConnectionLocked(r, null, null); //... } } finally { Binder.restoreCallingIdentity(origId); } return true;}复制代码
客户端的一个ServiceConnection
实例可以bind
至多个Service
,对应于AMS
这边就会保存多个ConnectionRecord
。 unbindServiceLocked
内使用了一个while
循环,依次对每个ConnectionRecord
调用removeConnectionLocked
。
ActiveServices.removeConnectionLocked
void removeConnectionLocked( ConnectionRecord c, ProcessRecord skipApp, ActivityRecord skipAct) { IBinder binder = c.conn.asBinder(); AppBindRecord b = c.binding; ServiceRecord s = b.service; //移除ServiceRecord以及客户端ProcessRecord等内部维护的 //ConnectionRecord ArrayListclist = s.connections.get(binder); if (clist != null) { clist.remove(c); if (clist.size() == 0) { s.connections.remove(binder); } } b.connections.remove(c); if (c.activity != null && c.activity != skipAct) { if (c.activity.connections != null) { c.activity.connections.remove(c); } } if (b.client != skipApp) { b.client.connections.remove(c); //... } clist = mServiceConnections.get(binder); if (clist != null) { clist.remove(c); if (clist.size() == 0) { mServiceConnections.remove(binder); } } //... if (b.connections.size() == 0) { b.intent.apps.remove(b.client); } //此处serviceDead为false if (!c.serviceDead) { //... if (s.app != null && s.app.thread != null && b.intent.apps.size() == 0 && b.intent.hasBound) { try { //... b.intent.hasBound = false; // Assume the client doesn't want to know about a rebind; // we will deal with that later if it asks for one. b.intent.doRebind = false; s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent()); } catch (Exception e) { Slog.w(TAG, "Exception when unbinding service " + s.shortName, e); serviceProcessGoneLocked(s); } } //这个flags就是调用bindService时用的flags if ((c.flags&Context.BIND_AUTO_CREATE) != 0) { boolean hasAutoCreate = s.hasAutoCreateConnections(); //... bringDownServiceIfNeededLocked(s, true, hasAutoCreate); } }}复制代码
removeConnectionLocked
首先会做一些清理工作,之后会调用ApplicationThread.scheduleUnbindService
方法触发Service.onUnbind
其次,如果发起bind
请求时所用的flags
中包含BIND_AUTO_CREATE
标志,还会触发bringDownServiceIfNeededLocked
hasAutoCreateConnections
和bringDownServiceIfNeededLocked
方法我们在分析stopService
流程的时候已经分析过了,就不展开讲了,这里只讨论bringDownServiceIfNeededLocked
入参变化而引起的一些变化。 假设当前没有其他客户端绑定至该服务,那么此时hasAutoCreate
应该为false
,那么bringDownServiceIfNeededLocked
的形参,knowConn
为true
,hasConn
为false
这两个参数,只会在bringDownServiceIfNeededLocked
内调用isServiceNeeded
方法使用到,再贴一下这个方法的代码
private final boolean isServiceNeeded(ServiceRecord r, boolean knowConn/*true*/, boolean hasConn/*false*/) { // startRequested只有在调用过startService才会被置为true // 这里为false if (r.startRequested) { return true; } // Is someone still bound to us keepign us running? if (!knowConn) { hasConn = r.hasAutoCreateConnections(); } if (hasConn) { return true; } return false;}复制代码
可以看到isServiceNeeded
此时返回false
,因此销毁的流程还会继续进行下去。 后续的流程就跟stopService
的一样了。