参考链接:
从一个简单的AIDL实现看binder原理(一)简单的AIDL实现
从一个简单的AIDL实现看binder原理(二)bindService的调用过程
BindService时Binder的转换
我们分析上面链接中的aidl实现案例,在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);
}
}
打印出的日志结果:
在org.hrcy.ipctest进程中:
![](https://img.haomeiwen.com/i3112838/790b804e9f8b8ba2.png)
在org.hrcy.ipctest:remote进程中:
![](https://img.haomeiwen.com/i3112838/868352c324112f51.png)
在demo中我们可以看到,StudentStub 继承于IAIDLInterface.Stub, IAIDLInterface.Stub 继承于android.os.Binder 也就是说 StudentStub是一个Binder对象,而在MainActivity打印出的log中我们看到,onServiceConnected方法接收到的是个BinderProxy,我们需要知道这个转换是在哪里发生的
我们回顾一下上一篇博文:
在这边文章里,我们找到了Service最终执行的地方,但是具体是怎么执行的还没有具体分析,下面我们分析一下onBind方法的具体执行
从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);
}
}
}
}
我们看第15行,从之前的分析我们可以知道,s.onBind方法执行的就是Service的onBind方法,在这里,onBind方法返回了一个Binder对象,接着执行了
ActivityManager.getService().publishService(data.token, data.intent, binder);
将获得的binder对象发送了出去,ActivityManager.getService()其实就是ActivityManagerService,这里是一个IPC的过程,具体细节不表,我们直接转到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);
}
}
在代码的第11行,这里转到了ActiveServices#publishServiceLocked执行,我们看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找到要进行通信的进程信息
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与目标进程建立连接
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进行绑定的目标进程,那么就会有同学发问了,这个ConnectionRecord是在哪里进行添加记录的呢?答案就是在我们在发起bindService的过程中,在上篇博文中我们讲到,在我们发戚bindService的过程中,会执行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的进程和该进程的其他信息,看到这里我们就能理解bindService的执行时序了:
![](https://img.haomeiwen.com/i3112838/3768bc2f6009d5e5.png)
回到之前的分析,在通过ConnectionRecord找到目标进城后,就要进行IPC调用对目标进程进行关联了,继续循着ActiveServices#publishServiceLocked方法进行分析,通过ConnectionRecord找到目标进程的IServiceConnection,IServiceConnection类长这样:
![](https://img.haomeiwen.com/i3112838/2e57bcb04adec15c.png)
看到这种格式就知道,IServiceConnection类是AIDL生成的,它Service端的实现是InnerConnection,
InnerConnection是ServiceDispatcher的内部类,ServiceDispatcher是LoadedApk的内部类,LoadedApk是目标进程APK在内存中的具体实现,回到ActiveServices#publishServiceLocked方法的解析,在这个方法中调用
c.conn.connected(r.name, service, false),这是一次IPC过程,从AMS进程跨进程调用到了启动要绑定Service的进程,那么connected方法的实现就一定是在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这里调用了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);
}
}
在这里调用了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的执行了
我们看一下bindService具体执行的时序图:
![](https://img.haomeiwen.com/i3112838/471b4367b13c945d.png)
可以看到,bindService的整个执行进行了四次进程跨越,可以说是非常复杂了,但是我们在这个过程中依然没有分析出来Binder是在什么时机转换为BinderProxy的,篇幅有限,下一节再讲吧
网友评论