參考鏈接:
從一個簡單的AIDL實(shí)現(xiàn)看binder原理(一)簡單的AIDL實(shí)現(xiàn)
從一個簡單的AIDL實(shí)現(xiàn)看binder原理(二)bindService的調(diào)用過程
BindService時Binder的轉(zhuǎn)換
我們分析上面鏈接中的aidl實(shí)現(xiàn)案例美莫,在bindService時打印一下日志:
/*** MainActivity */
ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.d("ipcLog", "service = " + service.getClass().getName());
proxy = IAIDLInterface.Stub.asInterface(service);
Log.d("ipcLog", "proxy = " + proxy.getClass().getName());
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
/*** RemoteService */
@Nullable
@Override
public IBinder onBind(Intent intent) {
StudentStub stub = new StudentStub();
Log.d("ipcLog", "stub = " + stub.getClass());
return stub;
}
public class StudentStub extends IAIDLInterface.Stub {
@Override
public List<Student> getStudent() throws RemoteException {
return studentList;
}
@Override
public void setStudent(Student student) throws RemoteException {
studentList.add(student);
}
}
打印出的日志結(jié)果:
在org.hrcy.ipctest進(jìn)程中:
在org.hrcy.ipctest:remote進(jìn)程中:
在demo中我們可以看到洲赵,StudentStub 繼承于IAIDLInterface.Stub风宁, IAIDLInterface.Stub 繼承于android.os.Binder 也就是說 StudentStub是一個Binder對象,而在MainActivity打印出的log中我們看到磅崭,onServiceConnected方法接收到的是個BinderProxy譬涡,我們需要知道這個轉(zhuǎn)換是在哪里發(fā)生的
我們回顧一下上一篇博文:
在這邊文章里合呐,我們找到了Service最終執(zhí)行的地方板乙,但是具體是怎么執(zhí)行的還沒有具體分析,下面我們分析一下onBind方法的具體執(zhí)行
從ActivityThread#handleBindService執(zhí)行開始:
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);
}
}
}
}
我們看第15行具篇,從之前的分析我們可以知道纬霞,s.onBind方法執(zhí)行的就是Service的onBind方法,在這里驱显,onBind方法返回了一個Binder對象诗芜,接著執(zhí)行了
ActivityManager.getService().publishService(data.token, data.intent, binder);
將獲得的binder對象發(fā)送了出去瞳抓,ActivityManager.getService()其實(shí)就是ActivityManagerService,這里是一個IPC的過程,具體細(xì)節(jié)不表伏恐,我們直接轉(zhuǎn)到ActivityManagerService中看publishService的實(shí)現(xiàn)
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);
}
}
在代碼的第11行孩哑,這里轉(zhuǎn)到了ActiveServices#publishServiceLocked執(zhí)行,我們看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找到要進(jìn)行通信的進(jìn)程信息
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 {
// 通過connectionRecord中的conn與目標(biāo)進(jìn)程建立連接
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找到與Service進(jìn)行綁定的目標(biāo)進(jìn)程翠桦,那么就會有同學(xué)發(fā)問了横蜒,這個ConnectionRecord是在哪里進(jìn)行添加記錄的呢?答案就是在我們在發(fā)起bindService的過程中销凑,在上篇博文中我們講到丛晌,在我們發(fā)戚bindService的過程中,會執(zhí)行ActivityServices#bindServiceLocked方法闻鉴,我們回顧一下這個方法:
int bindServiceLocked(IApplicationThread caller, IBinder token, Intent service,
String resolvedType, final IServiceConnection connection, int flags,
String callingPackage, final int userId) throws TransactionTooLargeException {
// 省略1萬字
AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
ConnectionRecord c = new ConnectionRecord(b, activity,
connection, flags, clientLabel, clientIntent);
IBinder binder = connection.asBinder();
ArrayList<ConnectionRecord> clist = s.connections.get(binder);
if (clist == null) {
clist = new ArrayList<ConnectionRecord>();
s.connections.put(binder, clist);
}
clist.add(c);
b.connections.add(c);
if (activity != null) {
if (activity.connections == null) {
activity.connections = new HashSet<ConnectionRecord>();
}
activity.connections.add(c);
}
b.client.connections.add(c);
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 (s.app != null) {
updateServiceClientActivitiesLocked(s.app, c, true);
}
clist = mServiceConnections.get(binder);
if (clist == null) {
clist = new ArrayList<ConnectionRecord>();
mServiceConnections.put(binder, clist);
}
clist.add(c);
// 省略1萬字
return 1;
}
去掉其他代碼后,這部分就是在啟動Service時記錄的啟動Service的進(jìn)程和該進(jìn)程的其他信息茂洒,看到這里我們就能理解bindService的執(zhí)行時序了:
回到之前的分析孟岛,在通過ConnectionRecord找到目標(biāo)進(jìn)城后,就要進(jìn)行IPC調(diào)用對目標(biāo)進(jìn)程進(jìn)行關(guān)聯(lián)了督勺,繼續(xù)循著ActiveServices#publishServiceLocked方法進(jìn)行分析渠羞,通過ConnectionRecord找到目標(biāo)進(jìn)程的IServiceConnection,IServiceConnection類長這樣:
看到這種格式就知道智哀,IServiceConnection類是AIDL生成的次询,它Service端的實(shí)現(xiàn)是InnerConnection,
InnerConnection是ServiceDispatcher的內(nèi)部類瓷叫,ServiceDispatcher是LoadedApk的內(nèi)部類屯吊,LoadedApk是目標(biāo)進(jìn)程APK在內(nèi)存中的具體實(shí)現(xiàn),回到ActiveServices#publishServiceLocked方法的解析摹菠,在這個方法中調(diào)用
c.conn.connected(r.name, service, false)盒卸,這是一次IPC過程,從AMS進(jìn)程跨進(jìn)程調(diào)用到了啟動要綁定Service的進(jìn)程次氨,那么connected方法的實(shí)現(xiàn)就一定是在InnerConnection類中:
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);
}
}
}
在connected這里調(diào)用了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);
}
}
在這里調(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);
}
}
看這個方法的最后一句蔽介,我們終于找到了onServiceConnected的執(zhí)行了
我們看一下bindService具體執(zhí)行的時序圖:
可以看到,bindService的整個執(zhí)行進(jìn)行了四次進(jìn)程跨越煮寡,可以說是非常復(fù)雜了虹蓄,但是我們在這個過程中依然沒有分析出來Binder是在什么時機(jī)轉(zhuǎn)換為BinderProxy的,篇幅有限幸撕,下一節(jié)再講吧