前言
在做Android開發(fā)過程中泼返,我們經(jīng)常使用bindService()
綁定服務(wù),并且通過返回的Binder
對象進(jìn)行多進(jìn)程間通信币叹。
ServiceConnection conn = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
// service是怎么來的润歉?
media = IMedia.Stub.asInterface(service);
}
@Override
public void onServiceDisconnected(ComponentName name) {
media = null;
}
};
Intent intent = new Intent(this, MediaService.class);
bindService(intent, conn, Context.BIND_AUTO_CREATE);
但是我很好奇這個(gè)Binder
對象service
是怎么被返回的?帶著這個(gè)疑問去系統(tǒng)源碼里尋找答案颈抚,然后就有了這篇bindService()過程分析踩衩。
第一步 android.app.ContextImpl.java
首先bindService(intent, conn, Context.BIND_AUTO_CREATE)
實(shí)際上是調(diào)用了ContextImpl
里的bindService(...)
方法
@Override
public boolean bindService(Intent service, ServiceConnection conn,
int flags) {
warnIfCallingFromSystemProcess();
return bindServiceCommon(service, conn, flags, mMainThread.getHandler(),
Process.myUserHandle());
}
接著又調(diào)用bindServiceCommon(...)
方法
private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags, Handler
handler, UserHandle user) {
// Keep this in sync with DevicePolicyManager.bindDeviceAdminServiceAsUser.
IServiceConnection sd;
if (conn == null) {
throw new IllegalArgumentException("connection is null");
}
if (mPackageInfo != null) {
sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), handler, flags);
}
...
int res = ActivityManager.getService().bindService(
mMainThread.getApplicationThread(), getActivityToken(), service,
service.resolveTypeIfNeeded(getContentResolver()),
sd, flags, getOpPackageName(), user.getIdentifier());
...
return res != 0;
}
通過調(diào)用ActivityManager.getService().bindService(...)
將跨進(jìn)程進(jìn)入到ActivityManagerService
的bindService(...)
方法,第三步將接著這里分析贩汉。
另外驱富,bindService(...)
傳入了一個(gè)重要的參數(shù)sd
,那么sd
是怎么獲取的匹舞?它的具體類型是什么呢褐鸥?請看第二步。
第二步 android.app.LoadedApk.java
首先mPackageInfo
是一個(gè)LoadedApk
類型對象赐稽,sd
是通過調(diào)用mPackageInfo
的getServiceDispatcher(...)
方法獲取的
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();
}
}
直接進(jìn)入到LoadedApk.ServiceDispatcher
的getIServiceConnection()
方法
static final class ServiceDispatcher {
private final Handler mActivityThread;
ServiceDispatcher(ServiceConnection conn,
Context context, Handler activityThread, int flags) {
// mIServiceConnection的類型是InnerConnection
mIServiceConnection = new InnerConnection(this);
mConnection = conn;
mContext = context;
mActivityThread = activityThread;
mLocation = new ServiceConnectionLeaked(null);
mLocation.fillInStackTrace();
mFlags = flags;
}
IServiceConnection getIServiceConnection() {
return mIServiceConnection;
}
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);
}
}
}
}
通過上面的代碼可知叫榕,sd
是ServiceDispatcher.InnerConnection
類型的對象浑侥,這個(gè)sd
后面的講解還會(huì)用到。
第三步 com.android.server.am.ActivityManagerService.java
第一步中ContextImpl
通過跨進(jìn)程通信進(jìn)入到了ActivityManagerService
的bindService(...)
方法
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);
}
}
然后mServices
是一個(gè)ActiveServices
對象晰绎、bindService (...)
就直接轉(zhuǎn)交給了ActiveServices
的bindServiceLocked(...)
第四步 com.android.server.am.ActiveServices.java
bindServiceLocked(...)
的代碼很長寓落,只列出了關(guān)鍵部分
int bindServiceLocked(IApplicationThread caller, IBinder token, Intent service,
String resolvedType, final IServiceConnection connection, int flags,
String callingPackage, final int userId) throws TransactionTooLargeException {
...
if ((flags&Context.BIND_AUTO_CREATE) != 0) {
s.lastActivity = SystemClock.uptimeMillis();
if (bringUpServiceLocked(s, service.getFlags(), callerFg, false,
permissionsReviewRequired) != null) {
return 0;
}
}
...
ConnectionRecord c = new ConnectionRecord(b, activity,
connection, flags, clientLabel, clientIntent);
if (s.app != null && b.intent.received) {
// Service is already running, so we can immediately
// publish the connection.
try {
c.conn.connected(s.name, b.intent.binder, false);
} catch (Exception e) {
Slog.w(TAG, "Failure sending service " + s.shortName
+ " 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) {
requestServiceBindingLocked(s, b.intent, callerFg, true);
}
} else if (!b.intent.requested) {
requestServiceBindingLocked(s, b.intent, callerFg, false);
}
...
}
從最開始的調(diào)用bindService(intent, conn, Context.BIND_AUTO_CREATE)
可知傳進(jìn)來的參數(shù)flags的位Context.BIND_AUTO_CREATE為1,所以會(huì)執(zhí)行bringUpServiceLocked (...)
去啟動(dòng)服務(wù)荞下,然后就直接返回了伶选。
如果不為1會(huì)繼續(xù)往下,創(chuàng)建一個(gè)ConnectionRecord
對象c
锄弱,c
的conn
為傳入的參數(shù)connection
考蕾,這個(gè)conn
實(shí)際上就是第二步中的sd
對象,即ServiceDispatcher.InnerConnection
類型對象会宪。
接下來判斷如果服務(wù)已經(jīng)在運(yùn)行肖卧、則會(huì)直接調(diào)用c.conn.connected(...)
發(fā)布連接,發(fā)布連接的過程將在第六步中分析掸鹅。
第五步 com.android.server.am.ActiveServices.java
接著第四步的bringUpServiceLocked (...)
分析
private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,
boolean whileRestarting, boolean permissionsReviewRequired)
throws TransactionTooLargeException
if (!isolated) {
app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false);
if (DEBUG_MU) Slog.v(TAG_MU, "bringUpServiceLocked: appInfo.uid=" + r.appInfo.uid
+ " app=" + app);
if (app != null && app.thread != null) {
try {
app.addPackage(r.appInfo.packageName, r.appInfo.versionCode, mAm.mProcessStats);
realStartServiceLocked(r, app, execInFg);
return null;
} catch (TransactionTooLargeException e) {
throw e;
} catch (RemoteException e) {
Slog.w(TAG, "Exception when starting service " + r.shortName, e);
}
// If a dead object exception was thrown -- fall through to
// restart the application.
}
} else {
...
}
}
如果進(jìn)程已啟動(dòng)塞帐,會(huì)調(diào)用realStartServiceLocked(...)
繼續(xù)去啟動(dòng)服務(wù)
private final void realStartServiceLocked(ServiceRecord r,
ProcessRecord app, boolean execInFg) throws RemoteException {
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 {
...
}
requestServiceBindingsLocked(r, execInFg);
updateServiceClientActivitiesLocked(app, null, true);
}
app.thread
是應(yīng)用程序端ApplicationThread
的一個(gè)遠(yuǎn)程Binder
對象,是在第一步中調(diào)用ActivityManager.getService().bindService(...)
傳入的mMainThread.getApplicationThread()
巍沙,
通過它服務(wù)端ActivityManagerService
可以調(diào)用應(yīng)用程序端ApplicationThread
中的方法葵姥。
app.thread.scheduleCreateService
這個(gè)方法通過多進(jìn)程通信讓應(yīng)用程序去創(chuàng)建Service
對象,并調(diào)用它的onCreate()
方法句携。
requestServiceBindingsLocked(...)
會(huì)輾轉(zhuǎn)調(diào)用到r.app.thread.scheduleBindService(...)
榔幸,接下來就調(diào)用到了ApplicationThread
的scheduleBindService(...)
方法
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);
}
發(fā)送一個(gè)Handler
消息給ActivityThread.H
類對象
case BIND_SERVICE:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceBind");
handleBindService((BindServiceData)msg.obj);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
接下來就調(diào)用到了ActivityThread
的handleBindService()
方法
private void handleBindService(BindServiceData data) {
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) {
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);
}
}
}
}
然后通過ActivityManager.getService().publishService(...)
又回到了ActivityManagerService
的publishService()
方法
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);
}
}
接著又回到了ActiveServices
的publishServiceLocked()
方法
void publishServiceLocked(ServiceRecord r, Intent intent, IBinder service) {
final long origId = Binder.clearCallingIdentity();
try {
if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "PUBLISHING " + r
+ " " + intent + ": " + service);
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;
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);
if (!filter.equals(c.binding.intent.intent)) {
if (DEBUG_SERVICE) Slog.v(
TAG_SERVICE, "Not publishing to: " + c);
if (DEBUG_SERVICE) Slog.v(
TAG_SERVICE, "Bound intent: " + c.binding.intent.intent);
if (DEBUG_SERVICE) Slog.v(
TAG_SERVICE, "Published intent: " + intent);
continue;
}
if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Publishing to: " + c);
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);
}
}
首先獲取到ConnectionRecord
類型對象c
,然后調(diào)用c.conn.connected(...)
發(fā)布連接矮嫉。前面第四步中已提到過如果服務(wù)已經(jīng)在運(yùn)行削咆,也會(huì)直接調(diào)用c.conn.connected(...)
來發(fā)布連接,接下來就在第六步中具體分析c.conn.connected(...)
蠢笋。
第六步 android.app.LoadedApk.ServiceDispatcher.InnerConnection.java
c.conn
其實(shí)就是sd
拨齐,是在第一步中通過ActivityManager.getService().bindService(...)
方法傳入的,由于ActivityManager.getService().bindService(...)
是一個(gè)跨進(jìn)程通信方法昨寞,從sd
到c.conn
其實(shí)在native層傳輸時(shí)有一次轉(zhuǎn)換瞻惋,這樣c.conn
可以從服務(wù)端調(diào)用到應(yīng)用端的方法。然后sd
是一個(gè)ServiceDispatcher.InnerConnection
類型對象援岩。
InnerConnection
繼承于IServiceConnection.Stub
歼狼,可知c.conn
確實(shí)是一個(gè)Binder
對象,調(diào)用c.conn.connected(...)
享怀,此時(shí)這個(gè)connected(...)
方法已經(jīng)被執(zhí)行在應(yīng)用端了
private static class InnerConnection extends IServiceConnection.Stub {
final WeakReference<LoadedApk.ServiceDispatcher> mDispatcher;
InnerConnection(LoadedApk.ServiceDispatcher sd) {
mDispatcher = new WeakReference<LoadedApk.ServiceDispatcher>(sd);
}
// 這個(gè)方法是被執(zhí)行在應(yīng)用端
public void connected(ComponentName name, IBinder service, boolean dead)
throws RemoteException {
LoadedApk.ServiceDispatcher sd = mDispatcher.get();
if (sd != null) {
sd.connected(name, service, dead);
}
}
}
接著又會(huì)調(diào)用到LoadedApk.ServiceDispatcher
的connected(...)
方法
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
是否存在羽峰,注意mActivityThread
是一個(gè)Handler
對象,并不是ActivityThread
對象凹蜈,是第一步中的bindServiceCommon (...)
方法傳入的mMainThread.getHandler()
限寞,并創(chuàng)建了ServiceDispatcher
以及ServiceDispatcher.InnerConnection
對象。
如果mActivityThread
存在仰坦,則讓RunConnection
的run()
方法運(yùn)行于UI線程履植,否則直接調(diào)用doConnected(...)
方法
public void run() {
if (mCommand == 0) {
doConnected(mName, mService, mDead);
} else if (mCommand == 1) {
doDeath(mName, mService);
}
}
接著還是調(diào)用了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.
return;
}
old = mActiveConnections.get(name);
if (old != null && old.binder == service) {
// Huh, already have this one. Oh well!
return;
}
if (service != null) {
// A new service is being connected... set it all up.
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) {
// 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 service, it is now connected.
if (service != null) {
mConnection.onServiceConnected(name, service);
}
}
最后調(diào)用mConnection.onServiceConnected(name, service)
,service
就是這樣被傳遞回應(yīng)用端的悄晃。