文章目錄
回顧
Service啓動系列總結:
《Service啓動流程總結-start和stop service》
概述
在開發中我們使用Context#bindService和Context#unbindService來綁定和解綁Service,通過綁定來啓動Service,可以方便的調用Service提供的API。Service的bind、unbind過程和start、stop過程類似,比較大的區別是多了Binder的傳遞過程。
基本使用
- 定義AIDL文件
// ISpeaker.aidl
package com.cdh.study;
// Declare any non-default types here with import statements
interface ISpeaker {
String sayHello();
}
- 定義Server端
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方法。
- 定義Client端
// 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);
}
- 調用Server端提供的API
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
bind過程
Caller發起bind
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方法。
IServiceConnection說明
在前面的基本使用例子中,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。
AMS處理bind請求
回到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處理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端。
AMS發佈Service
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進程。
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。
unbind過程
當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流程: