长文警告:从AIDL到内核,一次完整的Binder通信

AIDL生成代码分析

AIDL使用

首先写一个IHelloInterface.aidl文件如下

interface IHelloInterface {
    void hello(String msg);
}
复制代码

build之后会生成 IHelloInterface.java文件,然后创建一个远程服务

class RemoteService : Service() {
    private val serviceBinder = object : IHelloInterface.Stub() {
        override fun hello(msg: String) {
            Log.e("remote", "hello from client: $msg")
        }
    }
    override fun onBind(intent: Intent): IBinder = serviceBinder
}
复制代码

绑定远程服务,调用服务方法

class MainActivity : AppCompatActivity() {
    private val conn = object : ServiceConnection {
        override fun onServiceConnected(name: ComponentName, service: IBinder) {
            // 这里的service就是一个BinderProxy
            // asInterface返回一个IHelloInterface.Stub.Proxy实例
            val proxy = IHelloInterface.Stub.asInterface(service)
            proxy.hello("client msg")
        }

        override fun onServiceDisconnected(name: ComponentName?) {
        }
    }
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        bindService(Intent("com.lyj.RemoteService"), conn, Service.BIND_AUTO_CREATE)
    }
}
复制代码

远程服务在onBind中返回服务端Binder实例,客户端通过binserService绑定服务后由AMS创建一个对应此服务端Binder的BinderProxy实例,回调到ServiceConnection.onServiceConnected方法中,客户端可以通过IHelloInterface.Stub.asInterface根据该BinderProxy得到一个IHelloInterface.Stub.Proxy实例,调用其中的方法进行IPC通信。

IHelloInterface分析

此文件内容主要分为三部分,这里简单拆分方便看

  • IHelloInterface接口,是远程服务的功能抽象

    public interface IHelloInterface extends android.os.IInterface {
        public void hello(java.lang.String msg) throws android.os.RemoteException;
    }
    复制代码
    
  • IHelloInterface.Stub类表示服务端实现,它本身是一个继承于Binder的抽象类,hello方法由我们使用的时候重写实现(在远程Service onBind方法中返回该类实现,重写hello方法)

    public static abstract class Stub extends android.os.Binder implements com.lyj.bindertest.IHelloInterface {
        // 类型标识
        private static final java.lang.String DESCRIPTOR = "com.lyj.bindertest.IHelloInterface";
        // 客户端服务端以此code标识hello方法
        static final int TRANSACTION_hello = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
    
        public Stub() {
            this.attachInterface(this, DESCRIPTOR);
        }
    
        // 此方法一般在ServiceConnection.onServiceConnected回调中调用,
        public static com.lyj.bindertest.IHelloInterface asInterface(android.os.IBinder obj) {
            if ((obj == null)) {
                return null;
            }
            android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
            if (((iin != null) && (iin instanceof com.lyj.bindertest.IHelloInterface))) {
                return ((com.lyj.bindertest.IHelloInterface) iin);
            }
            return new com.lyj.bindertest.IHelloInterface.Stub.Proxy(obj);
        }
    
        @Override
        public android.os.IBinder asBinder() {
            return this;
        }
    
        // 解析客户端的调用
        @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 INTERFACE_TRANSACTION: {
                    reply.writeString(descriptor);
                    return true;
                }
                case TRANSACTION_hello: {
                    // code为TRANSACTION_hello时调用hello方法
                    data.enforceInterface(descriptor);
                    java.lang.String _arg0;
                    // 从parcel中读取数据
                    _arg0 = data.readString();
                    this.hello(_arg0);
                    reply.writeNoException();
                    return true;
                }
                default: {
                    return super.onTransact(code, data, reply, flags);
                }
            }
        }
    }
    复制代码
    
  • IHelloInterface.Stub.Proxy类表示远程服务在客户端的代理,成员mRemote代表远程服务Binder对应的BinderProxy

    private static class Proxy implements com.lyj.bindertest.IHelloInterface {
      // 远程服务Binder对应的BinderProxy
      private android.os.IBinder mRemote;
    
      Proxy(android.os.IBinder remote) {
          mRemote = remote;
      }
    
      @Override
      public android.os.IBinder asBinder() {
          return mRemote;
      }
    
      @Override
      public void hello(java.lang.String msg) throws android.os.RemoteException {
          android.os.Parcel _data = android.os.Parcel.obtain();
          android.os.Parcel _reply = android.os.Parcel.obtain();
          try {
              // 写类型标识
              _data.writeInterfaceToken(DESCRIPTOR);
              // 写参数
              _data.writeString(msg);
              // 调用BinderProxy.transact开始通讯
              boolean _status = mRemote.transact(Stub.TRANSACTION_hello, _data, _reply, 0);
              if (!_status && getDefaultImpl() != null) {
                  getDefaultImpl().hello(msg);
                  return;
              }
              _reply.readException();
          } finally {
              _reply.recycle();
              _data.recycle();
          }
      }
    复制代码
    

总结一下IHelloInterface.Stub和IHelloInterface.Stub.Proxy的关系

IHelloInterface.Stub本身就是一个Binder,通过onTransact方法接收来自客户端的调用,判断code=TRANSACTION_hello调用IHelloInterface.hello接口方法。

IHelloInterface.Stub.Proxy持有一个名为mRemote的BinderProxy(内部持有服务端Binder句柄),Proxy.hello调用到BinderProxy.transact,传入code=TRANSACTION_hello,也即服务端收到的code

由此可见真正发起通信的是BinderProxy.transact,而服务端接收消息的是Binder.onTransact,AIDL只是对此简单封装。

Java层到native层的过渡

BinderProxy.transact方法开始,调用JNI方法transactNative进入native层,BinderProxy.transactNative对应native函数是android_util_Binder.cpp中的android_os_BinderProxy_transact

final class BinderProxy implements IBinder {
    public boolean transact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
        // 检查parcel数据是否大于800k
        Binder.checkParcel(this, code, data, "Unreasonably large binder buffer");
        // 调用native层
        return transactNative(code, data, reply, flags);
    }
}
复制代码

android_os_BinderProxy_transact函数中通过传入的BinderProxy对象获取对应的BpBinder指针,然后调用BpBinder::transact

frameworks\base\core\jni\android_util_Binder.cpp

static jboolean android_os_BinderProxy_transact(JNIEnv* env, jobject obj,
        jint code, jobject dataObj, jobject replyObj, jint flags) // throws RemoteException
{
    // Java Parcel转为native Parcel
    Parcel* data = parcelForJavaObject(env, dataObj);
    Parcel* reply = parcelForJavaObject(env, replyObj);
    // 从Java BinderProxy对象获取BpBinder指针
    IBinder* target = (IBinder*) env->GetLongField(obj, gBinderProxyOffsets.mObject);
    // 调用BpBinder.transact
    status_t err = target->transact(code, *data, reply, flags);
    return JNI_FALSE;
}
复制代码

BpBinder调用到IPCThreadState.transactIPCThreadState::self获取当前线程IPCThreadState单例,不存在则创建。在上一篇文章中提到过,进行Binder通信的线程在native端对应一个IPCThreadState对象。 frameworks\native\libs\binder\BpBinder.cpp

status_t BpBinder::transact(
    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
    if (mAlive) {
        // mHandle是接收端BBinder的句柄
        status_t status = IPCThreadState::self()->transact(
            mHandle, code, data, reply, flags);
        if (status == DEAD_OBJECT) mAlive = 0;
        return status;
    }
    return DEAD_OBJECT;
}
复制代码

创建IPCThreadState

IPCThreadState::self做的事很简单,获取当前线程IPCThreadState单例对象(pthread_getspecific可以看从ThreadLocal中获取),不存在则调用空参构造函数创建

frameworks\native\libs\binder\IPCThreadState.cpp

IPCThreadState* IPCThreadState::self()
{
    // 是否已创建
    if (gHaveTLS) {
restart:
        const pthread_key_t k = gTLS;
        // 从线程私有空间获取
        IPCThreadState* st = (IPCThreadState*)pthread_getspecific(k);
        if (st) return st;
        return new IPCThreadState;
    }
    if (gShutdown) {
        return NULL;
    }
    // 线程同步锁
    pthread_mutex_lock(&gTLSMutex);
    if (!gHaveTLS) {
        int key_create_value = pthread_key_create(&gTLS, threadDestructor);
        if (key_create_value != 0) {
            pthread_mutex_unlock(&gTLSMutex);
            return NULL;
        }
        gHaveTLS = true;
    }
    pthread_mutex_unlock(&gTLSMutex);
    goto restart;
}
复制代码
IPCThreadState::IPCThreadState()
    // 赋值ProcessState
    : mProcess(ProcessState::self()),
      mStrictModePolicy(0),
      mLastTransactionBinderFlags(0)
{
    // 当前对象存到当前线程私有空间
    pthread_setspecific(gTLS, this);
    clearCaller();
    // mIn、mOut两个parcel对象用于从binder驱动读写数据
    mIn.setDataCapacity(256);
    mOut.setDataCapacity(256);
}
复制代码

IPCThreadState构造函数中我们主要关注ProcessState实例的获取赋值,它是一个进程范围内的单例对象,ProcessState::self获取该对象,不存在则创建。实际上在此调用处ProcessState单例已经存在了上一篇文章提到过,每个App进程在被Zygote进程fork出以后会调用到app_main.cpp onZygoteInit函数,在此创建该进程ProcessState并开启binder线程池。关于应用进程启动过程本文不加赘述,可以自行看源码,下面我们直接从onZygoteInit函数来看看Binder的初始化。

进程中的Binder初始化

frameworks\base\cmds\app_process\app_main.cpp

virtual void onZygoteInit()
{
    sp<ProcessState> proc = ProcessState::self();
    // 启动binder线程池
    proc->startThreadPool();
}
复制代码

创建ProcessState

frameworks\native\libs\binder\ProcessState.cpp

sp<ProcessState> ProcessState::self()
{
    // 进程互斥量
    Mutex::Autolock _l(gProcessMutex);
    if (gProcess != NULL) {
        return gProcess;
    }
    gProcess = new ProcessState("/dev/binder");
    return gProcess;
}
复制代码

ProcessState构造函数中先调用open_driver打开binder驱动,然后通过mmap系统调用到Binder驱动中binder_mmap方法开启用于接收数据的内存映射

ProcessState::ProcessState(const char *driver)
    // 打开binder,mDriverFD保存该文件描述符
    : mDriverFD(open_driver(driver))
    ......
    // 最大binder线程数,值为15
    : mMaxThreads(DEFAULT_MAX_BINDER_THREADS)
{
    if (mDriverFD >= 0) {
        // 调用binder_mmap建立(1M-8k)内存映射区
        mVMStart = mmap(0, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);
        if (mVMStart == MAP_FAILED) {
            close(mDriverFD);
            mDriverFD = -1;
            mDriverName.clear();
        }
    }
}
复制代码

open_driver中主要调用到内核层Binder进行初始化

  1. open系统调用对应到driver层binder_open,返回的fd是一个文件描述符,后续操作需要传递此fd
  2. ioctl BINDER_VERSION调用到driver层binder_ioctl BINDER_VERSION case,用于获取内核binder版本
  3. ioctl BINDER_SET_MAX_THREADS调用到driver层binder_ioctl BINDER_SET_MAX_THREADS case,在驱动中设置该进程的线程数量限制
static int open_driver(const char *driver)
{
    int fd = open(driver, O_RDWR | O_CLOEXEC);
    if (fd >= 0) {
        int vers = 0;
        // 获取内核binder版本
        status_t result = ioctl(fd, BINDER_VERSION, &vers);
        if (result == -1) {
=            close(fd);
            fd = -1;
        }
        // 对比内核binder版本和framework中binder版本
        if (result !
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值