Java 层添加服务

2019-10-30  本文已影响0人  Wi1ls努力努力再努力

以 AMS 为例
//ActivityManagerService.java

public void setSystemProcess( ){
  ServiceManager.addService(Context.ACTIVITY_SERVICE, this, true);
}

//ServiceManager.java

public static addService(String name, IBinder service, boolean allowIsolated){
  getIServiceManager( ).addService(name, service, allowIsloted)
}

private static IServiceManager getIServiceManager(){
  sServiceManager = ServiceManagerNative.getInterface(BinderInternal.getContextObject);
}

//android_utils_Binder.cpp

//该方法返回一个 Java 层的BinderProxy 对象,同时持有下面的 BpBinder(handle = 0)的句柄
static jobject android_os_BinderInternal_getContextObject(JNIEnv* env, jobject clazz){
  sp<IBinder> b = ProcessState::self()->getContextObject(NULL);
  return javaObjectForIBinder(env, b);
}

//ProcessState.cpp

//改方法返回一个 BpBinder(handle = 0)
sp<IBinder> ProcessState::getContextObject(const sp<IBinder>&){
  return getStrongProxyForHandle(0);
}

//ServiceManagerNative.java

static public IServiceManager asInterface(IBinder obj){
  return new ServiceManagerProxy(obj)
}

经过一系列的反应,最后再 AMS 进程中,service_manager 在 AMS 中的代理表现为

ServiceManagerNativeServiceManagerProxy.java 对象,该对象内部有一个 mRemote 成员变量表现为BinderProxy.java对象。BinderBidnerProxy.java 对象内部有成员变量 mObject,表现为 native 层BpBinder.cpp对象。BpBinder.cpp 对象内部有一个 handle 为0,表示 service_manager 在 binder 驱动中的注册编号

--重头戏---

addService( )@ServiveManager.java
⤵️
addService( )@ServiceManagerNative$ServiceManagerProxy.java
⤵️
transact(ADD_SERVICE_TRANSACTION)@Binder$BinderProxy.java
⤵️
android_os_BinderProxy_transact()@android_util_Binder.cpp
⤵️
transact( )@BpBinder.cpp
⤵️
transact( )@IPCThreadState.cpp
⤵️
ioctl()@IPCThreadState.cpp使用的 cmd 就是 BINDER_WRITE_READ

接下来看每一层的数据打包过程。

//参数,name = "activity", service 是 ActivityManagerService, allowIsolated=true
public void addService(String name,IBinder service, boolean allowIsolated){
  Parcel data = Parcel.obtain( )
  Parcel reply = Parcel.obtain( )
  data.writeInterfaceToken(IServiceManager.descriptor);
  data.writeString(name);
  data.writeStrongBinder(service);
  data.writeInt(allowIsolated? 1 : 0);
  mRemote.transact(ADD_SERVICE_TRANSACTION, data, reply, 0);
  reply.recycle( );
  data.recycle( );
}

关于 Parcel 打包,参见link
此时 Parcel data 打包了一些基础数据类型,将 ActivityManagerService.java 封装成了 flat_binder_object 打包进 Parcel。
//BinderProxy

//code 就是 ADD_SERVICE_TRANSACT, data 是封装了请求信息,reply 没有内容,flags=0
public boolean transact(int code, Parcel data, Parcel reply, int flags){
  return transactNative(code, data, reply, flags)
}

//android_utils_Binder.cpp

static jboolean android_os_BinderProxy_transact(JNIEnv* env, jobject obj, jint code, jobject dataObject, jobject replyObj, jint flags){
  //从 Parcel.java 中的 mNativePtr 获得 native 层的 Parcel.cpp
  Parcel* data = parcelForJavaObject(env, dataObj);
  Parcel* reply = parcelForJavaObject(env, replyObj);
  //从 BinderProxy.java 获得 BpBinder
  //此处 BpBinder 中的 handle = 0,代表 service_manager
  IBinder* target = (IBinder*) env->GetLongField(obj, gBinderProxyOffsets.mObject);

  status_t err = target->transact(code, *data, reply, flags)
}

//BpBinder.cpp

status BpBinder::transact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags){
  status_t status = IPCThreadState::self()->transact(mHandle, code, data, reply. flags);
}

//IPCThreadState.cpp

status_t IPCThreadState::transact(int32_t handle, uint32_T code, const Parcel& data, Parcel* reply, uint32_t flags){
  //表示通讯 cmd 是 BC_TRANSACTION,表示向 Binder 驱动发送消息
  //handle = 0 表示向 handle = 0 的服务,即 service_manager 发送消息
  //code = ADD_SERVICE,该码用来给目标服务表示要调用的方法
  //data 包含了请求的参数
  //于是 handle,code,data 包含了目标对象,目标方法,方法参数
  writeTransactionData(BC_TRANSACTION, flags, handle, code, data);
  //真正发起 RPC 通讯
  waitForResponse(reply)
}

status_t IPCThreadStatus::writeTransactionData(int32_t cmd, uint32_t binderFlags, int32_t handle, uint32_t code, const Parcel& data, status_t* statusBuffer){
  //IPCThreadStatus 层的包装协议是 binder_transaction_data,在目标进程也按照该协议进行拆箱
  //cmd = BC_TRANSACTION 是该层的命令协议
  //封装的 binder_transaction_data 连同 cmd 打包进了 mOut
  binder_transaction_data tr;

  tr.target.ptr = 0;
  tr.target.handle = handle;
  tr.code = code;
  tr.flags = binderFlags;
  tr.cookie=0
  tr.sender_pid = 0;
  tr.sender_euid = 0;
  tr.data_size = data.ipcDataSize( );
  tr.data.ptr.buffer = data.ipcData();
  tr.offsets_size = data.ipcObjecCount()*sizeof(binder_size_t);
  tr.data.ptr.offet = data.ipcObjects( );

  mOut.writeInt32(cmd)
  mout.write(&tr, sizeof(tr))
}

status_t IPCThreadStatus::waitForResponse(Parcel * reply, status_t *acquireResult){
  //进行 PRC
  talkWithDriver();
  //处理 RPC 返回结果
  ...
}

status_t IPCThreadStatus::talkWithDriver(boolean doReceive){
  //与 Binder 驱动交换数据
  binder_write_read bwr;
  bwr.write_siez = outAvail;
  bwr.write_buffer = (uintptr_t)mOut.data()
  ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr)
}

接下来看通讯的解包装
//binder.c,此时是在 kernel中运行

static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long args){
  //获得发起请求的进程 binder_proc 结构
  struct binder_proc *proc = filp->private_data;
  struct binder_thread *thread;
  //用户空间的 binder_write_read 的指针
  void __user *ubuf = (void __user *)arg;
  //kernal将当前进程,即发起请求的进程进行休眠。直到被唤醒
  //如果 binder_stop_on_user_error < 2则直接跳过不会挂起
  wait_event_interruptible(binder_user_error_wait, binder_stop_on_user_error <2);
  //获得发起 RPC 请求的现场
  thread = binder_get_thread(proc);
  switch(cmd){
  //符合一级通讯 cmd
  case BINDER_WRITE_READ{
    struct binder_write_read bwr;
    //将用户进程的 binder_write_read 拷贝到内核空间
    copy_from_user(&bwr, ubuf, sizeof(bwr))
    //本次请求符合
    if(bwr.write_size >0){
        binder_thread_write(proc, thread, bwr.write_buffer, bwr.write_size, &bwr.write_consumed);
    }
  }
  }
}

int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread, binder_uintptr_t binder_buffer, size_t size, binder_size_t *consumed){
  uint32_t cmd;
  void __user *buffer = (void __user *)(uintptr_t) binder_buffer;
  void __user *ptr = buffer+*consumed;//此时指针子 bwr 中 write_buffer 的 data
  void __user *end = buffer+size
  swicth(cmd){
    //二级通讯 cmd
   case BC_TRANSACTION:
    binder_transaction_data tr;
    //再次拆箱,拆出 binder_transaction_data
    copy_from_user(&tr, ptr, sizeof(tr));
    //真正发起 RPC,这里可以看到,binder 驱动将 BC_TRANSACTION换成了 BC_REPLY
    binder_transaction(proc, thread, &tr, cmd = BC_REPLY);
  }
}

binder_transaction( )函数格外复杂。简而言之是根据请求中目标进程的 handle(此处为 0),多啰嗦一句,所有的 Binder 实体经过 Binder 驱动,都会被记录到一个 binder_node 节点并且插入到 Binder 驱动的 2 颗红黑树(key 不同)。在这里因为 handle 为 0,于是找到对应的 Binder 实体对应的进程,随后创建一个事务binder_transaction,将其挂载到目标进程 traget_list 即 todo 队列。随后唤醒目标进程。

在此处,调用wait_event_interruptible()尝试休眠 AMS 进程是,因为 binder_stop_on_user_error < 2成立,因此不会休眠进程。在进行binder_thread_write()进行 rpc 调用后,在binder_thread_read()会通过wait_event_freezable_exclusive()休眠当前线程,知道 service_manager.cpp 返回请求结果。
而 service_manager.cpp 进入 loop 后,就是一直阻塞在binder_thread_read()中的wait_event_freezable_exclusive()去尝试获取请求。当 binder_has_proc_work()符合条件,即进程所造的 todo 队列有内容,才会唤醒。
当 AMS 将此次 RPC 请求投递到 service_manager.cpp 所在的 todo 队列,service_manager.cpp 就会被唤醒,读取处理请求。同事 AMS 会在wait_event_freezable_exclusive()挂起线程,直到有某个事务(其他进程或者 service_manager.cpp 返回了结果)被投递到 AMS 进程所在的 todo 队列


Binder 的通讯大致过程都相似,如果是同步请求 A 进程像 Binder 发送 RPC,内核休眠 A 进程,唤醒目标 B 进程,处理请求,回复 Binder 驱动,唤醒 A 进程。

上一篇 下一篇

猜你喜欢

热点阅读