0
点赞
收藏
分享

微信扫一扫

从AIDL来看Binder的通信原理(基于Andorid8.0)


首先感谢:
​​​从AILD与bindService谈Binder进程间通信原理(上)​​ 解答了我很多疑惑, 但由于上述文章的源码是7.0的,Java框架层没有用AIDL,所以我想根据新的源码(8.0)来理解Binder的知识。

前几天在学习一些Binder机制(较浅)后,我就在趁热打铁看看AIDL的一些东西,在学习的时候发现了几点疑问,并且网上鲜有解答:

  1. ​ServiceManager​​管理的是系统服务,那我们自定义的Service会注册到ServiceManager中吗?
  2. 为什么AIDL中的跨进程下asInterface()会返回​​BinderProxy​​?我们在Service的启动流程没有留意到这个类呀?

不过最后我一些地方还是有些模糊,如果大神能有幸阅读我的文章,请麻烦指出我文中的错误!我定查阅改正。

1.关于系统Service和自定义Service的区别

这里是 bindService在应用层 - framwork层的绑定流程,源码基于8.0:​​Service的startService和bindService源码流程​​​ 或者阅读《Android进阶解密》第四章
这里是关于系统服务和ServiceManager在基于Binder角度 注册、获取、使用上的流程,源码基于9.0,也是皇叔写的:​​​Binder原理​​

可以大概总结出他们的区别:

  1. 系统Service
    是指在 SystemServer进程开启后,通过​​​startBootstrapServices()​​​、​​startCoreServices()​​​、​​startOtherServices()​​​所开启的服务,他们显示地通过​​add_service()​​​注册在了​​ServiceManager​​​中。
    之后客户端进程想要使用系统Service,需要通过 ServiceManager的进程来查看是否有目标Service,然后再来获取和使用
  2. 自定义Service
    通过​​​startService()​​​和​​bindService()​​​两种方式开启,在framwork框架层中没有发现流程中使用add_service方法(甚至都没出现ServiceManager)。
    ↑ 这就看出无论自定义Service最后在不在ServiceManager中,Android本身是不希望我们通过ServiceManager的途径去获取使用自定义Service的。

上述第二条的结论,原因是什么?我不是很清楚,但是基于结论来看:
只要一个进程持有另一进程的BinderProxy类,那我还去找 ServiceManager干什么,这不更加省事吗?

所以,在自定义的流程中把ServiceManager忽略掉,我们就不用考虑Service到底有没有注册在ServiceManager中了。

2. 从AIDL上看Binder

AIDL本质上是在Java层对Binder进行了封装。所以Android8.0前后AMS是否使用了AIDL,本质都是使用Binder + 代理模式,只是说使用了 AIDL通过编译时生成代码,节省了一些代码的编写,提高了开发效率。

那么我们就从编译时产生的代码开始,来看看Binder的运作机制,这里使用的例子是:​​使用AIDL来进行进程间通信​​,就是一个 Service远程服务 + User类 + IUserManager代理类

2.1 用于进程传输的Stub类

在编译文件产生的 IUserManager中,它是一个接口类,同时它有一个静态内部类 ​​Stub​​:

// IUserManager.java
// 0
public static abstract class Stub extends android.os.Binder implements com.rikkatheworld.aidl_demo.IUserManager {
private static final java.lang.String DESCRIPTOR = "com.rikkatheworld.aidl_demo.IUserManager";

// 1
public Stub() {
this.attachInterface(this, DESCRIPTOR);
}

// 2
public static com.rikkatheworld.aidl_demo.IUserManager asInterface(android.os.IBinder obj) {
...
}

// 3
@Override
public android.os.IBinder asBinder() {
return this;
}

// 4
@Override
public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException {
...
}

// 5
private static class Proxy implements com.rikkatheworld.aidl_demo.IUserManager {
private android.os.IBinder mRemote;

Proxy(android.os.IBinder remote) {
mRemote = remote;
}
...

// 6
@Override
public com.rikkatheworld.aidl_demo.User getUser(java.lang.String name) throws android.os.RemoteException {
....
}
}
}

Stub类分成两个部分,一个是自己本身的成员方法,另一个是Proxy类,先来看看这些成员。

(1)自身部分

  1. 注释0
    Stub类继承自​​​Binder​​,说明这个类是用于进程间传输的。
  2. 注释1​​Stub()​​ 构造方法,把自身和标记自身的descriptor传入,后者用于表明身份
  3. 注释2​​asInterface(obj)​​ 静态方法, 处理ActivityManagerService丢给我们的 IBinder,将它转换成 客户端进程想要的类。
  4. 注释3:​​asBinder()​​ 用于Binder传输的过程,需要转换自身的类型,Stub(A进程)->IBinder(Binder)->Stub(B进程),就用到这个方法,这个例子非常粗糙,可能也有问题,但是这个方法是辅助用的,我们不需要对这个方法深入理解。
  5. 注释4 :​​onTransact()​​ 重写父类的 onTrancsact,这个方法是客户端进程在使用Binder进行数据传输时需要用到的数据。

(2)Proxy代理类

  1. 注释5
    静态内部类,实现了 IUserManager接口
    内部定义了一个 IBinder类型的 mRemote对象
  2. 注释6
    实现方法,如果客户端进程要跨进程调用Server端的方法,就要通过调用这些方法。

我们看看客户端进程是怎么使用这个类的:

private ServiceConnection mServiceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
// 1
IUserManager userManager = IUserManager.Stub.asInterface(service);
try {
User user = userManager.getUser("Rikka");
} catch (RemoteException e) {
e.printStackTrace();
}
}

@Override
public void onServiceDisconnected(ComponentName name) {
}
};

AIDL的客户端进程,在 ​​onServiceConnected()​​​中拿到 AMS传过来的 service,通过 ​​asInterface()​​转化成 IUserManager,然后调用它的方法,就能完成跨进程的方法调用了。

我们来看看 ​​asInterface()​​具体实现:

// IUserManager.java
...
public static com.rikkatheworld.aidl_demo.IUserManager asInterface(android.os.IBinder obj) {
if ((obj == null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin != null) && (iin instanceof com.rikkatheworld.aidl_demo.IUserManager))) {
return ((com.rikkatheworld.aidl_demo.IUserManager) iin);
}
return new com.rikkatheworld.aidl_demo.IUserManager.Stub.Proxy(obj);
}
...

可以看出调用了 ​​queryLocalInterface()​​获得一个 IInterface类型的对象iin,如果iin不为空,则返回iin,如果为空,则 new一个 Proxy类并返回。

我们知道AMS给我们返回的一定是Binder的对象,所以我们去 Binder中看看​​queryLocalInterface()​​:

// Binder.java
public class Binder implements IBinder {
...
// 1
public @Nullable IInterface queryLocalInterface(@NonNull String descriptor) {
if (mDescriptor != null && mDescriptor.equals(descriptor)) {
return mOwner;
}
return null;
}
...
}
// 2
final class BinderProxy implements IBinder {
// 3
public IInterface queryLocalInterface(String descriptor) {
return null;
}
...
}

可以发现Binder文件中,有两处实现了这个方法,在Binder类中。
注释1中 通过 descriptor标识来返回,mOwner是Bidner本身。
注释2、3是 ​​​BinderProxy​​实现的,直接返回一个空。

在Stub类的构造方法里我们就看到了只要​​Stub​​被构建就会调用:

public Stub() {
this.attachInterface(this, DESCRIPTOR);
}

按理来说,​​queryLocalInterface​​不可能返回为空,我们应该都是得到一个正宗的 Stub类才对,但是实际上这里出现了偏出。

在跨进程服务中,我们通过 asInterface() 返回的是一个 ​​IUserManager.Stub.Proxy​​​的对象。这就说明 ​​queryLocalInterface()​​​返回了空,只有一种情况会导致这种结果, 那就是 ServiceConnection返回来的值是一个 ​​BinderProxy​​类型的对象。

这就是我最开始的疑问点,为什么 ​​onServiceConnection()​​​中远端进程和同进程下返回的是Binder,而不同进程下返回的是​​BinderProxy​​。

2.2 BindService 客户端进程传出流程

Binder机制是C/S架构,任意两个进程,请求方是C端,接收方是S端
C端通过 ​​​BpBinder​​​来访问S端,S端通过 ​​BBinder​​​来访问C端,而​​BpProxy​​就是BpBinder的封装类。他们的具体知识这里就不再赘述了。详情请看皇叔的文章。下面以框架层角度画个图来看下 客户端进程的数据传出经过了什么方法:

从AIDL来看Binder的通信原理(基于Andorid8.0)_android

万物的开端在于BindService,在 ​​Service的startService和bindService源码流程​​​中,我们知道主进程的最终代码是到 ​​ContextImpl.bindServiceCommon()​​:

// ContextImpl.java
private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags, Handler
handler, UserHandle user) {
IServiceConnection sd;
if (mPackageInfo != null) {
sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), handler, flags);
} else {
throw new RuntimeException("Not supported in system context");
}
...
try {
IBinder token = getActivityToken();
...
int res = ActivityManager.getService().bindService(
mMainThread.getApplicationThread(), getActivityToken(), service,
service.resolveTypeIfNeeded(getContentResolver()),
sd, flags, getOpPackageName(), user.getIdentifier());
...
} ...
}
// ActivityManager
public static IActivityManager getService() {
return IActivityManagerSingleton.get();
}

private static final Singleton<IActivityManager> IActivityManagerSingleton =
new Singleton<IActivityManager>() {
@Override
protected IActivityManager create() {
final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
final IActivityManager am = IActivityManager.Stub.asInterface(b);
return am;
}
};

ActivityManager.getService()是 ​​IActivityManager.Stub.asInterface(b)​​,这个肯定是Proxy类(套娃了,不过问题不大),我们要来看看bindService做了什么,由于IActivityManager是编译产生的,所以我暂时还没有找到IActivityManager,但是我们知道 它的实现肯定和我们自己所编译出来的如出一辙,甚至我们自己都可以写出来:

// 这个地方是照着 IUserManger.Stub.Proxy 仿写的,也看了开篇Blog的内容
// IActivityManager.Stub.Proxy
@Override
public int bindService(IApplicationThread caller, IBinder token,
Intent service, String resolvedType, IServiceConnection connection, int flags, int userId) throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain(); // 1
android.os.Parcel _reply = android.os.Parcel.obtain(); // 2
int _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeStrongBinder(caller != null ? caller.asBinder() : null); // 3
_data.writeStrongBinder(token); // 4
service.writeToParcel(data, 0);
_data.writeString(resolvedType);
_data.writeStrongBinder(connection.asBinder()); // 5
_data.writeInt(flags);
_data.writeInt(userId);
mRemote.transact(TRANSACTION_bindService, data, reply, 0); // 6
reply.readException();
_result = reply.readInt(); // 7
} finally {
_reply.recycle();
_data.recycle();
}
return _result;
}

注释1:获得一个传出去的序列化数据 data
注释2:获得一个用于接收的序列化数据 reply
注释3、4、5: 通过 ​​​writeStrongBinder()​​​把 Binder数据写入到 data中
注释6:调用原生层的 ​​​transact()​​​,传入数据
注释7:在返回结果reply读出数据result

其中,注释3、4、5、6是这个方法的关键。就是参数是这么从客户端进程传出去的。
我们来看看 ​​​writeStrongBinder()​​,它是一个native方法:

// frameworks/base/core/jni/android_os_Parcel.cpp
static void android_os_Parcel_writeStrongBinder(JNIEnv* env, jclass clazz, jlong nativePtr, jobject object)
{
Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
if (parcel != NULL) {
const status_t err = parcel->writeStrongBinder(ibinderForJavaObject(env, object));
if (err != NO_ERROR) {
signalExceptionForError(env, clazz, err);
}
}
}

这里调用了两个函数, 一个是调用了 ​​ibindForJavaObject​​​得到一个IBinder,在传入到 ​​Parcel->writeStrongBinder()​​​中:
先来看看前者

// frameworks/base/core/jni/android_os_Parcel.cpp
sp<IBinder> ibinderForJavaObject(JNIEnv* env, jobject obj)
{
if (obj == NULL) return NULL;

if (env->IsInstanceOf(obj, gBinderOffsets.mClass)) {
JavaBBinderHolder* jbh = (JavaBBinderHolder*)
env->GetLongField(obj, gBinderOffsets.mObject);
return jbh != NULL ? jbh->get(env, obj) : NULL; // 1
}
if (env->IsInstanceOf(obj, gBinderProxyOffsets.mClass)) {
return (IBinder*)
env->GetLongField(obj, gBinderProxyOffsets.mObject); // 2
}
return NULL;
}

注释1:如果传进来的binder是 gBinderOffsets,则 new一个 ​​JavaBBinder​​​并返回。
注释2:如果传进来的bind是 gBinderProxyOffsets(代理类),类中的 代理对象。(也就是封装在里面了,取出来用)

由于我们是客户端进程,所以进来的并不是代理类,所以 ​​ibinderForJavaObject()​​​会返回一个 JavaBBinder返回给我们。
再来看看 Parcel.writeStrongBinder():

// frameworks\native\libs\binder\Parcel.cpp
status_t Parcel::writeStrongBinder(const sp<IBinder>& val)
{
return flatten_binder(ProcessState::self(), val, this);
}

status_t flatten_binder(const sp<ProcessState>& /*proc*/,
const sp<IBinder>& binder, Parcel* out)
{
...
if (binder != NULL) {
IBinder *local = binder->localBinder(); // 1
if (!local) {
BpBinder *proxy = binder->remoteBinder();
if (proxy == NULL) {
ALOGE("null proxy");
}
const int32_t handle = proxy ? proxy->handle() : 0;
obj.type = BINDER_TYPE_HANDLE;
obj.binder = 0; /* Don't pass uninitialized stack data to a remote process */
obj.handle = handle;
obj.cookie = 0;
} else {
obj.type = BINDER_TYPE_BINDER; // 2
obj.binder = reinterpret_cast<uintptr_t>(local->getWeakRefs());
obj.cookie = reinterpret_cast<uintptr_t>(local);
}
} else {
obj.type = BINDER_TYPE_BINDER;
obj.binder = 0;
obj.cookie = 0;
}

return finish_flatten_binder(binder, obj, out);
}

inline static status_t finish_flatten_binder(
const sp<IBinder>& /*binder*/, const flat_binder_object& flat, Parcel* out)
{
return out->writeObject(flat, false);
}

在writeStrongBinder中调用了 ​​flatten_binder()​​​,
注释1:localBinder()是取出Binder中的数据,用来标识传入Binder的进程是否是当前进程,所以local不为null,会走到else中去
注释2:设置 type为 ​​​BIND_TYPE_BINDER​

最后把这些数据写到输出数据中。也就是一开始我们的 _data。

接下来看下 ​​mRemote.transact()​​​这个方法,mRemote是 ​​ServiceManager​​​返回给我们的,它是一个 BinderProxy对象,所以会调用 ​​BinderProxy.transact()​​:

// Binder.java
// BinderProxy ->
public boolean transact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
....
try {
return transactNative(code, data, reply, flags);
} ...
}

调用了 native层的 ​​transactNative()​​:

// android_util_Binder.cpp
static jboolean android_os_BinderProxy_transact(JNIEnv* env, jobject obj,
jint code, jobject dataObj, jobject replyObj, jint flags) // throws RemoteException
{
...
Parcel* data = parcelForJavaObject(env, dataObj); // 1
..
Parcel* reply = parcelForJavaObject(env, replyObj); // 2
...
IBinder* target = (IBinder*)
env->GetLongField(obj, gBinderProxyOffsets.mObject); // 3
....
status_t err = target->transact(code, *data, reply, flags); // 4
....
}

注释1、2:通过 ​​parcelForJavaObject()​​​ 把 Java层的Parce -> Natve层的Parcel,data是参数数据,reply是结果数据
注释3:把 java层的 ActivityManagerService的 ​​​BinderProxy​​​ 转换成 Native层的 ​​BpBinder​​​ 注释4:调用 ​​BpBinder.transact()​

到这里我就不往下说了,BpBinder会调用 ​​IPCThreadState.transact()​​​ 、​​writeData()​​​、​​talkWithDriver()​​​、​​waitForResponse()​​​等方法去深入到 Kernel层的Binder,具体请看: ​​Android Binder原理(三)系统服务的注册过程​​,里面写了一个系统服务注册到ServiceManager的过程,其中就有上述接下来的过程。

这样我们的Binder数据就从客户端进程传出去了。

2.3 ActivityManagerService接收数据

如果一个支持Binder通信的进程被创建后,它会开启一条线程加入到Binder线程池中,并通过 ​​joinThreadPool()​​​开启死循环,读 Binder驱动中的 ​​BR_TRANSACTION​​​(因为客户端进程传入的是 ​​BC_TRANSACTION​​)命令,具体可以看 《Android进阶解密》第三章 应用程序进程的创建。

// IPCThreadState.cpp
void IPCThreadState::joinThreadPool(bool isMain)
{
...
do {
...
result = getAndExecuteCommand();
...
} while (result != -ECONNREFUSED && result != -EBADF);
...
talkWithDriver(false);
}

可以看到在死循环中不断调用 ​​getAndExecuteCommand()​​:

status_t IPCThreadState::getAndExecuteCommand()
{
...
result = talkWithDriver();
if (result >= NO_ERROR) {
size_t IN = mIn.dataAvail();
if (IN < sizeof(int32_t)) return result;
cmd = mIn.readInt32();
...
result = executeCommand(cmd);

...
}

return result;
}

// IPCThreadState.cpp
status_t IPCThreadState::talkWithDriver(bool doReceive)
{
if (mProcess->mDriverFD <= 0) {
return -EBADF;
}
//和Binder驱动通信的结构体
binder_write_read bwr; //1
//mIn是否有可读的数据,接收的数据存储在mIn
const bool needRead = mIn.dataPosition() >= mIn.dataSize();
const size_t outAvail = (!doReceive || needRead) ? mOut.dataSize() : 0;
bwr.write_size = outAvail;
bwr.write_buffer = (uintptr_t)mOut.data();//2
//这时doReceive的值为true
if (doReceive && needRead) {
bwr.read_size = mIn.dataCapacity();
bwr.read_buffer = (uintptr_t)mIn.data();//3
} else {
bwr.read_size = 0;
bwr.read_buffer = 0;
}
...
if ((bwr.write_size == 0) && (bwr.read_size == 0)) return NO_ERROR;
bwr.write_consumed = 0;
bwr.read_consumed = 0;
status_t err;
do {
IF_LOG_COMMANDS() {
alog << "About to read/write, write size = " << mOut.dataSize() << endl;
}
#if defined(__ANDROID__)
if (ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr) >= 0)//4
err = NO_ERROR;
else
err = -errno;
#else
err = INVALID_OPERATION;
#endif
...
} while (err == -EINTR);
...
return err;
}

​talkWithDriver()​​​ 就是通过 ​​ioctl​​​读取有没有想要的BR数据,有就响应,调用 ​​executeCommand()​​:

status_t IPCThreadState::executeCommand(int32_t cmd)
{
BBinder* obj;
RefBase::weakref_type* refs;
status_t result = NO_ERROR;

switch ((uint32_t)cmd) {
....
case BR_TRANSACTION:
{
binder_transaction_data tr; // 1
result = mIn.read(&tr, sizeof(tr)); // 2
....
Parcel buffer;
buffer.ipcSetDataReference(
reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer),
tr.data_size,
reinterpret_cast<const binder_size_t*>(tr.data.ptr.offsets),
tr.offsets_size/sizeof(binder_size_t), freeBuffer, this); // 3
....
Parcel reply;
status_t error;
if (tr.target.ptr) {
if (....) {
error = reinterpret_cast<BBinder*>(tr.cookie)->transact(tr.code, buffer,
&reply, tr.flags); // 4
}
} ...
....
}
break;
...
return result;
}

这里只要截取 ​​BR_TRANSACTION​​​,因为客户端进程发的是 ​​BC_TRANSATION​​​ 注释1:创建 ​​binder_transaction_data​​ 结构体的对象tr,它是IPCThread专用的 Parcel包, 在客户端进程的IPCThreadState调用transact时也是用这个类型
注释2:mIn是Binder驱动的读到的Parcel数据,通过 read()方法把这些数据写入到 tr中
注释3:通过写好的数据重新构造一个 Parcel包。(把它修改成AMS用的包)
注释4:调用 ​​BBinder.transact()​​,这里的 BBinder是指 ActivityManagerService在Service端的对象,也就是自己。最后会调用自己的 ​​onTransact()​​,会调用父类也就是 ​​IActivityManager.onTransact()​

在 ​​IActivityManager​​​对 onTransact应该是对 ​​TRANSACTION_bindService()​​​case处理,虽然我们没有 IActivityManager这个类,但是我们通过 ​​IUserManager​​文件,可以仿写一份 IActivityManager的代码:

// 跟IActivityManager.Stub.Proxy类一样, 根据 IUserManager 仿写 IActivityManager.Stub.onTransact(),
// 代码参照开篇Blog,即Android7.0 的Binder返回的处理
@Override
public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException {
java.lang.String descriptor = DESCRIPTOR;
switch (code) {
...
case TRANSACTION_bindService: {
data.enforceInterface(descriptor);
IBinder b = data.readStrongBinder(); // 1
IApplicationThread app = ApplicationThreadNative.asInterface(b);
IBinder token = data.readStrongBinder();
Intent service = Intent.CREATOR.createFromParcel(data);
String resolvedType = data.readString();
b = data.readStrongBinder();
IServiceConnection conn = IServiceConnection.Stub.asInterface(b);
int fl = data.readInt();
int userId = data.readInt();
int res = bindService(app, token, service, resolvedType, conn, fl, userId); // 5
reply.writeNoException();
reply.writeInt(res);
return true;
}
default: {
return super.onTransact(code, data, reply, flags);
}
}
}

