本文基于 Android 7.1.1 源码分析,转载请说明出处!
0 综述 我们通过 startService
启动的服务,需要通过 stopService
来停止:
1 context.stopService(intent);
以前我们只是会调用,但是其底层的调用到底是什么样的呢?知其然知其所以然,今天我们就来学习下 stopService
的过程!
如果之前并不了解这块逻辑的话,那该如何去学习呢? follow the funtion path!
1 发起端进程 1.1 ContextWrapper.stopService 1 2 3 4 5 6 7 8 9 10 11 12 13 public class ContextWrapper extends Context { Context mBase; public ContextWrapper (Context base) { mBase = base; } @Override public boolean stopService (Intent name) { return mBase.stopService(name); } }
ContextWrapper
提供了两个方法来启动 Service
,其中一个是隐藏方法:startServiceAsUser
!
mBase
是 ContextImpl
对象,继续看!
1.2 ContextImpl.stopService 1 2 3 4 5 6 7 8 9 10 11 class ContextImpl extends Context { @Override public boolean stopService (Intent service) { warnIfCallingFromSystemProcess(); return stopServiceCommon(service, mUser); } }
这里调用了 warnIfCallingFromSystemProcess
,判断是否是系统进程调用!1 2 3 4 5 6 private void warnIfCallingFromSystemProcess () { if (Process.myUid() == Process.SYSTEM_UID) { Slog.w(TAG, "Calling a method in the system process without a qualified user: " + Debug.getCallers(5 )); } }
ContextImpl
和 ContextWrapper
的具体关系,请来看另一博文:Android
系统的 Context
分析,这里我们不再详细说明!
mUser
:表示的是当前的设备 user
!
最终,调用了 stopServiceCommon
方法;
1.3 ContextImpl.stopServiceCommon 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 private boolean stopServiceCommon (Intent service, UserHandle user) { try { validateServiceIntent(service); service.prepareToLeaveProcess(this ); int res = ActivityManagerNative.getDefault().stopService( mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded(getContentResolver()), user.getIdentifier()); if (res < 0 ) { throw new SecurityException( "Not allowed to stop service " + service); } return res != 0 ; } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } }
validateServiceIntent 方法用用来校验启动用的 intent 是否安全:1 2 3 4 5 6 7 8 9 10 11 12 private void validateServiceIntent (Intent service) { if (service.getComponent() == null && service.getPackage() == null ) { if (getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.LOLLIPOP) { IllegalArgumentException ex = new IllegalArgumentException( "Service Intent must be explicit: " + service); throw ex; } else { Log.w(TAG, "Implicit intents with startService are not safe: " + service + " " + Debug.getCallers(2 , 3 )); } } }
如果 intent
既没有设置 component
也没有设置 package
,那就要判断一下系统的版本了:
如果系统版本不低于 L
,那就要抛出异常,提示必须是显示启动;
如果系统版本低于 L
,那只提示隐式启动不安全;
接着,调用 ActivityManagerNative.getDefault()
方法,获得 AMS
的代理对象 ActivityManagerProxy
!
ActivityManagerProxy
是 ActivityManagerN
的内部类,通过 getDefault
方法创建了对应的单例模式,保存在 ActivityManagerNative
的类变量 getDefault
中!
1.4 ActivityManagerP.stopService 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 public int stopService (IApplicationThread caller, Intent service, String resolvedType, int userId) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); data.writeInterfaceToken(IActivityManager.descriptor); data.writeStrongBinder(caller != null ? caller.asBinder() : null ); service.writeToParcel(data, 0 ); data.writeString(resolvedType); data.writeInt(userId); mRemote.transact(STOP_SERVICE_TRANSACTION, data, reply, 0 ); reply.readException(); int res = reply.readInt(); reply.recycle(); data.recycle(); return res; }
通过 binder
进程间通信,进入系统进程,参数分析:
IApplicationThread caller
:调用者进程的 ApplicationThread
对象,实现了 IApplicationThread
接口;
Intent service
:启动的 intent
;
String resolvedType
:这个 intent
的 MIME
类型;
String callingPackage
:启动者所属包名;
int userId
:设备用户 id
;
2 系统进程 接下来,进入系统进程的 ActivityManagerService
中!
首先要进入 ActivityManagerN.onTransact
方法!1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 case STOP_SERVICE_TRANSACTION: { data.enforceInterface(IActivityManager.descriptor); IBinder b = data.readStrongBinder(); IApplicationThread app = ApplicationThreadNative.asInterface(b); Intent service = Intent.CREATOR.createFromParcel(data); String resolvedType = data.readString(); int userId = data.readInt(); int res = stopService(app, service, resolvedType, userId); reply.writeNoException(); reply.writeInt(res); return true ; }
2.1 ActivityManagerS.stopService 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 @Override public int stopService (IApplicationThread caller, Intent service, String resolvedType, int userId) { enforceNotIsolatedCaller("stopService" ); if (service != null && service.hasFileDescriptors() == true ) { throw new IllegalArgumentException("File descriptors passed in Intent" ); } synchronized (this ) { return mServices.stopServiceLocked(caller, service, resolvedType, userId); } }
mServices
是 ActivityManagerService
的一个内部管理对象,用于管理所有的 Service
!
2.2 ActiveServices.stopServiceLocked 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 int stopServiceLocked (IApplicationThread caller, Intent service, String resolvedType, int userId) { if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "stopService: " + service + " type=" + resolvedType); final ProcessRecord callerApp = mAm.getRecordForAppLocked(caller); if (caller != null && callerApp == null ) { throw new SecurityException( "Unable to find app for caller " + caller + " (pid=" + Binder.getCallingPid() + ") when stopping service " + service); } ServiceLookupResult r = retrieveServiceLocked(service, resolvedType, null , Binder.getCallingPid(), Binder.getCallingUid(), userId, false , 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 ; }
2.2.1 ActiveServices.retrieveServiceLocked 根据 intent
来查询被启动服务的 ServiceRecord
对象,参数传递:
boolean createIfNeeded
:传入的是 true
;
boolean callingFromFg
:表示是从前台调用,还是后台调用;
boolean isBindExternal
:表示 bind
的是否是 isolated
, external
类型的服务,我们这里默认为 false
;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 private ServiceLookupResult retrieveServiceLocked (Intent service, String resolvedType, String callingPackage, int callingPid, int callingUid, int userId, boolean createIfNeeded, boolean callingFromFg, boolean isBindExternal) { ServiceRecord r = null ; if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "retrieveServiceLocked: " + service + " type=" + resolvedType + " callingUid=" + callingUid); userId = mAm.mUserController.handleIncomingUser(callingPid, callingUid, userId, false , ActivityManagerService.ALLOW_NON_FULL_IN_PROFILE, "service" , null ); ServiceMap smap = getServiceMap(userId); final ComponentName comp = service.getComponent(); if (comp != null ) { r = smap.mServicesByName.get(comp); } if (r == null && !isBindExternal) { Intent.FilterComparison filter = new Intent.FilterComparison(service); r = smap.mServicesByIntent.get(filter); } if (r != null && (r.serviceInfo.flags & ServiceInfo.FLAG_EXTERNAL_SERVICE) != 0 && !callingPackage.equals(r.packageName)) { r = null ; } if (r == null ) { try { ResolveInfo rInfo = AppGlobals.getPackageManager().resolveService(service, resolvedType, ActivityManagerService.STOCK_PM_FLAGS | PackageManager.MATCH_DEBUG_TRIAGED_MISSING, userId); 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 name = new ComponentName( sInfo.applicationInfo.packageName, sInfo.name); if ((sInfo.flags & ServiceInfo.FLAG_EXTERNAL_SERVICE) != 0 ) { if (isBindExternal) { if (!sInfo.exported) { throw new SecurityException("BIND_EXTERNAL_SERVICE failed, " + name + " is not exported" ); } if ((sInfo.flags & ServiceInfo.FLAG_ISOLATED_PROCESS) == 0 ) { throw new SecurityException("BIND_EXTERNAL_SERVICE failed, " + name + " is not an isolatedProcess" ); } ApplicationInfo aInfo = AppGlobals.getPackageManager().getApplicationInfo( callingPackage, ActivityManagerService.STOCK_PM_FLAGS, userId); if (aInfo == null ) { throw new SecurityException("BIND_EXTERNAL_SERVICE failed, " + "could not resolve client package " + callingPackage); } sInfo = new ServiceInfo(sInfo); sInfo.applicationInfo = new ApplicationInfo(sInfo.applicationInfo); sInfo.applicationInfo.packageName = aInfo.packageName; sInfo.applicationInfo.uid = aInfo.uid; name = new ComponentName(aInfo.packageName, name.getClassName()); service.setComponent(name); } else { throw new SecurityException("BIND_EXTERNAL_SERVICE required for " + name); } } else if (isBindExternal) { throw new SecurityException("BIND_EXTERNAL_SERVICE failed, " + name + " is not an externalService" ); } if (userId > 0 ) { if (mAm.isSingleton(sInfo.processName, sInfo.applicationInfo, sInfo.name, sInfo.flags) && mAm.isValidSingletonCall(callingUid, sInfo.applicationInfo.uid)) { userId = 0 ; smap = getServiceMap(0 ); } sInfo = new ServiceInfo(sInfo); sInfo.applicationInfo = mAm.getAppInfoForUser(sInfo.applicationInfo, userId); } r = smap.mServicesByName.get(name); if (r == null && createIfNeeded) { Intent.FilterComparison filter = new Intent.FilterComparison(service.cloneFilter()); ServiceRestarter res = new ServiceRestarter(); BatteryStatsImpl.Uid.Pkg.Serv ss = null ; BatteryStatsImpl stats = mAm.mBatteryStatsService.getActiveStatistics(); synchronized (stats) { ss = stats.getServiceStatsLocked( sInfo.applicationInfo.uid, sInfo.packageName, sInfo.name); } r = new ServiceRecord(mAm, ss, name, filter, sInfo, callingFromFg, res); res.setService(r); smap.mServicesByName.put(name, r); smap.mServicesByIntent.put(filter, r); for (int i=mPendingServices.size()-1 ; i>=0 ; i--) { ServiceRecord pr = mPendingServices.get(i); if (pr.serviceInfo.applicationInfo.uid == sInfo.applicationInfo.uid && pr.name.equals(name)) { mPendingServices.remove(i); } } } } catch (RemoteException ex) { } } if (r != null ) { if (mAm.checkComponentPermission(r.permission, callingPid, callingUid, r.appInfo.uid, r.exported) != PackageManager.PERMISSION_GRANTED) { if (!r.exported) { Slog.w(TAG, "Permission Denial: Accessing service " + r.name + " from pid=" + callingPid + ", uid=" + callingUid + " that is not exported from uid " + r.appInfo.uid); return new ServiceLookupResult(null , "not exported from uid " + r.appInfo.uid); } Slog.w(TAG, "Permission Denial: Accessing service " + r.name + " from pid=" + callingPid + ", uid=" + callingUid + " requires " + r.permission); return new ServiceLookupResult(null , r.permission); } else if (r.permission != null && callingPackage != null ) { final int opCode = AppOpsManager.permissionToOpCode(r.permission); if (opCode != AppOpsManager.OP_NONE && mAm.mAppOpsService.noteOperation( opCode, callingUid, callingPackage) != AppOpsManager.MODE_ALLOWED) { Slog.w(TAG, "Appop Denial: Accessing service " + r.name + " from pid=" + callingPid + ", uid=" + callingUid + " requires appop " + AppOpsManager.opToName(opCode)); return null ; } } if (!mAm.mIntentFirewall.checkService(r.name, service, callingUid, callingPid, resolvedType, r.appInfo)) { return null ; } return new ServiceLookupResult(r, null ); } return null ; }
这个方法的最终目的是返回要启动的服务的信息封装对象 ServiceLookupResult!
2.3 ActiveServices.stopServiceLocked 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 private void stopServiceLocked (ServiceRecord service) { if (service.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 ); }
2.4 ActiveServices.bringDownServiceIfNeededLocked 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 private final void bringDownServiceIfNeededLocked (ServiceRecord r, boolean knowConn, boolean hasConn) { if (isServiceNeeded(r, knowConn, hasConn)) { return ; } if (mPendingServices.contains(r)) { return ; } bringDownServiceLocked(r); }
如果这个服务仍然被需要,或者服务所在的进程正在启动,这两种情况下,不能停止服务!
2.4.1 ActiveServices.isServiceNeeded 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 private final boolean isServiceNeeded (ServiceRecord r, boolean knowConn, boolean hasConn) { if (r.startRequested) { return true ; } if (!knowConn) { hasConn = r.hasAutoCreateConnections(); } if (hasConn) { return true ; } return false ; }
判断一个服务是否仍被需要,有两种情况:
服务已经被请求启动,stopService
前面会被置为 false
;
服务被应用通过自动创建的方式绑定,即 bindService
时,flags
为 Context.BIND_AUTO_CREATE
;
继续来看!
2.5 ActiveServices.bringDownServiceLocked 我们来看看 bringDownServiceLocked 方法做了什么:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 private final void bringDownServiceLocked (ServiceRecord r) { 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); 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); } } } 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); } } } } if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Bringing down " + r + " " + r.intent); r.destroyTime = SystemClock.uptimeMillis(); if (LOG_SERVICE_START_STOP) { EventLogTags.writeAmDestroyService( r.userId, System.identityHashCode(r), (r.app != null ) ? r.app.pid : -1 ); } 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); } } cancelForegroudNotificationLocked(r); r.isForeground = false ; r.foregroundId = 0 ; r.foregroundNoti = null ; r.clearDeliveredStartsLocked(); r.pendingStarts.clear(); if (r.app != null ) { synchronized (r.stats.getBatteryStats()) { r.stats.stopLaunchedLocked(); } r.app.services.remove(r); if (r.whitelistManager) { updateWhitelistManagerLocked(r.app); } 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); } if (r.bindings.size() > 0 ) { r.bindings.clear(); } if (r.restarter instanceof ServiceRestarter) { ((ServiceRestarter)r.restarter).setService(null ); } int memFactor = mAm.mProcessStats.getMemFactorLocked(); long now = SystemClock.uptimeMillis(); if (r.tracker != null ) { r.tracker.setStarted(false , memFactor, now); r.tracker.setBound(false , memFactor, now); if (r.executeNesting == 0 ) { r.tracker.clearCurrentOwner(r, false ); r.tracker = null ; } } smap.ensureNotStartingBackground(r); }
这段代码很简单,主要逻辑如下:
首先进入绑定服务的应用进程,回调 ServiceConnection 的 onServiceDisconnected 方法,取消所有进程对该服务的绑定;
接着,进入服务所在的进程,拉起服务的 onUnbind 方法;
最后,拉起服务的 onDestroy 方法,销毁服务;
整个过程,还会清空和重置一些关键变量!!
下面我们重点分析一下上面的三个过程!
3 绑定者进程 系统进程会调用 IServiceConnection.Proxy 代理对象的 connected 方法,通过 binder 调用,进入绑定服务的应用进程,这个是异步调用:
1 cr.conn.connected(r.name, null );
我们去看看!
3.1 InnerConnection.connected 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 private static class InnerConnection extends IServiceConnection .Stub { final WeakReference<LoadedApk.ServiceDispatcher> mDispatcher; InnerConnection(LoadedApk.ServiceDispatcher sd) { mDispatcher = new WeakReference<LoadedApk.ServiceDispatcher>(sd); } public void connected (ComponentName name, IBinder service) throws RemoteException { LoadedApk.ServiceDispatcher sd = mDispatcher.get(); if (sd != null ) { sd.connected(name, service); } } }
继续来看:
3.2 ServiceDispatcher.connected 1 2 3 4 5 6 7 8 9 public void connected (ComponentName name, IBinder service) { if (mActivityThread != null ) { mActivityThread.post(new RunConnection(name, service, 0 )); } else { doConnected(name, service); } }
看过 bindService 一文的朋友,应该知道,最后都会调用 doConnected 方法:
3.3 ServiceDispatcher.doConnected 参数 service 这里为 null!1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 public void doConnected (ComponentName name, IBinder service) { ServiceDispatcher.ConnectionInfo old; ServiceDispatcher.ConnectionInfo info; synchronized (this ) { if (mForgotten) { return ; } old = mActiveConnections.get(name); if (old != null && old.binder == service) { return ; } if (service != null ) { info = new ConnectionInfo(); info.binder = service; info.deathMonitor = new DeathMonitor(name, service); try { service.linkToDeath(info.deathMonitor, 0 ); mActiveConnections.put(name, info); } catch (RemoteException e) { mActiveConnections.remove(name); return ; } } else { mActiveConnections.remove(name); } if (old != null ) { old.binder.unlinkToDeath(old.deathMonitor, 0 ); } } if (old != null ) { mConnection.onServiceDisconnected(name); } if (service != null ) { mConnection.onServiceConnected(name, service); } }
这里,最后会进入应用的 ServiceConnection 对象!1 2 3 4 5 6 private ServiceConnection mConnection = new ServiceConnection() { @Override public void onServiceDisconnected (ComponentName name) { } }
注意,onServiceDisconnected 方法是非阻塞的,即,系统进程不会等 onServiceDisconnected 执行完才继续执行!!
4 服务所在进程 我们先回到系统进程 bringDownServiceLocked 方法中:1 2 3 4 5 6 7 8 r.app.thread.scheduleUnbindService(r, ibr.intent.getIntent()); ... ... ... ... r.app.thread.scheduleStopService(r);
这两个方法,都通过 ApplicationThreadProxy 对象进行 bind 通信,我们下面来逐个分析:
4.1 ApplicationThread.scheduleUnbindService 参数 IBinder token 就是 ServiceRecord 对象!
1 2 3 4 5 6 7 8 9 10 11 12 13 public final void scheduleUnbindService (IBinder token, Intent intent) throws RemoteException { Parcel data = Parcel.obtain(); data.writeInterfaceToken(IApplicationThread.descriptor); data.writeStrongBinder(token); intent.writeToParcel(data, 0 ); mRemote.transact(SCHEDULE_UNBIND_SERVICE_TRANSACTION, data, null , IBinder.FLAG_ONEWAY); data.recycle(); }
可以看出 scheduleUnbindService 方法的 binder 通信是 IBinder.FLAG_ONEWAY 方式!
4.2 ApplicationThreadP.scheduleStopService 参数 IBinder token 就是 ServiceRecord 对象!
1 2 3 4 5 6 7 8 9 10 11 12 public final void scheduleStopService (IBinder token) throws RemoteException { Parcel data = Parcel.obtain(); data.writeInterfaceToken(IApplicationThread.descriptor); data.writeStrongBinder(token); mRemote.transact(SCHEDULE_STOP_SERVICE_TRANSACTION, data, null , IBinder.FLAG_ONEWAY); data.recycle(); }
可以看出 scheduleStopService 方法的 binder 通信是 IBinder.FLAG_ONEWAY 方式!
下面是真正进入了应用程序进程 !
4.3 ApplicationThreadN.onTransact 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 case SCHEDULE_UNBIND_SERVICE_TRANSACTION: { data.enforceInterface(IApplicationThread.descriptor); IBinder token = data.readStrongBinder(); Intent intent = Intent.CREATOR.createFromParcel(data); scheduleUnbindService(token, intent); return true ; } case SCHEDULE_STOP_SERVICE_TRANSACTION:{ data.enforceInterface(IApplicationThread.descriptor); IBinder token = data.readStrongBinder(); scheduleStopService(token); return true ; }
4.4 ApplicationThread 接着,进入 ApplicationThread!!
4.4.1 ApplicationThread.scheduleUnbindService 1 2 3 4 5 6 7 8 9 10 public final void scheduleUnbindService (IBinder token, Intent intent) { BindServiceData s = new BindServiceData(); s.token = token; s.intent = intent; sendMessage(H.UNBIND_SERVICE, s); }
4.4.2 ApplicationThread.scheduleStopService 1 2 3 4 5 public final void scheduleStopService (IBinder token) { sendMessage(H.STOP_SERVICE, token); }
4.5 ActivityThread.H 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 private class H extends Handler { public void handleMessage (Message msg) { case UNBIND_SERVICE: Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceUnbind" ); handleUnbindService((BindServiceData)msg.obj); Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); break ; case STOP_SERVICE: Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceStop" ); handleStopService((IBinder)msg.obj); maybeSnapshot(); Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); break ; } }
这里很简单,我们继续看:
4.5.1 ActivityThread.handleUnbindService 首先会拉起 Serivce 的 onUnbind 方法!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 private void handleUnbindService (BindServiceData data) { Service s = mServices.get(data.token); if (s != null ) { try { data.intent.setExtrasClassLoader(s.getClassLoader()); data.intent.prepareToEnterProcess(); boolean doRebind = s.onUnbind(data.intent); try { if (doRebind) { ActivityManagerNative.getDefault().unbindFinished( data.token, data.intent, doRebind); } else { ActivityManagerNative.getDefault().serviceDoneExecuting( data.token, SERVICE_DONE_EXECUTING_ANON, 0 , 0 ); } } catch (RemoteException ex) { throw ex.rethrowFromSystemServer(); } } catch (Exception e) { if (!mInstrumentation.onException(s, e)) { throw new RuntimeException( "Unable to unbind to service " + s + " with " + data.intent + ": " + e.toString(), e); } } } }
如果 onUnbind 方法返回 true,并且服务被解绑后没有被销毁,下次被绑定时,会拉起 onRebind 方法!
4.5.2 ActivityThread.handleStopService 最后,拉起 Serivce 的 onDestroy 方法!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 private void handleStopService (IBinder token) { Service s = mServices.remove(token); if (s != null ) { try { if (localLOGV) Slog.v(TAG, "Destroying service " + s); s.onDestroy(); Context context = s.getBaseContext(); if (context instanceof ContextImpl) { final String who = s.getClassName(); ((ContextImpl) context).scheduleFinalCleanup(who, "Service" ); } QueuedWork.waitToFinish(); try { ActivityManagerNative.getDefault().serviceDoneExecuting( token, SERVICE_DONE_EXECUTING_STOP, 0 , 0 ); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } catch (Exception e) { if (!mInstrumentation.onException(s, e)) { throw new RuntimeException( "Unable to stop service " + s + ": " + e.toString(), e); } Slog.i(TAG, "handleStopService: exception for " + token, e); } } else { Slog.i(TAG, "handleStopService: token=" + token + " not found." ); } }
这里逻辑很清楚,我们继续来看,接下来,调用 ActivityManagerP 相关的方法!
4.6 ActivityManagerProxy 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 public void unbindFinished (IBinder token, Intent intent, boolean doRebind) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); data.writeInterfaceToken(IActivityManager.descriptor); data.writeStrongBinder(token); intent.writeToParcel(data, 0 ); data.writeInt(doRebind ? 1 : 0 ); mRemote.transact(UNBIND_FINISHED_TRANSACTION, data, reply, 0 ); reply.readException(); data.recycle(); reply.recycle(); } public void serviceDoneExecuting (IBinder token, int type, int startId, int res) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); data.writeInterfaceToken(IActivityManager.descriptor); data.writeStrongBinder(token); data.writeInt(type); data.writeInt(startId); data.writeInt(res); mRemote.transact(SERVICE_DONE_EXECUTING_TRANSACTION, data, reply, IBinder.FLAG_ONEWAY); reply.readException(); data.recycle(); reply.recycle(); }
发送了 UNBIND_FINISHED_TRANSACTION 和 SERVICE_DONE_EXECUTING_TRANSACTION 消息!
unbindFinished 的 binder 通信是同步的,serviceDoneExecuting 的 binder 通信是异步的!
5 系统进程 首先会进入 ActivityManagerNative 的 onTransact 方法中:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 case UNBIND_FINISHED_TRANSACTION: { data.enforceInterface(IActivityManager.descriptor); IBinder token = data.readStrongBinder(); Intent intent = Intent.CREATOR.createFromParcel(data); boolean doRebind = data.readInt() != 0 ; unbindFinished(token, intent, doRebind); reply.writeNoException(); return true ; } case SERVICE_DONE_EXECUTING_TRANSACTION: { data.enforceInterface(IActivityManager.descriptor); IBinder token = data.readStrongBinder(); int type = data.readInt(); int startId = data.readInt(); int res = data.readInt(); serviceDoneExecuting(token, type, startId, res); reply.writeNoException(); return true ; }
接下来,进入 AMS!
5.1 ActivityManagerS.unbindFinished 1 2 3 4 5 6 7 8 9 10 11 12 13 public void unbindFinished (IBinder token, Intent intent, boolean doRebind) { if (intent != null && intent.hasFileDescriptors() == true ) { throw new IllegalArgumentException("File descriptors passed in Intent" ); } synchronized (this ) { mServices.unbindFinishedLocked((ServiceRecord)token, intent, doRebind); } }
5.1.1 ActiveServices.unbindFinishedLocked 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 void unbindFinishedLocked (ServiceRecord r, Intent intent, boolean doRebind) { final long origId = Binder.clearCallingIdentity(); try { if (r != null ) { Intent.FilterComparison filter = new Intent.FilterComparison(intent); IntentBindRecord b = r.bindings.get(filter); if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "unbindFinished in " + r + " at " + b + ": apps=" + (b != null ? b.apps.size() : 0 )); boolean inDestroying = mDestroyingServices.contains(r); if (b != null ) { if (b.apps.size() > 0 && !inDestroying) { boolean inFg = false ; for (int i=b.apps.size()-1 ; i>=0 ; i--) { ProcessRecord client = b.apps.valueAt(i).client; if (client != null && client.setSchedGroup != ProcessList.SCHED_GROUP_BACKGROUND) { inFg = true ; break ; } } try { requestServiceBindingLocked(r, b, inFg, true ); } catch (TransactionTooLargeException e) { } } else { b.doRebind = true ; } } serviceDoneExecutingLocked(r, inDestroying, false ); } } finally { Binder.restoreCallingIdentity(origId); } }
接着来看!
5.1.2 ActiveServices.serviceDoneExecutingLocked 参数传递:
boolean inDestroying:传入 false;
boolean finishing:传入 false;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 private void serviceDoneExecutingLocked (ServiceRecord r, boolean inDestroying, boolean finishing) { if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "<<< DONE EXECUTING " + r + ": nesting=" + r.executeNesting + ", inDestroying=" + inDestroying + ", app=" + r.app); else if (DEBUG_SERVICE_EXECUTING) Slog.v(TAG_SERVICE_EXECUTING, "<<< DONE EXECUTING " + r.shortName); r.executeNesting--; if (r.executeNesting <= 0 ) { if (r.app != null ) { if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Nesting at 0 of " + r.shortName); r.app.execServicesFg = false ; r.app.executingServices.remove(r); if (r.app.executingServices.size() == 0 ) { if (DEBUG_SERVICE || DEBUG_SERVICE_EXECUTING) Slog.v(TAG_SERVICE_EXECUTING, "No more executingServices of " + r.shortName); mAm.mHandler.removeMessages(ActivityManagerService.SERVICE_TIMEOUT_MSG, r.app); } else if (r.executeFg) { 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); } r.executeFg = false ; if (r.tracker != null ) { r.tracker.setExecuting(false , mAm.mProcessStats.getMemFactorLocked(), SystemClock.uptimeMillis()); if (finishing) { r.tracker.clearCurrentOwner(r, false ); r.tracker = null ; } } if (finishing) { if (r.app != null && !r.app.persistent) { r.app.services.remove(r); if (r.whitelistManager) { updateWhitelistManagerLocked(r.app); } } r.app = null ; } } }
这里就不再详细说了!!
5.2 ActivityManagerS.serviceDoneExecuting 对于拉起 onDestroy 方法,最后会调用1 2 3 4 5 6 7 8 9 10 11 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.2.1 ActiveServices.serviceDoneExecutingLocked 根据参数传递:
int type :传入 ActivityThread.SERVICE_DONE_EXECUTING_STOP;
int startId :传入 0;
int res :传入 0;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 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) { 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()); } }
5.2.2 ActiveServices.serviceDoneExecutingLocked 参数传递:
boolean inDestroying:传入 true;
boolean finishing:传入 true;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 private void serviceDoneExecutingLocked (ServiceRecord r, boolean inDestroying, boolean finishing) { if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "<<< DONE EXECUTING " + r + ": nesting=" + r.executeNesting + ", inDestroying=" + inDestroying + ", app=" + r.app); else if (DEBUG_SERVICE_EXECUTING) Slog.v(TAG_SERVICE_EXECUTING, "<<< DONE EXECUTING " + r.shortName); r.executeNesting--; if (r.executeNesting <= 0 ) { if (r.app != null ) { if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Nesting at 0 of " + r.shortName); r.app.execServicesFg = false ; r.app.executingServices.remove(r); if (r.app.executingServices.size() == 0 ) { if (DEBUG_SERVICE || DEBUG_SERVICE_EXECUTING) Slog.v(TAG_SERVICE_EXECUTING, "No more executingServices of " + r.shortName); mAm.mHandler.removeMessages(ActivityManagerService.SERVICE_TIMEOUT_MSG, r.app); } else if (r.executeFg) { 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); } r.executeFg = false ; if (r.tracker != null ) { r.tracker.setExecuting(false , mAm.mProcessStats.getMemFactorLocked(), SystemClock.uptimeMillis()); if (finishing) { r.tracker.clearCurrentOwner(r, false ); r.tracker = null ; } } if (finishing) { if (r.app != null && !r.app.persistent) { r.app.services.remove(r); if (r.whitelistManager) { updateWhitelistManagerLocked(r.app); } } r.app = null ; } } }
到这里,stopService 的整个过程,就分析完了!!
6 总结 我们来回顾一下,整个 stopService 的过程,都遇到了那些重要的数据结构!