Service启动系列总结:
《Service启动流程总结-start和stop service》
在开发中我们使用Context#bindService和Context#unbindService来绑定和解绑Service,通过绑定来启动Service,可以方便的调用Service提供的API。Service的bind、unbind过程和start、stop过程类似,比较大的区别是多了Binder的传递过程。
// ISpeaker.aidl package com.cdh.study; // Declare any non-default types here with import statements interface ISpeaker { String sayHello(); } 复制代码
public class SpeakerService extends Service { // 创建由aidl文件自动生成的Stub实例 private final ISpeaker.Stub mSpeakerBinder = new ISpeaker.Stub() { @Override public String sayHello() throws RemoteException { return "hello!"; } }; @Nullable @Override public IBinder onBind(Intent intent) { // 返回Stub实例 return mSpeakerBinder; } } 复制代码
在Service的onBind回调中返回创建的ISpeaker.Stub实例,Stub继承Binder和ISpeaker。Client端在成功连接后便可通过其调用Server端的sayHello方法。
// Server端API接口,若Client和Server处于同一进程则返回的即是Server端binder实例,否则是Server端binder代理 private ISpeaker mISpeaker; // 创建ServiceConnection实例,用作回调接口 private final ServiceConnection mConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { // 连接回调,service即Server端onBind返回的IBinder mISpeaker = ISpeaker.Stub.asInterface(service); } @Override public void onServiceDisconnected(ComponentName name) { // 断连回调 mISpeaker = null; } }; public void bind() { // 绑定Server mContext.bindService(new Intent(mContext, SpeakerService.class), mConnection, Context.BIND_AUTO_CREATE); } public void unbind() { // 解绑Server,需要传入绑定时的ServiceConnection接口(内部以ServiceConnection作为key) mContext.unbindService(mConnection); } 复制代码
public void requestHello() { if (mISpeaker != null) { try { // 调用Service方法,会返回"hello!" mISpeaker.sayHello(); } catch (RemoteException e) { e.printStackTrace(); } } } 复制代码
Client端首先进行绑定Service,成功绑定后会回调ServiceConnection的onServiceConnected方法,在这里获取Server端binder实例或binder代理,之后便可通过binder来调用Server端API。
以上是一个bind service的简单例子,接下来跟踪源码调用看看bind service的整体流程。
文中源码基于 Android 10.0
Caller指调用方,发起bind service,将会调用ContextImpl的bindService方法:
[ContextImpl#bindService]
public boolean bindService(Intent service, ServiceConnection conn, int flags) { warnIfCallingFromSystemProcess(); // 传入意图、ServiceConnection实例、BIND_AUTO_CREATE(表示目标Service未启动时自动创建)和主线程Handler和当前用户具柄 return bindServiceCommon(service, conn, flags, null, mMainThread.getHandler(), null, getUser()); } 复制代码
[ContextImpl#bindServiceCommon]
private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags, String instanceName, Handler handler, Executor executor, UserHandle user) { // Keep this in sync with DevicePolicyManager.bindDeviceAdminServiceAsUser. // binder通信接口,用于AMS向Caller进程通信 IServiceConnection sd; // ··· if (mPackageInfo != null) { if (executor != null) { sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), executor, flags); } else { // 此时executor是null,执行这个case获取IServiceConnection sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), handler, flags); } } else { throw new RuntimeException("Not supported in system context"); } // 省略显示意图校验 ··· try { IBinder token = getActivityToken(); // ··· // 请求AMS进行bind流程 int res = ActivityManager.getService().bindIsolatedService( mMainThread.getApplicationThread(), getActivityToken(), service, service.resolveTypeIfNeeded(getContentResolver()), sd, flags, instanceName, 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(); } } 复制代码
该方法中先获取IServiceConnection,然后调用AMS的bindIsolatedService方法。
在前面的基本使用例子中,Client端通过ServiceConnection接口回调获取Server端binder。但ServiceConnection只是一个普通接口,不支持跨进程通信。因此这里利用IServiceConnection进行AMS向Caller进程调用时的binder通信接口。
sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), handler, flags);
上文通过这个方法获取IServiceConnection,mPackageInfo是LoadedApk,进入方法看看。
[LoadedApk#getServiceDispatcher]
public final IServiceConnection getServiceDispatcher(ServiceConnection c, Context context, Handler handler, int flags) { return getServiceDispatcherCommon(c, context, handler, null, flags); } 复制代码
[LoadedApk#getServiceDispatcherCommon]
private IServiceConnection getServiceDispatcherCommon(ServiceConnection c, Context context, Handler handler, Executor executor, int flags) { synchronized (mServices) { LoadedApk.ServiceDispatcher sd = null; // ··· if (sd == null) { if (executor != null) { sd = new ServiceDispatcher(c, context, executor, flags); } else { // 创建ServiceDispatcher sd = new ServiceDispatcher(c, context, handler, flags); } // ··· } else { // ··· } // 返回其中的mIServiceConnection成员 return sd.getIServiceConnection(); } } 复制代码
这里省略了判断缓存的部分,若没有缓存,则新建ServiceDispatcher包装传入的参数。
接着看ServiceDispatcher构造方法:
ServiceDispatcher(ServiceConnection conn, Context context, Handler activityThread, int flags) { mIServiceConnection = new InnerConnection(this); mConnection = conn; mContext = context; mActivityThread = activityThread; mActivityExecutor = null; mLocation = new ServiceConnectionLeaked(null); mLocation.fillInStackTrace(); mFlags = flags; } 复制代码
ServiceDispatcher会持有InnerConnection和ServiceConnection。
InnerConnection继承IServiceConnection.Stub,它实现了IServiceConnection的connected方法:
private static class InnerConnection extends IServiceConnection.Stub { @UnsupportedAppUsage final WeakReference<LoadedApk.ServiceDispatcher> mDispatcher; InnerConnection(LoadedApk.ServiceDispatcher sd) { // 利用弱引用持有ServiceDispatcher 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) { // 连接回调转发给ServiceDispatcher sd.connected(name, service, dead); } } } 复制代码
InnerConnection持有ServiceDispatcher,当绑定Server端成功时,AMS会调用其connected方法,在该方法中将参数转发给ServiceDispatcher。
回到ContextImpl#bindServiceCommon方法中,再获取到IServiceConnection后,便调用AMS#bindIsolatedService方法:
[ActivityManagerService#bindIsolatedService]
public int bindIsolatedService(IApplicationThread caller, IBinder token, Intent service, String resolvedType, IServiceConnection connection, int flags, String instanceName, String callingPackage, int userId) throws TransactionTooLargeException { // ··· synchronized(this) { return mServices.bindServiceLocked(caller, token, service, resolvedType, connection, flags, instanceName, callingPackage, userId); } } 复制代码
调用ActiveServices的bindServiceLocked方法: [ActiveServices#bindServiceLocked]
int bindServiceLocked(IApplicationThread caller, IBinder token, Intent service, String resolvedType, final IServiceConnection connection, int flags, String instanceName, String callingPackage, final int userId) throws TransactionTooLargeException { // ··· // 用于保存发起方Activity和Service的连接信息 ActivityServiceConnectionsHolder<ConnectionRecord> activity = null; if (token != null) { // 将token强转为Token,然后获取它内部通过弱引用持有的ActivityRecord,最后创建ActivityServiceConnectionsHolder保存ActivityRecord返回 activity = mAm.mAtmInternal.getServiceConnectionsHolder(token); if (activity == null) { // 如果查找ActivityRecord失败,则bind失败 Slog.w(TAG, "Binding with unknown activity: " + token); return 0; } } // ··· final boolean callerFg = callerApp.setSchedGroup != ProcessList.SCHED_GROUP_BACKGROUND; final boolean isBindExternal = (flags & Context.BIND_EXTERNAL_SERVICE) != 0; final boolean allowInstant = (flags & Context.BIND_ALLOW_INSTANT) != 0; // 从查找或新建可用ServiceRecord ServiceLookupResult res = retrieveServiceLocked(service, instanceName, resolvedType, callingPackage, Binder.getCallingPid(), Binder.getCallingUid(), userId, true, callerFg, isBindExternal, allowInstant); if (res == null) { return 0; } if (res.record == null) { return -1; } ServiceRecord s = res.record; // ··· final long origId = Binder.clearCallingIdentity(); try { // ··· // AppBindRecord记录一个绑定了Server的Caller信息 // 保存ServiceRecord(在运行的Service信息)、IntentBindRecord(绑定意图信息)、ProcessRecord(发起方进程信息) AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp); // ConnectionRecord记录一个Caller和Service绑定的连接信息,保存绑定相关参数 ConnectionRecord c = new ConnectionRecord(b, activity, connection, flags, clientLabel, clientIntent, callerApp.uid, callerApp.processName, callingPackage); IBinder binder = connection.asBinder(); // 保存连接信息 s.addConnection(binder, c); b.connections.add(c); if (activity != null) { activity.addConnection(c); } b.client.connections.add(c); c.startAssociationIfNeeded(); if ((c.flags&Context.BIND_ABOVE_CLIENT) != 0) { b.client.hasAboveClient = true; } if ((c.flags&Context.BIND_ALLOW_WHITELIST_MANAGEMENT) != 0) { s.whitelistManager = true; } if ((flags & Context.BIND_ALLOW_BACKGROUND_ACTIVITY_STARTS) != 0) { s.setHasBindingWhitelistingBgActivityStarts(true); } if (s.app != null) { updateServiceClientActivitiesLocked(s.app, c, true); } // mServiceConnections中存储着所有ConnectionRecord ArrayList<ConnectionRecord> clist = mServiceConnections.get(binder); if (clist == null) { clist = new ArrayList<>(); mServiceConnections.put(binder, clist); } // 添加本次绑定连接信息 clist.add(c); // 发起bind时通常会设置BIND_AUTO_CREATE if ((flags&Context.BIND_AUTO_CREATE) != 0) { s.lastActivity = SystemClock.uptimeMillis(); // bringUpServiceLocked中会判断是否已启动Service,若未启动会先启动,遇到错误会返回描述原因字符串 if (bringUpServiceLocked(s, service.getFlags(), callerFg, false, permissionsReviewRequired) != null) { return 0; } } // 省略更新Service所在进程优先级和oom_adj部分 ··· if (s.app != null && b.intent.received) { // Service is already running, so we can immediately // publish the connection. try { // Service已经启动,则回调Caller端connected c.conn.connected(s.name, b.intent.binder, false); } catch (Exception e) { Slog.w(TAG, "Failure sending service " + s.shortInstanceName + " to connection " + c.conn.asBinder() + " (in " + c.binding.client.processName + ")", e); } // If this is the first app connected back to this binding, // and the service had previously asked to be told when // rebound, then do so. if (b.intent.apps.size() == 1 && b.intent.doRebind) { // 若之前unbind过且返回true,则再次bind时会执行Service的onRebind回调 requestServiceBindingLocked(s, b.intent, callerFg, true); } } else if (!b.intent.requested) { // 若前面bringUpServiceLocked方法中没有执行bind,则这里再次尝试执行Service的onBind回调 requestServiceBindingLocked(s, b.intent, callerFg, false); } // ··· } finally { Binder.restoreCallingIdentity(origId); } return 1; } 复制代码
该方法中会检查Caller是否是有效的Activity,然后从缓存查找或新建ServiceRecord,然后利用ActivityServiceConnectionsHolder、AppBindRecord、ConnectionRecord、mServiceConnections保存本次绑定连接Service的相关参数信息。接着调用bringUpServiceLocked方法(flags设置了BIND_AUTO_CREATE)进行启动Service(若未启动)和绑定流程。
bringUpServiceLocked方法的主要逻辑在《Service启动流程总结-start和stop service》中简单总结过,其中又会调用realStartServiceLocked方法,这里看和bind相关的部分:
[ActiveServices#realStartServiceLocked]
private final void realStartServiceLocked(ServiceRecord r, ProcessRecord app, boolean execInFg) throws RemoteException { // ··· try { // ··· // 启动Service app.thread.scheduleCreateService(r, r.serviceInfo, mAm.compatibilityInfoForPackage(r.serviceInfo.applicationInfo), app.getReportedProcState()); // ··· } catch (DeadObjectException e) { Slog.w(TAG, "Application dead when creating service " + r); mAm.appDiedLocked(app); throw e; } finally { // ··· } // ··· // 进一步执行bind流程 requestServiceBindingsLocked(r, execInFg); // ··· // 内部会判断pendingStarts集合中元素个数,通过start启动Service时会触发onStartCommand回调,bind流程可忽略。 sendServiceArgsLocked(r, execInFg, true); // ··· } 复制代码
进入requestServiceBindingsLocked方法: [ActiveServices#requestServiceBindingsLocked]
private final void requestServiceBindingsLocked(ServiceRecord r, boolean execInFg) throws TransactionTooLargeException { for (int i=r.bindings.size()-1; i>=0; i--) { // 依次取出ServiceRecord中保存的IntentBindRecord IntentBindRecord ibr = r.bindings.valueAt(i); // 进一步执行bind流程,若bind失败会返回false if (!requestServiceBindingLocked(r, ibr, execInFg, false)) { break; } } } 复制代码
看requestServiceBindingLocked方法:
[ActiveServices#requestServiceBindingLocked]
private final boolean requestServiceBindingLocked(ServiceRecord r, IntentBindRecord i, boolean execInFg, boolean rebind) throws TransactionTooLargeException { // ··· if ((!i.requested || rebind) && i.apps.size() > 0) { try { bumpServiceExecutingLocked(r, execInFg, "bind"); r.app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE); // 调度Service执行bind回调 r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind, r.app.getReportedProcState()); if (!rebind) { // 将requested成员置为true,那么在ActiveServices#bindServiceLocked方法结尾不会再执行requestServiceBindingLocked i.requested = true; } i.hasBound = true; i.doRebind = false; } catch (TransactionTooLargeException e) { // 省略异常处理部分 ··· } catch (RemoteException e) { // 省略异常处理部分 ··· } } return true; } 复制代码
该方法中通过IApplicationThread调度Service所在进程执行bind操作。
接下来便来到Service所在进程,ActivityThread会发送BIND_SERVICE消息至主线程,执行handleBindService方法,直接看这个方法:
[ActivityThread#handleBindService]
private void handleBindService(BindServiceData data) { // 获取缓存的Service实例(启动时会将创建的Service保存在mServices中) 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 { if (!data.rebind) { // 触发Service的onBind回调 IBinder binder = s.onBind(data.intent); // 通知AMS发布Service,并传送IBinder ActivityManager.getService().publishService( data.token, data.intent, binder); } else { // 触发Service的onRebind回调 s.onRebind(data.intent); ActivityManager.getService().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 bind to service " + s + " with " + data.intent + ": " + e.toString(), e); } } } } 复制代码
**这里从mServices取出之前启动创建时保存的Service实例,然后调用它的onBind生命周期回调方法。**在开头例子中,返回了Server端binder实例ISpeaker.Stub。
接下来便请求ActivityManagerService,将binder传送给Caller端。
Server端在执行完Service的onBind后,需要将创建的binder传给Caller,以便Caller通过binder调用Service提供的API,因此需要通过publishService方法通知AMS。
接下来看ActivityManagerService的publishService方法,在该方法中又调用了ActiveServices的publishServiceLocked方法:
[ActiveServices#publishServiceLocked]
void publishServiceLocked(ServiceRecord r, Intent intent, IBinder service) { final long origId = Binder.clearCallingIdentity(); try { // 省略DEBUG信息 ··· if (r != null) { Intent.FilterComparison filter = new Intent.FilterComparison(intent); IntentBindRecord b = r.bindings.get(filter); if (b != null && !b.received) { b.binder = service; b.requested = true; b.received = true; ArrayMap<IBinder, ArrayList<ConnectionRecord>> connections = r.getConnections(); for (int conni = connections.size() - 1; conni >= 0; conni--) { ArrayList<ConnectionRecord> clist = connections.valueAt(conni); for (int i=0; i<clist.size(); i++) { // 依次取出bind目标Service的Caller连接信息 ConnectionRecord c = clist.get(i); if (!filter.equals(c.binding.intent.intent)) { // 省略DEBUG信息 ··· continue; } // 省略DEBUG信息 ··· try { // conn是Caller发起bind时传过来的IServiceConnection c.conn.connected(r.name, service, false); } catch (Exception e) { // 省略DEBUG信息 ··· } } } } serviceDoneExecutingLocked(r, mDestroyingServices.contains(r), false); } } finally { Binder.restoreCallingIdentity(origId); } } 复制代码
该方法中,会依次取出bind目标Service的等待中的Caller的ConnectionRecord,通过ConnectionRecord保存的IServiceConnection的connected方法调度到Caller进程。
AMS在处理publishService时,又会通过IServiceConnection调度Caller端,将会执行InnerConnection的connected方法,该方法中又会调用ServiceDispatcher的connected方法:
[ServiceDispatcher#connected]
public void connected(ComponentName name, IBinder service, boolean dead) { if (mActivityExecutor != null) { // mActivityExecutor默认为null mActivityExecutor.execute(new RunConnection(name, service, 0, dead)); } else if (mActivityThread != null) { // mActivityThread是构造时传入的主线程handler mActivityThread.post(new RunConnection(name, service, 0, dead)); } else { doConnected(name, service, dead); } } 复制代码
该方法中通过主线程handler切换到主线程执行connect回调。
RunConnection#run中会执行doConnected方法:
[ServiceDispatcher#doConnected]
public void doConnected(ComponentName name, IBinder service, boolean dead) { // 缓存的旧的连接信息 ServiceDispatcher.ConnectionInfo old; // 新的连接信息 ServiceDispatcher.ConnectionInfo info; synchronized (this) { if (mForgotten) { // We unbound before receiving the connection; ignore // any connection received. // 已经执行unbind return; } // mActiveConnections中缓存已经完成连接的ConnectionInfo old = mActiveConnections.get(name); if (old != null && old.binder == service) { // Huh, already have this one. Oh well! // 已经连接过一样的Service return; } if (service != null) { // A new service is being connected... set it all up. // ConnectionInfo保存连接信息 info = new ConnectionInfo(); info.binder = service; info.deathMonitor = new DeathMonitor(name, service); try { // 设置Service死亡监听 service.linkToDeath(info.deathMonitor, 0); // 添加mActiveConnections集合保存 mActiveConnections.put(name, info); } catch (RemoteException e) { // This service was dead before we got it... just // don't do anything with it. mActiveConnections.remove(name); return; } } else { // The named service is being disconnected... clean up. mActiveConnections.remove(name); } if (old != null) { // 取消旧连接信息设置的死亡监听 old.binder.unlinkToDeath(old.deathMonitor, 0); } } // If there was an old service, it is now disconnected. if (old != null) { mConnection.onServiceDisconnected(name); } if (dead) { mConnection.onBindingDied(name); } // If there is a new viable service, it is now connected. if (service != null) { // 执行ServiceConnection接口的onServiceConnected回调 mConnection.onServiceConnected(name, service); } else { // The binding machinery worked, but the remote returned null from onBind(). mConnection.onNullBinding(name); } } 复制代码
在该方法中,会执行mConnection的onServiceConnected回调,mConnection即我们创建的ServiceConnection接口实例。在onServiceConnected回调中保存Service->AMS->Caller传来的IBinder,若Caller与Service属于同一进程则保存的是Server端binder实例,否则是binder代理。
至此便完成了Caller向Service的绑定过程,也拿到了Service提供的binder接口,后续就可以提供binder很方便地调用Service提供的API。
当Caller发起绑定时的Activtiy退出或者主动调用unbindService方法时,会开始解绑流程。
进入ContextImpl的unbindService方法:
[ContextImpl#unbindService]
public void unbindService(ServiceConnection conn) { if (conn == null) { throw new IllegalArgumentException("connection is null"); } if (mPackageInfo != null) { // 获取缓存的IServiceConnection IServiceConnection sd = mPackageInfo.forgetServiceDispatcher( getOuterContext(), conn); try { // 请求AMS进行解绑 ActivityManager.getService().unbindService(sd); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } else { throw new RuntimeException("Not supported in system context"); } } 复制代码
该方法中首先从LoadedApk获取缓存的IServiceConnection,然后请求AMS调度解绑。
forgetServiceDispatcher方法中从mServices集合中移除当前context和ServiceConnection对应的ServiceDispatcher,然后转存到mUnboundServices集合中,最后返回ServiceDispatcher持有的InnerConnection实例。
接着来到AMS侧,在ActivityManagerService#unbindService方法中又调用ActiveServices#unbindServiceLocked方法: [ActiveServices#unbindServiceLocked]
boolean unbindServiceLocked(IServiceConnection connection) { IBinder binder = connection.asBinder(); // ··· final long origId = Binder.clearCallingIdentity(); try { // clist中保存着IServiceConnection对应的所有连接信息 while (clist.size() > 0) { // 依次取出ConnectionRecord ConnectionRecord r = clist.get(0); // 移除连接相关信息和解绑操作 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); } // ··· } mAm.updateOomAdjLocked(OomAdjuster.OOM_ADJ_REASON_UNBIND_SERVICE); } finally { Binder.restoreCallingIdentity(origId); } return true; } 复制代码
该方法中取出缓存的ConnectionRecord,然后进一步执行解绑操作。
进入removeConnectionLocked方法:
[ActiveServices#removeConnectionLocked]
void removeConnectionLocked(ConnectionRecord c, ProcessRecord skipApp, ActivityServiceConnectionsHolder skipAct) { IBinder binder = c.conn.asBinder(); // 开始清理相关信息 AppBindRecord b = c.binding; ServiceRecord s = b.service; ArrayList<ConnectionRecord> clist = s.getConnections().get(binder); if (clist != null) { clist.remove(c); if (clist.size() == 0) { s.removeConnection(binder); } } b.connections.remove(c); c.stopAssociation(); if (c.activity != null && c.activity != skipAct) { c.activity.removeConnection(c); } if (b.client != skipApp) { b.client.connections.remove(c); if ((c.flags&Context.BIND_ABOVE_CLIENT) != 0) { b.client.updateHasAboveClientLocked(); } // If this connection requested whitelist management, see if we should // now clear that state. if ((c.flags&Context.BIND_ALLOW_WHITELIST_MANAGEMENT) != 0) { s.updateWhitelistManager(); if (!s.whitelistManager && s.app != null) { updateWhitelistManagerLocked(s.app); } } // And do the same for bg activity starts whitelisting. if ((c.flags & Context.BIND_ALLOW_BACKGROUND_ACTIVITY_STARTS) != 0) { s.updateHasBindingWhitelistingBgActivityStarts(); } if (s.app != null) { updateServiceClientActivitiesLocked(s.app, c, true); } } clist = mServiceConnections.get(binder); if (clist != null) { clist.remove(c); if (clist.size() == 0) { mServiceConnections.remove(binder); } } mAm.stopAssociationLocked(b.client.uid, b.client.processName, s.appInfo.uid, s.appInfo.longVersionCode, s.instanceName, s.processName); if (b.connections.size() == 0) { b.intent.apps.remove(b.client); } 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_HEAVY_WEIGHT) { // 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, OomAdjuster.OOM_ADJ_REASON_UNBIND_SERVICE); 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; // 调用Service端执行unbind s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent()); } catch (Exception e) { Slog.w(TAG, "Exception when unbinding service " + s.shortInstanceName, e); serviceProcessGoneLocked(s); } } // If unbound while waiting to start, remove the pending service mPendingServices.remove(s); 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()); } } // 该方法中会判断unbind后是否执行销毁Service bringDownServiceIfNeededLocked(s, true, hasAutoCreate); } } } 复制代码
该方法中会清理之前缓存的绑定相关的连接信息,然后调度Service端执行scheduleUnbindService触发onUnbind回调。
在ActivityThread的scheduleUnbindService方法中通过发送UNBIND_SERVICE消息至主线程,执行handleUnbindService方法:
[ActivityThread#handleUnbindService]
private void handleUnbindService(BindServiceData data) { // 取出缓存的Service实例 Service s = mServices.get(data.token); if (s != null) { try { data.intent.setExtrasClassLoader(s.getClassLoader()); data.intent.prepareToEnterProcess(); // 执行Service的onUnbind回调方法 boolean doRebind = s.onUnbind(data.intent); try { // 判断onUnbind返回的结果,默认为false if (doRebind) { // 请求AMS支持reBind ActivityManager.getService().unbindFinished( data.token, data.intent, doRebind); } else { // 通知unbind完成 ActivityManager.getService().serviceDoneExecuting( data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0); } } catch (RemoteException ex) { throw ex.rethrowFromSystemServer(); } } catch (Exception e) { // ··· } } } 复制代码
该方法中取出缓存的Service实例,调用它的onUnbind生命周期回调方法,最后再通知AMS。
至此解绑流程便已完成。注意,可以看到解绑流程中没有调用ServiceConnection的onServiceDisconnected回调,onServiceDisconnected的回调时机是在绑定时判断旧连接时触发和Caller通过binder死亡监听监听到Service端进程死亡时触发。
bind流程:
unbind流程: