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.transact
,IPCThreadState::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进行初始化
- open系统调用对应到driver层binder_open,返回的fd是一个文件描述符,后续操作需要传递此fd
- ioctl BINDER_VERSION调用到driver层binder_ioctl BINDER_VERSION case,用于获取内核binder版本
- 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 !