在拿到 natvie层的Pacel包后,进行拆包。
注释1-2前:通过readString() 、readInt()、 ​​​readStrongBinder()​​​拆包,怎么装包的就怎么拆包
注释2:执行 ​​​ActivityManagerService.bindService()​​,正式开启 AMS之旅。

我们来看看解包的一个方法 ​​readStrongBinder()​​​,它和装包的 ​​writeStrongBinder()​​对应:

// Parcel.cpp
status_t Parcel::readStrongBinder(sp<IBinder>* val) const
{
status_t status = readNullableStrongBinder(val);
if (parcel != NULL) {
return javaObjectForIBinder(env, parcel->readStrongBinder());
}
return status;
}

status_t Parcel::readNullableStrongBinder(sp<IBinder>* val) const
{
return unflatten_binder(ProcessState::self(), *this, val);
}

readStrongBinder()调用了 ​​readNullableStrongBinder()​​​,它里面调用了 ​​unflatten_binder()​​:

// Parcel.cpp
status_t unflatten_binder(const sp<ProcessState>& proc,
const Parcel& in, sp<IBinder>* out)
{
const flat_binder_object* flat = in.readObject(false);
if (flat) {
switch (flat->type) {
case BINDER_TYPE_BINDER:
*out = reinterpret_cast<IBinder*>(flat->cookie);
return finish_unflatten_binder(NULL, *flat, in);
case BINDER_TYPE_HANDLE:
*out = proc->getStrongProxyForHandle(flat->handle); // 1
return finish_unflatten_binder(
static_cast<BpBinder*>(out->get()), *flat, in);
}
}
return BAD_TYPE;
}

我们在客户端进程传入进来flat的是 ​​BINDER_TYPE_BINDER​​​, 但是我跟你讲,这里拿到的是 ​​BINDER_TYPE_HANDLE​​,因为

  1. 如果是非跨进程调用
    数据Parcel包在kernel层不会做修改
  2. 如果是跨进程调用
    kernel层的​​​binder_transaction()​​​会修改这个值,即​​BINDER_TYPE_BINDER​​​ ->​​BINDER_TYPE_HANDLE​

所以这里会在注释1中得到一个 ​​BpBinder​​,然后返回。

也就是说 ​​readStrongBinder(Parcel)​​​可以拿到 parcel包里面的 的Binder数据并转化为 BpBinder, 然后把BpBinder通过 ​​Parcel.javaObjectForIBinder()​​​转换成 ​​BinderProxy​​。在Android7.0可以找到这个转换,8.0后我突然找不到了…不知道为什么。以后找机会再查查吧。

到这里,就已经明了了,客户端进程的 Binder 到了 服务端进程后 会包装成 BinderProxy。
这句话也可以换成:
任意一个进程的IBinder 通过 Binder机制 到达了另外一个进程后,就会包装成一个 BinderProxy。
这就回到了我最开始的第二点疑问,通过Service -> AMS -> MainActivity.onServiceConnection(IBinder) 中的 IBinder是一个BindProxy类。

3. 总结

从一开始我的两个问题,到现在也算是解决了。
自定义Service并不需要通过 ​​​addService()​​​来加入到 ServiceManager,因为它只要别的进程能够持有它的BinderProxy,就可以调用它的方法。
其次 Binder在跨进程后会转换成 BindProxy,这也是为什么AIDL中能够拿到 Proxy类。

至此,通过AIDL来看Binder原理也就写完了。但是还没有结束,因为我上面应该是由一些还没有具体解决的点,我列一下:

  1. ​IActivityManager​​的代码到底时怎么样的?
  2. Android7.0 的​​readStrongBinder()​​​显示的用了​​javaObjectForIBinder()​​把 unflatten_binder得到 BpBinder转换成了 BinderProxy,但是Andorid8.0我却没有看到这样的代码,到了BpBinder就好了…不知道是不是我看漏了,反正查了半天没查到…

如果有大牛看到希望可以解答我的疑问。


举报

相关推荐

0 条评论