Service基础知识 Android Study Plan II - Service
Service工作过程 Service分为两种工作状态,一种是启动状态
,主要用于执行后台计算;另一种是绑定状态
,主要用于其他组件和Service的交互。
Service的这两种状态是可以共存的,即Service既可以处于启动状态也可以同时处于绑定状态。
1 2 3 4 5 6 7 //启动Service Intent intent= new Intent(this ,MyService.class); startService(intent); //绑定Service Intent intent= new Intent(this ,MyService.class); bindService(intent,mServiceConnection,BIND_AUTO_CREATE);
Service启动过程 - startService Service的启动过程从ContextWrapper.startService()
开始
1 2 3 4 5 6 // ../android/content/ContextWrapper.java Context mBase; @Override public ComponentName startService(Intent service) { return mBase.startService(service); }
在Activity启动的时候performLaunActivity
时,会创建上下文对象Context
,然后在Activity.attach()
调用了attachBaseContext()
将得到的contenxt进行赋值。最终操作的就是ContextImpl
。
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 // ../android/app/ContextImpl.jsvs @Override public ComponentName startService(Intent service) { warnIfCallingFromSystemProcess(); return startServiceCommon(service, false , mUser); } private ComponentName startServiceCommon(Intent service, boolean requireForeground, UserHandle user) { try { validateServiceIntent(service); service.prepareToLeaveProcess(this ); //启动Service ComponentName cn = ActivityManager.getService().startService( mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded( getContentResolver()), requireForeground, getOpPackageName(), user.getIdentifier()); if (cn != null ) { ... } return cn; } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } }
ActivityManager.getService()
在Activity启动过程中有介绍它是得到IActiivtyManager
实际就是指向AMS
的一个Binder对象,调用到的就是AMS.startService()
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 // ../core/java/com/android/server/am/ActivityManagerService.java @Override public ComponentName startService(IApplicationThread caller, Intent service, String resolvedType, boolean requireForeground, String callingPackage, int userId) throws TransactionTooLargeException { enforceNotIsolatedCaller("startService"); // Refuse possible leaked file descriptors if (service != null && service.hasFileDescriptors() == true ) { throw new IllegalArgumentException("File descriptors passed in Intent"); } if (callingPackage == null ) { throw new IllegalArgumentException("callingPackage cannot be null "); } if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "*** startService: " + service + " type=" + resolvedType + " fg=" + requireForeground); synchronized (this ) { final int callingPid = Binder.getCallingPid(); final int callingUid = Binder.getCallingUid(); final long origId = Binder.clearCallingIdentity(); ComponentName res; try { res = mServices.startServiceLocked(caller, service, resolvedType, callingPid, callingUid, requireForeground, callingPackage, userId); } finally { Binder.restoreCallingIdentity(origId); } return res; } }
mServices
的类型是ActiveServices
.ActiveServices
是一个辅助AMS
进行Service管理的类,其中包括Service的启动,绑定和停止等功能。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 // ../core/java/com/android/server/am/ActiveServices.java ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType, int callingPid, int callingUid, boolean fgRequired, String callingPackage, final int userId) throws TransactionTooLargeException { ... //去查找是否有与参数 service 对应的ServiceRecord。 ServiceLookupResult res = retrieveServiceLocked(service, resolvedType, callingPackage, callingPid, callingUid, userId, true , callerFg, false ); if (res == null ) { return null ; } if (res.record == null ) { return new ComponentName("!", res.permission != null ? res.permission : "private to package "); } //封装一个ServiceRecord对象 ServiceRecord r = res.record; ... ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting); }
ServiceRecord
描述的是一个Service记录,一直贯穿着整个Service的启动过程。
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 ComponentName startServiceInnerLocked(ServiceMap smap, Intent service, ServiceRecord r, boolean callerFg, boolean addToStarting) throws TransactionTooLargeException { ... String error = bringUpServiceLocked(r, service.getFlags(), callerFg, false , false ); if (error != null ) { return new ComponentName("!!", error); } ... return r.name; }private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg, boolean whileRestarting, boolean permissionsReviewRequired) throws TransactionTooLargeException { ... //获取Service想在那个进程中运行 process final String procName = r.processName; String hostingType = "service"; ProcessRecord app; //当前不止一个进程 if (!isolated) { //查询是否存在一个 与Service类型对应的ProcessRecord对象的app进程 app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false ); if (DEBUG_MU) Slog.v(TAG_MU, "bringUpServiceLocked: appInfo.uid=" + r.appInfo.uid + " app=" + app); //Service的运行进程已经存在 if (app != null && app.thread != null ) { try { app.addPackage(r.appInfo.packageName, r.appInfo.versionCode, mAm.mProcessStats); //启动service 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 { app = r.isolatedProc; if (WebViewZygote.isMultiprocessEnabled() && r.serviceInfo.packageName.equals(WebViewZygote.getPackageName())) { hostingType = "webview_service"; } } //没有对应的运行进程启动 if (app == null && !permissionsReviewRequired) { //需要新启动一个应用进程 承载Service 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; } } ... }
在bringUpServiceLocked()
中,优先获取Service需要的运行进程--通过android:process设置
,然后去判断当前进程中是否存在符合要求的
不存在,调用AMS.startProcessLocked()
去新建对应应用进程,这个函数在Activity启动过程中有讲解
存在,直接调用realStartServiceLocked()
去启动Service,命名方法类似Activity启动过程中的realStartActivityLocked()
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 private final void realStartServiceLocked(ServiceRecord r, ProcessRecord app, boolean execInFg) throws RemoteException { ... boolean created = false ; try { ... 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) { // Keep the executeNesting count accurate. final boolean inDestroying = mDestroyingServices.contains(r); serviceDoneExecutingLocked(r, inDestroying, inDestroying); // Cleanup. if (newService) { app.services.remove(r); r.app = null ; } // Retry. if (!inDestroying) { scheduleServiceRestartLocked(r, false ); } } } ... //由于 必须startRequested 参数为true 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 ); }private final void sendServiceArgsLocked(ServiceRecord r, boolean execInFg, boolean oomAdjusted) throws TransactionTooLargeException { ... //通知ActivityThread初始化已经完成,然后调用后续方法 r.app.thread.scheduleServiceArgs(r, slice); ... }
app.thread
是IApplicationThread
类型的,实际上是一个Binder对象,它的实现是ApplicationThread
,用于和ActivityThread
进行通信。
1 2 3 4 5 6 7 8 9 10 11 // ../android/app/ActivityThread.java 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); }
这里与Activity启动过程
是一致的,通过ActivityThread.H
这个Handler对象发送消息,切换到主线程去处理消息。这个发送的是CREATE_SERVICE
,最后调用到了ActivityThread.handleCreateService()
去启动Service
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 final ArrayMap<IBinder, Service> mServices = new ArrayMap<>(); private void handleCreateService(CreateServiceData data) { // If we are getting ready to gc after going to the background, well // we are back active so skip it. unscheduleGcIdler(); //获取LoaderApk对象 是一个Apk文件的描述器 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 { if (localLOGV) Slog.v(TAG, "Creating service " + data.info.name); //创建Service的ContextImpl对象 ContextImpl context = ContextImpl.createAppContext(this , packageInfo); context.setOuterContext(service); Application app = packageInfo.makeApplication(false , mInstrumentation); //初始化Service service.attach(context, this , data.info.name, data.token, app, ActivityManager.getService()); //调用 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); } } }
handleCreateService()
执行了以下的几件事:
通过类加载器创建Service
实例,Actiivty启动过程是利用了 Instrumention.newActivity() 执行相同创建实例
makeApplication()
创建Application
对象并调用其onCreate
创建ContextImpl
对象并调用Service.attach()
建立关系
最后调用Service.onCreate()
开始创建过程,并存储至ArrayMap<IBinder,Service>
中,在下一节会介绍这里存储数据的作用
调用onCreate()
之后,Service也已经启动了。
{% fullimage /images/Service启动过程.png,Service启动过程,Service启动过程%}
Service绑定过程 - bindService 和Service的启动过程一样,Service的绑定过程也是从ContextWrapper
开始
1 2 3 4 5 6 // ../android/content/ContextWrapper.java @Override public boolean bindService(Intent service, ServiceConnection conn, int flags) { return mBase.bindService(service, conn, flags); }
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 // ../android/app/ContextImpl.java @Override public boolean bindService(Intent service, ServiceConnection conn, int flags) { warnIfCallingFromSystemProcess(); return bindServiceCommon(service, conn, flags, mMainThread.getHandler(), Process.myUserHandle()); } private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags, Handler handler, UserHandle user) { IServiceConnection sd; if (conn == null ) { throw new IllegalArgumentException("connection is null "); } if (mPackageInfo != null ) { sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), handler, flags); } else { throw new RuntimeException("Not supported in system context"); } validateServiceIntent(service); try { ... service.prepareToLeaveProcess(this ); int res = ActivityManager.getService().bindService( mMainThread.getApplicationThread(), getActivityToken(), service, service.resolveTypeIfNeeded(getContentResolver()), sd, flags, getOpPackageName(), user.getIdentifier()); if (res < 0) { throw new SecurityException( "Not allowed to bind to service " + service); } return res != 0; } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } }
在bindServiceCommon()
主要做了两件事情:
getServiceDispatcher()
将传进来的ServiceConnection
转化成IServiceConnection
,通过Binder对象进行通信。使得Service的绑定支持跨进程调用。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 // ../android/app/LoaderApk.java public final IServiceConnection getServiceDispatcher(ServiceConnection c, Context context, Handler handler, int flags) { synchronized (mServices) { LoadedApk.ServiceDispatcher sd = null ; ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> map = mServices.get(context); if (map != null ) { if (DEBUG) Slog.d(TAG, "Returning existing dispatcher " + sd + " for conn " + c); sd = map.get(c); } if (sd == null ) { sd = new ServiceDispatcher(c, context, handler, flags); if (DEBUG) Slog.d(TAG, "Creating new dispatcher " + sd + " for conn " + c); if (map == null ) { map = new ArrayMap<>(); mServices.put(context, map); } map.put(c, sd); } else { sd.validate(context, handler); } return sd.getIServiceConnection(); } }
mServices
存储了一个应用当前活动的ServiceConnection和ServiceDispatcher
的映射关系。ServiceDispatcher
的作用是连接ServiceConnection和IServiceConnection。
bindService()
开始Service的绑定流程
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 // ../core/java/com/android/server/am/ActivityManagerService.java public int bindService(IApplicationThread caller, IBinder token, Intent service, String resolvedType, IServiceConnection connection, int flags, String callingPackage, int userId) throws TransactionTooLargeException { enforceNotIsolatedCaller("bindService"); // Refuse possible leaked file descriptors if (service != null && service.hasFileDescriptors() == true ) { throw new IllegalArgumentException("File descriptors passed in Intent"); } if (callingPackage == null ) { throw new IllegalArgumentException("callingPackage cannot be null "); } synchronized (this ) { return mServices.bindServiceLocked(caller, token, service, resolvedType, connection, flags, callingPackage, userId); } }
存储好对应的ServiceConnection
和ServiceDispatcher
映射的关系,之后开始继续绑定流程
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 // ../core/java/com/android/server/am/ActiveServices.java int bindServiceLocked(IApplicationThread caller, IBinder token, Intent service, String resolvedType, final IServiceConnection connection, int flags, String callingPackage, final int userId) throws TransactionTooLargeException { // 获取应用进程信息 final ProcessRecord callerApp = mAm.getRecordForAppLocked(caller); if (callerApp == null ) { throw new SecurityException( "Unable to find app for caller " + caller + " (pid=" + Binder.getCallingPid() + ") when binding service " + service); } //获取绑定Activity信息 ActivityRecord activity = null ; if (token != null ) { activity = ActivityRecord.isInStackLocked(token); if (activity == null ) { Slog.w(TAG, "Binding with unknown activity: " + token); return 0; } } //获取Service相关信息 ServiceRecord s = res.record; //启动Activity成功后 ,再启动Service if (mAm.mPermissionReviewRequired) { if (mAm.getPackageManagerInternalLocked().isPermissionsReviewRequired( s.packageName, s.userId)) { RemoteCallback callback = new RemoteCallback( new RemoteCallback.OnResultListener() { @Override public void onResult(Bundle result) { synchronized (mAm) { final long identity = Binder.clearCallingIdentity(); try { ... if (...) { try { // 启动 Service bringUpServiceLocked(...); } catch (RemoteException e) { /* ignore - local call */ } } else { ... } } finally { ... } } } }); final Intent intent = new Intent(Intent.ACTION_REVIEW_PERMISSIONS); // 注意 callback intent.putExtra(Intent.EXTRA_REMOTE_CALLBACK, callback); // 启动 Activity,成功启动后回调 callback mAm.mHandler.post(new Runnable() { @Override public void run() { mAm.mContext.startActivityAsUser(intent, new UserHandle(userId)); } }); } } try { // 如果设置了绑定后自动启动 if ((flags&Context.BIND_AUTO_CREATE) != 0) { s.lastActivity = SystemClock.uptimeMillis(); // 启动 Service if (bringUpServiceLocked(s, service.getFlags(), callerFg, false , permissionsReviewRequired) != null ) { return 0; } } // Service 已经在运行中,直接回调 onServiceConnected 即可 if (s.app != null && b.intent.received) { // Service is already running, so we can immediately // publish the connection. try { // 回调 onServiceConnected c.conn.connected(s.name, b.intent.binder, false ); } catch (Exception e) { ... } // if (b.intent.apps.size() == 1 && b.intent.doRebind) { requestServiceBindingLocked(s, b.intent, callerFg, true ); } ... //没有进行过绑定Service请求 } else if (!b.intent.requested) { // 回调 onBind,内部调用了 scheduleBindService requestServiceBindingLocked(s, b.intent, callerFg, false ); } ... } finally { Binder.restoreCallingIdentity(origId); } return 1; }
介绍几个与Service有关的对象类型:
ServiceRecord:描述一个Service
ProcessREcord:描述一个进程的信息
ConnectionRecord:描述应用程序进程和Service建立的一次通信。
AppBindRecord:维护Srvice与应用程序进程之间的关联。
IntentBindRecord:描述绑定Service的Intent
bindServiceLocked()
内部会通过bringUpServiceLocked()
自动启动Service。然后向下走启动Service流程
。
还会多调用一个requestServiceBindingLocked()
请求绑定过程
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 // ../core/java/com/android/server/am/ActiveServices.java private final boolean requestServiceBindingLocked(ServiceRecord r, IntentBindRecord i, boolean execInFg, boolean rebind/*是否重新绑定*/) throws TransactionTooLargeException { if (r.app == null || r.app.thread == null ) { // If service is not currently running, can't yet bind. return false ; } if (DEBUG_SERVICE) Slog.d(TAG_SERVICE, "requestBind " + i + ": requested=" + i.requested + " rebind=" + rebind); //是否发送过 绑定Service的请求 if ((!i.requested || rebind) && i.apps.size() > 0) { try { bumpServiceExecutingLocked(r, execInFg, "bind"); r.app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE); r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind, r.app.repProcState); if (!rebind) { i.requested = true ; } i.hasBound = true ; i.doRebind = false ; } catch (... ) {//最大通常限制为1M. ... } } return true ; }
app.thread
把逻辑切换到了 ActivityThread
中了
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 // ../android/app/ActivityThread.java public final void scheduleBindService(IBinder token, Intent intent, boolean rebind, int processState) { updateProcessState(processState, false ); BindServiceData s = new BindServiceData(); s.token = token; s.intent = intent; s.rebind = rebind; if (DEBUG_SERVICE) Slog.v(TAG, "scheduleBindService token=" + token + " intent=" + intent + " uid=" + Binder.getCallingUid() + " pid=" + Binder.getCallingPid()); sendMessage(H.BIND_SERVICE, s); } // 处理绑定Service流程private void handleBindService(BindServiceData data) { //获取要绑定的Service对象 Service s = mServices.get(data.token); if (DEBUG_SERVICE) Slog.v(TAG, "handleBindService s=" + s + " rebind=" + data.rebind); if (s != null ) { try { data.intent.setExtrasClassLoader(s.getClassLoader()); data.intent.prepareToEnterProcess(); try { //绑定Service if (!data.rebind) { //调用 onBind 方法,此时已绑定Service IBinder binder = s.onBind(data.intent); //通知绑定成功 ActivityManager.getService().publishService( data.token, data.intent, binder); } else { //执行重新绑定流程 s.onRebind(data.intent); ActivityManager.getService().serviceDoneExecuting( data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0); } ensureJitEnabled(); } catch (RemoteException ex) { throw ex.rethrowFromSystemServer(); } } catch (Exception e) { if (!mInstrumentation.onException(s, e)) { throw new RuntimeException( "Unable to bind to service " + s + " with " + data.intent + ": " + e.toString(), e); } } } }
Service.onRebind()
执行条件为:使用Service的流程是,先startService()
然后bindService()
,在Activity退出的时候,Service并不会停止,再进入Activity重新进行bindService()
,会触发onRebind()
方法。但是先前Activity退出时调用的onUnbind()
返回为true
,直接写死返回结果。
当多次绑定同一个Service时,onBind()
只会执行一次,除非Service被终止。
Service绑定通知 发现Service未绑定时,就会调用到onBind()
,Service就处于绑定状态,但是客户端无法感知到Service已经连接成功,所以需要AMS
进行通知。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 // ../core/java/com/android/server/am/ActivityManagerService.java public void publishService(IBinder token, Intent intent, IBinder service) { // Refuse possible leaked file descriptors if (intent != null && intent.hasFileDescriptors() == true ) { throw new IllegalArgumentException("File descriptors passed in Intent"); } synchronized (this ) { if (!(token instanceof ServiceRecord)) { throw new IllegalArgumentException("Invalid service token"); } mServices.publishServiceLocked((ServiceRecord)token, intent, service); } }
mServices
就是ActiveServices
对象,调用其内部的publishServiceLocked()
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 // ../core/java/com/android/server/am/ActiveServices.javavoid publishServiceLocked(ServiceRecord r, Intent intent, IBinder service) { final long origId = Binder.clearCallingIdentity(); try { ... for (int conni=r.connections.size()-1; conni>=0; conni--) { ArrayList<ConnectionRecord> clist = r.connections.valueAt(conni); for (int i=0; i<clist.size(); i++) { ConnectionRecord c = clist.get(i); try { c.conn.connected(r.name, service, false ); } catch (Exception e) { Slog.w(TAG, "Failure sending service " + r.name + " to connection " + c.conn.asBinder() + " (in " + c.binding.client.processName + ")", e); } } } } serviceDoneExecutingLocked(r, mDestroyingServices.contains(r), false ); } } finally { Binder.restoreCallingIdentity(origId); } }
c.conn
指向IServiceConnection
,他是ServiceConnection
在本地的代理对象,用于解决当前应用程序进程和Service跨进程通信的问题。
他的具体实现为ServiceDispatcher.InnerConnection
。
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 // ../android/app/LoaderApk.javastatic final class ServiceDispatcher { ... 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, boolean dead) throws RemoteException { LoadedApk.ServiceDispatcher sd = mDispatcher.get(); if (sd != null ) { sd.connected(name, service, dead); } } } public void connected(ComponentName name, IBinder service, boolean dead) { if (mActivityThread != null ) { mActivityThread.post(new RunConnection(name, service, 0, dead)); } else { doConnected(name, service, dead); } } ... }
mActivityThread
是一个Handler对象,指向的就是ActivityThread.H
。因此可以通过调用post()
直接发送RunConnection
对象的内容运行在主线程中。mActivityThread不可能为空。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 private final class RunConnection implements Runnable { RunConnection(ComponentName name, IBinder service, int command, boolean dead) { mName = name; mService = service; mCommand = command; mDead = dead; } public void run() { if (mCommand == 0) { doConnected(mName, mService, mDead); } else if (mCommand == 1) { doDeath(mName, mService); } } final ComponentName mName; final IBinder mService; final int mCommand; final boolean mDead; }
调用了RunConnection
实际上还是调用了doConnected()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 ServiceConnection mConnection;public void doConnected(ComponentName name, IBinder service, boolean dead) { ServiceDispatcher.ConnectionInfo old; ServiceDispatcher.ConnectionInfo info; synchronized (this ) { ... // 如果存在老Service 会优先断掉连接 if (old != null ) { mConnection.onServiceDisconnected(name); } // Service已消失 死亡回调 if (dead) { mConnection.onBindingDied(name); } // 全新的Service 通知绑定成功 if (service != null ) { mConnection.onServiceConnected(name, service); } }
1 2 3 4 5 6 7 8 9 10 11 12 //使用场景 private ServiceConnection mConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { //绑定成功回调 } @Override public void onServiceDisconnected(ComponentName name) { } };
Service解绑过程 - unbindService() Service的解绑过程也是从ContextWrapper
开始
1 2 3 4 @Overridepublic void unbindService(ServiceConnection conn) { mBase.unbindService(conn); }
实际调用的是ContextImpl.unbindService()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 // ../android/app/ContextImpl.java @Override public void unbindService(ServiceConnection conn) { if (conn == null ) { throw new IllegalArgumentException("connection is null "); } if (mPackageInfo != null ) { IServiceConnection sd = mPackageInfo.forgetServiceDispatcher( getOuterContext(), conn); try { ActivityManager.getService().unbindService(sd); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } else { throw new RuntimeException("Not supported in system context"); } }
这里主要分为两部分:
调用到ActiveServices.unbindServiceLocked()
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 // ../core/java/android/com/server/am/ActiveServices.java 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); //移除掉对应Service的绑定 removeConnectionLocked(r, null , null ); ... //从映射表中移除对应的ServiceConnection } mAm.updateOomAdjLocked(); } finally { Binder.restoreCallingIdentity(origId); } return true ; } void removeConnectionLocked( ConnectionRecord c, ProcessRecord skipApp, ActivityRecord skipAct) { IBinder binder = c.conn.asBinder(); AppBindRecord b = c.binding; ServiceRecord s = b.service; ArrayList<ConnectionRecord> clist = s.connections.get(binder); if (clist != null ) { clist.remove(c); if (clist.size() == 0) { s.connections.remove(binder); } } b.connections.remove(c); ... if (!c.serviceDead) { if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Disconnecting binding " + b.intent + ": shouldUnbind=" + b.intent.hasBound); if (s.app != null && s.app.thread != null && b.intent.apps.size() == 0 && b.intent.hasBound) { try { bumpServiceExecutingLocked(s, false , "unbind"); if (b.client != s.app && (c.flags&Context.BIND_WAIVE_PRIORITY) == 0 && s.app.setProcState <= ActivityManager.PROCESS_STATE_RECEIVER) { // If this service's process is not already in the cached list, // then update it in the LRU list here because this may be causing // it to go down there and we want it to start out near the top. mAm.updateLruProcessLocked(s.app, false , null ); } mAm.updateOomAdjLocked(s.app, true ); 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); } } ... //如果是利用 BIND_AUTO_CREATE的flag就会向下调用 if ((c.flags&Context.BIND_AUTO_CREATE) != 0) { boolean hasAutoCreate = s.hasAutoCreateConnections(); if (!hasAutoCreate) { if (s.tracker != null ) { s.tracker.setBound(false , mAm.mProcessStats.getMemFactorLocked(), SystemClock.uptimeMillis()); } } //这里走的是stopService的流程 bringDownServiceIfNeededLocked(s, true , hasAutoCreate); } } }
又看到了熟悉的app.thread
就知道切换回到了ActivityThread
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 // ../android/app/ActivityThread.javapublic final void scheduleUnbindService(IBinder token, Intent intent) { BindServiceData s = new BindServiceData(); s.token = token; s.intent = intent; sendMessage(H.UNBIND_SERVICE, s); }private void handleUnbindService(BindServiceData data) { Service s = mServices.get(data.token); if (s != null ) { try { data.intent.setExtrasClassLoader(s.getClassLoader()); data.intent.prepareToEnterProcess(); //调用到 onUnbind() 生命周期 boolean doRebind = s.onUnbind(data.intent); try { if (doRebind) { //需要重新绑定 ActivityManager.getService().unbindFinished( data.token, data.intent, doRebind); } else { //取消绑定 ActivityManager.getService().serviceDoneExecuting( data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0); } } catch (RemoteException ex) { throw ex.rethrowFromSystemServer(); } } catch (Exception e) { ... } } }
当Service调用onUnbind()
之后,还需要做一件事情,如果是靠bindService()
并配置flag
为BIND_AUTO_CREATE
。那么后续还会执行到stopService()
中的流程,即会调用到Service.onDestroy()
。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 // ../core/java/android/com/server/am/ActiveServices.java void removeConnectionLocked( //如果是利用 BIND_AUTO_CREATE的flag就会向下调用 if ((c.flags&Context.BIND_AUTO_CREATE) != 0) { boolean hasAutoCreate = s.hasAutoCreateConnections(); if (!hasAutoCreate) { if (s.tracker != null ) { s.tracker.setBound(false , mAm.mProcessStats.getMemFactorLocked(), SystemClock.uptimeMillis()); } } //这里走的是stopService的流程 bringDownServiceIfNeededLocked(s, true , hasAutoCreate); //true 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 private final void bringDownServiceIfNeededLocked(ServiceRecord r, boolean knowConn, boolean hasConn) { //由于bindService过程中的Service不是由startService()进行启动的,所有这里可以向下执行 if (isServiceNeededLocked(r, knowConn, hasConn)) { return; } // Are we in the process of launching? if (mPendingServices.contains(r)) { return; } bringDownServiceLocked(r); }private final boolean isServiceNeededLocked(ServiceRecord r, boolean knowConn, boolean hasConn) { // 是否由startService()执行 if (r.startRequested) { return true ; } // Is someone still bound to us keeping us running? if (!knowConn) { hasConn = r.hasAutoCreateConnections(); } if (hasConn) { return true ; } return false ; }
Service停止过程 - stopService() 还是由ContextWrapper.stopService()
开始执行
1 2 3 4 @Overridepublic boolean stopService(Intent name) { return mBase.stopService(name); }
向下执行到ContextImpl.stopService()
中
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 @Overridepublic boolean stopService(Intent service) { warnIfCallingFromSystemProcess(); return stopServiceCommon(service, mUser); }private boolean stopServiceCommon(Intent service, UserHandle user) { try { validateServiceIntent(service); service.prepareToLeaveProcess(this ); int res = ActivityManager.getService().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(); } }
ActivityManager.getService()
实际就是指向ActivityManagerService
的一个Binder对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 // ../core/java/android/com/server/am/ActivityManagerService.java @Override public int stopService(IApplicationThread caller, Intent service, String resolvedType, int userId) { enforceNotIsolatedCaller("stopService"); // Refuse possible leaked file descriptors if (service != null && service.hasFileDescriptors() == true ) { throw new IllegalArgumentException("File descriptors passed in Intent"); } synchronized (this ) { return mServices.stopServiceLocked(caller, service, resolvedType, userId); } }
mServices
是ActiveServices
的一个实际对象。
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 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 , 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) { ... service.startRequested = false ; if (service.tracker != null ) { service.tracker.setStarted(false , mAm.mProcessStats.getMemFactorLocked(), SystemClock.uptimeMillis()); } service.callStart = false ; bringDownServiceIfNeededLocked(service, false , false ); } private final boolean isServiceNeededLocked(ServiceRecord r, boolean knowConn, boolean hasConn) { // Are we still explicitly being asked to run? if (r.startRequested) { return true ; } if (!knowConn) { hasConn = r.hasAutoCreateConnections(); } if (hasConn) { return true ; } return false ; } private final void bringDownServiceIfNeededLocked(ServiceRecord r, boolean knowConn, boolean hasConn) { if (isServiceNeededLocked(r, knowConn, hasConn)) { return; } if (mPendingServices.contains(r)) { return; } bringDownServiceLocked(r); }
最后调用到了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 private final void bringDownServiceLocked(ServiceRecord r) { ... 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, true ); 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); } ... }
app.thread
切换到ApplicaitonThread
继续执行流程
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 // ../android/app/ActivityThread.javapublic final void scheduleStopService(IBinder token) { sendMessage(H.STOP_SERVICE, token); }private void handleStopService(IBinder token) { Service s = mServices.remove(token); if (s != null ) { try { if (localLOGV) Slog.v(TAG, "Destroying service " + s); s.onDestroy(); s.detachAndCleanUp(); Context context = s.getBaseContext(); if (context instanceof ContextImpl) { final String who = s.getClassName(); ((ContextImpl) context).scheduleFinalCleanup(who, "Service"); } QueuedWork.waitToFinish(); try { ActivityManager.getService().serviceDoneExecuting( token, SERVICE_DONE_EXECUTING_STOP, 0, 0); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } catch (Exception e) { ... } } else { ... } }
最后执行到Service.onDestroy
完成停止流程。
拓展 为什么Activity退出时bindService()
的Service会一并销毁?
观察源码发现,bindService()
也会去启动Service,但为什么没有回调到onStartCommand()
?