Android IPC Binder机制学习(一)

一、多进程系统设计及意义

Android系统分为5层,不过Android一般岗位只关注上三层就够用了即:应用层、framework层、native层。

  1. Android中的应用层和系统服务层不在同一个进程,系统服务在单独的进程中。

  1. Android中不同的应用属于不同的进程中

Android应用和系统服务运行在不同的进程中是为了安全、稳定、及内存管理的原因,但应用和系统服务需要通信和分享数据。

优点

  • 安全性:每个进程都可以单独运行,可以保证应用层对系统层的隔离。

  • 稳定性:如果某个进程崩溃了不会导致其他进程崩溃

  • 内存分配:如果某个进程已经不需要了,可以从能存中移除,并回收相应的内存。

以上优点都是将系统设计成多进程的原因,我们在开发App时,也可以根据需要将App也设计成多进程的,比如以下场景:

虚拟机分配给各个进程的运行内存是有限的,LMK也会优先回收对系统资源占用多的进程。

  • 突破进程内存限制,如图库占用内存过多

  • 功能稳定性:独立的通信进程保持长连接的稳定性(如:微信的消息推送功能跑在独立的进程)

  • 规避系统内存泄漏:独立的webview进程阻隔内存泄漏导致的问题

  • 隔离风险:对于不稳定的功能放入独立的进程,避免导致主进程崩溃

二、Android/Linux都有哪些进程间通信方式?Android为什么主要采用Binder作为进程间的通信方式?

  1. 内存共享

  1. 管道

  1. 消息队列

  1. socket

  1. binder

疑问1:共享内存和内存映射有什么区别?

共享内存可以直接创建,内存映射需要磁盘文件(匿名映射除外)

内存映射用于文件读写:当多个进程映射到同一个文件时,并且设置了MAP_SHARE,此时可以IPC,不过数据会写回磁盘,所以还是共享内存快。

疑问2:为什么binder通信要将数据拷贝到内核空间,再由内核空间和server端做内存映射,而不是client和server直接做内存映射?

答:有两点1是拷贝到内核会对uid和pid等进行身份检测,权限安全,2是有一次拷贝,这就是个单向操作,server端哪怕修改了内存映射中的数据,也不会影响到client端中的数据,保证数据安全。

各种方式对比

三、Binder通信模型(以请求系统服务为例如ActivityManagerService)

  1. Android系统服务在启动后会将自己注册到ServiceManager,ServiceManager维护了一个表来存储各种系统服务的名字和binder(系统服务名和系统服务的binder(可理解为系统服务的句柄)是对应关系)。

  1. 客户度想要请求系统服务时,要向serviceManager中传对应的系统服务名来获取对应的系统服务Binder。

  1. 客户端有了系统服务的binder就可以通过Binder驱动向系统服务发送数据,从而完成了跨进程通信。

  1. 客户端向服务端发送的数据中会携带客户端的binder,这样服务端如果有数据需要返回给客户端,就可以通过客户端的binder来实现。

四、Binder是怎么创建的?

1.要讨论Binder是怎么创建的,需要先清楚Binder是什么?

在Android中我们所使用的Activity,Service等组件都需要和AMS通信,这种跨进程的通信都是通过Binder完成的。

  • 机制:Binder是一种进程间的通信机制

  • 驱动:Binder是一个虚拟物理设备驱动

  • 应用层:Binder是一个能发起通信的Java类

  • Framework/native:Binder连接了Client、Server、ServiceManager和Binder驱动程序,形成一套C/S的通信架构

2.Binder是什么时候创建的呢?

在进程创建的时候,就准备了binder

以Service Manager进程为例:

//文件路径:frameworks\native\cmds\servicemanager\main.cpp
int main(int argc, char** argv) {
    if (argc > 2) {
        LOG(FATAL) << "usage: " << argv[0] << " [binder driver]";
    }

    //此时要使用的binder驱动为 "/dev/binder"
    const char* driver = argc == 2 ? argv[1] : "/dev/binder";
    //初始化binder驱动
    sp<ProcessState> ps = ProcessState::initWithDriver(driver);
    ps->setThreadPoolMaxThreadCount(0);
    ps->setCallRestriction(ProcessState::CallRestriction::FATAL_IF_NOT_ONEWAY);
    //实例化ServiceManager
    sp<ServiceManager> manager = new ServiceManager(std::make_unique<Access>());
    //将自身作为服务添加
    if (!manager->addService("manager", manager, false /*allowIsolated*/, IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk()) {
        LOG(ERROR) << "Could not self register servicemanager";
    }
    //设置服务端Bbinder对象
    IPCThreadState::self()->setTheContextObject(manager);
    //设置称为binder驱动的context manager,称为上下文的管理者
    ps->becomeContextManager(nullptr, nullptr);
    //通过Looper epoll机制处理binder事务
    sp<Looper> looper = Looper::prepare(false /*allowNonCallbacks*/);

    BinderCallback::setupTo(looper);
    ClientCallbackCallback::setupTo(looper, manager);

    while(true) {
        looper->pollAll(-1);
    }

    // should not be reached
    return EXIT_FAILURE;
}

五、Binder的使用

通常我们使用Binder并不是直接使用,因为Binder的使用较为复杂容易出问题,由此Android官方出了一个对Binder的封装框架即AIDL。

可以先看下AIDL的简单使用

通过AIDL文件生成的接口中,内部类Stub提供了服务端提供的服务的实现逻辑,Proxy是Stub的代理类,用于给客户端提供调用服务端Stub的句柄。在使用demo中也能看到AIDL文件在客户端和服务端中都要用到(且内容相同),但在客户端与服务端中使用的部分是不一样的,Proxy是给客户端使用的,Stub是服务端使用的,或者说Stub是服务端所持有的。(注意这个service不是我们自己的service而是AMS)

六、Binder跨进程传递数据的详细流程

上图概括出了从Activity要拿到我们自己service的Binder的过程,要经过8次跨进程通信

这里我们以上图中①处的从App进程到servicemanager进程获取AMS的IBinder的操作为例,来具体分析Binder跨进程通信的过程。其中会涉及servicemanager的启动流程相关的内容,不熟悉的小伙伴可以先看一下。

  1. 客户端发送请求数据到内核中的Binder驱动

//入口代码
Activity中调用startService()

//最终会调用到ContextImpl.java中的
private ComponentName startServiceCommon(Intent service, boolean requireForeground,
            UserHandle user) {
        try {
            validateServiceIntent(service);
            service.prepareToLeaveProcess(this);
            // ActivityManager.getService() 就是本小节分析的重点,跨进程获取AMS的IBinder
            ComponentName cn = ActivityManager.getService().startService(
                    mMainThread.getApplicationThread(), service,
                    service.resolveTypeIfNeeded(getContentResolver()), requireForeground,
                    getOpPackageName(), getAttributionTag(), user.getIdentifier());
        ...
}

// ActivityManager.java
@UnsupportedAppUsage
    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;
                }
            };

//ServiceManager.java

public static IBinder getService(String name) {
        try {
            IBinder service = sCache.get(name);
            if (service != null) {
                return service;
            } else {
                //缓存中到不到,走这里
                return Binder.allowBlocking(rawGetService(name));
            }
        } catch (RemoteException e) {
            Log.e(TAG, "error in getService", e);
        }
        return null;
    }

 // name是一层层传递进来的,ACTIVITY_SERVICE = "activity"
 private static IBinder rawGetService(String name) throws RemoteException {
        final long start = sStatLogger.getTime();
        //这里分为两步
        // step1:getIServiceManager() 拿到servicemanager的IBinder
        // step2:getService(name) 这一步就是跨进程通信了
        final IBinder binder = getIServiceManager().getService(name);
        ...
        return binder;
 }

 //----------------------先看step1:---------------------------
 private static IServiceManager getIServiceManager() {
        //不为空直接返回
        if (sServiceManager != null) {
            return sServiceManager;
        }

        // Find the service manager
        sServiceManager = ServiceManagerNative
                .asInterface( //注解1
                 Binder.allowBlocking(
                     BinderInternal.getContextObject()  //注解2
                     ) 
                 );
        return sServiceManager;
  }

  //先看注解2:    BinderInternal.java
  //是个native方法,由此进入native层源码
  public static final native IBinder getContextObject();

//寻找getContextObject()对应对的native方法,了解过Android系统启动流程的小伙伴知道在启动zygote进程的
//时候(frameworks\base\cmds\app_process\app_main.cpp),有一个非常重要的步骤就是会进行一系列的jni方法注册,
//我们来具体看下
//main方法
int main(int argc, char* const argv[])
{
    ...
     if (zygote) {
        //启动运行时环境
        runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
      }
}

//进入start()      frameworks\base\core\jni\AndroidRuntime.cpp
void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{
    ...
    if (startReg(env) < 0) {  //注册JNI
        ALOGE("Unable to register all android natives\n");
        return;
    }
    ...
} 

int AndroidRuntime::startReg(JNIEnv* env)
{
   
    ...
    // gRegJNI 是定义好的jni方法 相关的结构体数组,系统中所有需要动态加载的jni方法都在这了
    if (register_jni_procs(gRegJNI, NELEM(gRegJNI), env) < 0) {
        env->PopLocalFrame(NULL);
        return -1;
    }
    ...

    return 0;
}

static const RegJNIRec gRegJNI[] = {
   ...
   //这个也有一定的规律,我们要寻找的BinderProxy.transactNative()的包名就是android.os,它是binder相关的jni
   REG_JNI(register_android_os_Binder),  
   ...
}
//   frameworks\base\core\jni\android_util_Binder.cpp  进入register_android_os_Binder这个方法
int register_android_os_Binder(JNIEnv* env)
{
    if (int_register_android_os_Binder(env) < 0)
        return -1;
    if (int_register_android_os_BinderInternal(env) < 0) //在这个方法里注册BinderInternal.java中的native方法
        return -1;
    if (int_register_android_os_BinderProxy(env) < 0) 
        return -1;
    ...
}

//看和java类对应上了吧
const char* const kBinderInternalPathName = "com/android/internal/os/BinderInternal";
static int int_register_android_os_BinderInternal(JNIEnv* env)
{
     ... 
    return RegisterMethodsOrDie(
        env, kBinderInternalPathName,
        gBinderInternalMethods, NELEM(gBinderInternalMethods));
}

//重点在这里,这个数组中写死了java方法与native方法的对应关系,(jni动态注册)
static const JNINativeMethod gBinderInternalMethods[] = {
     /* name, signature, funcPtr */
    //android_os_BinderInternal_getContextObject就是我们要找的native方法
    { "getContextObject", "()Landroid/os/IBinder;", (void*)android_os_BinderInternal_getContextObject },
    { "joinThreadPool", "()V", (void*)android_os_BinderInternal_joinThreadPool },
    { "disableBackgroundScheduling", "(Z)V", (void*)android_os_BinderInternal_disableBackgroundScheduling },
    { "setMaxThreads", "(I)V", (void*)android_os_BinderInternal_setMaxThreads },
    { "handleGc", "()V", (void*)android_os_BinderInternal_handleGc },
    { "nSetBinderProxyCountEnabled", "(Z)V", (void*)android_os_BinderInternal_setBinderProxyCountEnabled },
    { "nGetBinderProxyPerUidCounts", "()Landroid/util/SparseIntArray;", (void*)android_os_BinderInternal_getBinderProxyPerUidCounts },
    { "nGetBinderProxyCount", "(I)I", (void*)android_os_BinderInternal_getBinderProxyCount },
    { "nSetBinderProxyCountWatermarks", "(II)V", (void*)android_os_BinderInternal_setBinderProxyCountWatermarks}
};

static jobject android_os_BinderInternal_getContextObject(JNIEnv* env, jobject clazz)
{
    sp<IBinder> b = ProcessState::self()->getContextObject(NULL);
    //将b转成java中的对象
    return javaObjectForIBinder(env, b);  //注解3
}

//frameworks\native\libs\binder\ProcessState.cpp
sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& /*caller*/)
{
    sp<IBinder> context = getStrongProxyForHandle(0);
    ...
    return context;
}

sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)
{
    ...
    handle_entry* e = lookupHandleLocked(handle);

    if (e != nullptr) {
        IBinder* b = e->binder;
        if (b == nullptr || !e->refs->attemptIncWeak(this)) {
            // //创建BpBinder并保存下来以便后面再次查找
            //ServiceManager 服务比较特殊,其BBinder(服务)保存在IPCThreadState中(the_context_object),对应的handle 是0;
            //ServiceManager的BBinder在每一个进程中的handle值都为0。因此,任何进程和ServiceManager进程的通信便不再需要事先获取它的代理对象,
            //而只需要告诉Binder Driver:我需要和handle值为0的进程通信。Binder Driver便会自动将该进程的通信请求转发到ServiceManager进程。 
            b = BpBinder::create(handle);
            e->binder = b;
            if (b) e->refs = b->getWeakRefs();
            result = b;
     }
   ...
   }
    //最终将servicemanager的BBinder的代理对象BpBinder返回了出去
    return result;
}

//接下来看注解3处的流程,将得到的BpBinder转换成Java层使用的对象
// 将一个BpBinder对象(这是native中的类型)转换成java中的类型
jobject javaObjectForIBinder(JNIEnv* env, const sp<IBinder>& val)
{
     ...
     //通过反射创建java 对应的BpBinder对象(BinderProxy)
     jobject object = env->CallStaticObjectMethod(gBinderProxyOffsets.mClass,
            gBinderProxyOffsets.mGetInstance, (jlong) nativeData, (jlong) val.get());
     ...
}

//gBinderProxyOffsets.mClass就是反射创建对象的类型,它是在下面的方法中被赋值的
const char* const kBinderProxyPathName = "android/os/BinderProxy";

static int int_register_android_os_BinderProxy(JNIEnv* env)
{
    ...
    gBinderProxyOffsets.mClass = MakeGlobalRefOrDie(env, clazz);
    gBinderProxyOffsets.mGetInstance = GetStaticMethodIDOrDie(env, clazz, "getInstance",
            "(JJ)Landroid/os/BinderProxy;");
    gBinderProxyOffsets.mSendDeathNotice =
            GetStaticMethodIDOrDie(env, clazz, "sendDeathNotice",
                                   "(Landroid/os/IBinder$DeathRecipient;Landroid/os/IBinder;)V");
    gBinderProxyOffsets.mNativeData = GetFieldIDOrDie(env, clazz, "mNativeData", "J");
    ...
}


/**回到注解2处,我们知道BinderInternal.getContextObject() = BinderProxy对象
  *实质上是servicemanager进程中创建的BBinder对象
  *                                java层 | native层                     
  *封装关系ServicemanagerProxy->BinderProxy->BpBinder == BBinder
  *此时再来看注释1处,其实就是
  *sServiceManager = ServiceManagerNative.asInterface(BinderProxy对象) //伪代码
 **/
//ServiceManagerNative.java

public static IServiceManager asInterface(IBinder obj) {
        if (obj == null) {
            return null;
        }

        // ServiceManager is never local
        return new ServiceManagerProxy(obj);
}

//java层的servicemanager的IBinder代理类

class ServiceManagerProxy implements IServiceManager {
    public ServiceManagerProxy(IBinder remote) {
        mRemote = remote;  //BinderProxy
        //熟悉AIDL的小伙伴应该知道,IServiceManager这个类就是通过IServiceManager.aidl文件生成的,下面会给出这个文件
        mServiceManager = IServiceManager.Stub.asInterface(remote);
    }

    //注意,后面step2就是走到这个方法
    public IBinder getService(String name) throws RemoteException {
        // Same as checkService (old versions of servicemanager had both methods).
        return mServiceManager.checkService(name);
    }

    private IBinder mRemote;
    private IServiceManager mServiceManager;  //IServiceManager.Stub.Proxy类型
}

//---------------------------step2----------------------------
/**回到step2处,
  *private static IBinder rawGetService(String name) throws RemoteException {
        final long start = sStatLogger.getTime();
        //这里分为两步
        // step1:getIServiceManager() 拿到servicemanager的IBinder
        // step2:getService(name) 这一步就是跨进程通信了
        //由上可知getIServiceManager() = ServiceManagerNative.ServiceManagerProxy对象
        final IBinder binder = getIServiceManager().getService(name);
        ...
        return binder;
    }
**/

//getService(name)会调到ServiceManagerNative.ServiceManagerProxy.getService()
public IBinder getService(String name) throws RemoteException {
        //mServiceManager是IServiceManager.Stub.Proxy类型的对象
        return mServiceManager.checkService(name);
}

//为了方便分析,我们可以使用aidl工具将IserviceManager.aidl的java类生成出来:
//内容较多只截取当前需要的部分代码
public interface IServiceManager extends android.os.IInterface
{
 
  /** Local-side IPC implementation stub class. */
  public static abstract class Stub extends android.os.Binder implements android.os.IServiceManager
  {
    private static final java.lang.String DESCRIPTOR = "android.os.IServiceManager";
    /** Construct the stub at attach it to the interface. */
    public Stub()
    {
      this.attachInterface(this, DESCRIPTOR);
    }
    /**
     * Cast an IBinder object into an android.os.IServiceManager interface,
     * generating a proxy if needed.
     */
    public static android.os.IServiceManager asInterface(android.os.IBinder obj)
    {
      if ((obj==null)) {
        return null;
      }
      android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
      if (((iin!=null)&&(iin instanceof android.os.IServiceManager))) {
        return ((android.os.IServiceManager)iin);
      }
      return new android.os.IServiceManager.Stub.Proxy(obj);
    }
    @Override public android.os.IBinder asBinder()
    {
      return this;
    }
    
    private static class Proxy implements android.os.IServiceManager
    {
      private android.os.IBinder mRemote; //BinderProxy
      Proxy(android.os.IBinder remote)
      {
        mRemote = remote;
      }
      @Override public android.os.IBinder asBinder()
      {
        return mRemote;
      }
      public java.lang.String getInterfaceDescriptor()
      {
        return DESCRIPTOR;
      }
      
      
      @Override public android.os.IBinder checkService(java.lang.String name) throws android.os.RemoteException
      {
        android.os.Parcel _data = android.os.Parcel.obtain();
        android.os.Parcel _reply = android.os.Parcel.obtain();
        android.os.IBinder _result;
        try {
          _data.writeInterfaceToken(DESCRIPTOR);
          _data.writeString(name);
          //_data中写入了我们传的那么参数,mRemote的类型是BinderProxy,TRANSACTION_checkService代表当前要跨进程执行的是checkService()这个函数        
          boolean _status = mRemote.transact(Stub.TRANSACTION_checkService, _data, _reply, 0);
          if (!_status && getDefaultImpl() != null) {
            return getDefaultImpl().checkService(name);
          }
          _reply.readException();
          _result = _reply.readStrongBinder();
        }
        finally {
          _reply.recycle();
          _data.recycle();
        }
        return _result;
      }
      
      public static android.os.IServiceManager sDefaultImpl;
    }
    static final int TRANSACTION_getService = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
    static final int TRANSACTION_checkService = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
   
}

//来到BinderProxy类的transact()
public boolean transact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
       ...
        try {
            //主线流程来到transactNative(),他是一个native方法,
            final boolean result = transactNative(code, data, reply, flags);

            if (reply != null && !warnOnBlocking) {
                reply.addFlags(Parcel.FLAG_IS_REPLY_FROM_BLOCKING_ALLOWED_OBJECT);
            }

            return result;
        } 
        ...
 }

//由此将从java层调用到native层
public native boolean transactNative(int code, Parcel data, Parcel reply,
            int flags) throws RemoteException;


//4.寻找transactNative()对应对的native方法,了解过Android系统启动流程的小伙伴知道在启动zygote进程的
//时候(frameworks\base\cmds\app_process\app_main.cpp),有一个非常重要的步骤就是会进行一系列的jni方法注册,
//我们来具体看下:
//main方法
int main(int argc, char* const argv[])
{
    ...
     if (zygote) {
        //启动运行时环境
        runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
      }
}

//进入start()      frameworks\base\core\jni\AndroidRuntime.cpp
void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{
    ...
    if (startReg(env) < 0) {  //注册JNI
        ALOGE("Unable to register all android natives\n");
        return;
    }
    ...
} 

int AndroidRuntime::startReg(JNIEnv* env)
{ 
    ...
    // gRegJNI 是定义好的jni方法 相关的结构体数组,系统中所有需要动态加载的jni方法都在这了
    if (register_jni_procs(gRegJNI, NELEM(gRegJNI), env) < 0) {
        env->PopLocalFrame(NULL);
        return -1;
    }
    ...

    return 0;
}

static const RegJNIRec gRegJNI[] = {
   ...
   //这个也有一定的规律,我们要寻找的BinderProxy.transactNative()的包名就是android.os,它是binder相关的jni
   REG_JNI(register_android_os_Binder),  
   ...
}
//   frameworks\base\core\jni\android_util_Binder.cpp  进入register_android_os_Binder这个方法
int register_android_os_Binder(JNIEnv* env)
{
    if (int_register_android_os_Binder(env) < 0)
        return -1;
    if (int_register_android_os_BinderInternal(env) < 0)
        return -1;
    if (int_register_android_os_BinderProxy(env) < 0) //android.os.BinderProxy中的jni方法
        return -1;
    ...
}

static int int_register_android_os_BinderProxy(JNIEnv* env)
{
    //通过反射技术进行动态注册
    ...
    return RegisterMethodsOrDie(
        env, kBinderProxyPathName,
        gBinderProxyMethods, NELEM(gBinderProxyMethods));
}

//JNINativeMethod这个结构体封装了java方法与native方法的对应关系,及方法签名
static const JNINativeMethod gBinderProxyMethods[] = {
     /* name, signature, funcPtr */
    {"pingBinder",          "()Z", (void*)android_os_BinderProxy_pingBinder},
    {"isBinderAlive",       "()Z", (void*)android_os_BinderProxy_isBinderAlive},
    {"getInterfaceDescriptor", "()Ljava/lang/String;", (void*)android_os_BinderProxy_getInterfaceDescriptor},
    {"transactNative",      "(ILandroid/os/Parcel;Landroid/os/Parcel;I)Z", (void*)android_os_BinderProxy_transact},
    {"linkToDeath",         "(Landroid/os/IBinder$DeathRecipient;I)V", (void*)android_os_BinderProxy_linkToDeath},
    {"unlinkToDeath",       "(Landroid/os/IBinder$DeathRecipient;I)Z", (void*)android_os_BinderProxy_unlinkToDeath},
    {"getNativeFinalizer",  "()J", (void*)android_os_BinderProxy_getNativeFinalizer},
    {"getExtension",        "()Landroid/os/IBinder;", (void*)android_os_BinderProxy_getExtension},
};

//android_os_BinderProxy_transact就是我们要寻找的目标,当java层调用BinderProxy的transactNative(),就会调到这个native方法:
static jboolean android_os_BinderProxy_transact(JNIEnv* env, jobject obj,
        jint code, jobject dataObj, jobject replyObj, jint flags) // throws RemoteException
{
   ...
   //这里就是将java层的BinderProxy对象转换为native层的BpBinder对象
    IBinder* target = getBPNativeData(env, obj)->mObject.get();
   ...
   //调用BpBinder的transact()
   status_t err = target->transact(code, *data, reply, flags);
}

//进入transact()    frameworks\native\libs\binder\BpBinder.cpp
status_t BpBinder::transact(
    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
    ...
    status_t status = IPCThreadState::self()->transact(
            mHandle, code, data, reply, flags);
    ...
}

//进入transact()  frameworks\native\libs\binder\IPCThreadState.cpp
status_t IPCThreadState::transact(int32_t handle,
                                  uint32_t code, const Parcel& data,
                                  Parcel* reply, uint32_t flags)
{
   ...
   if (reply) { 
            err = waitForResponse(reply); //即我们跨进程执行的函数时有返回值的
        } else {
            Parcel fakeReply;
            err = waitForResponse(&fakeReply);
        }
} 

status_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult)
{
    ...
    while(1){
        //读写binder驱动
        if ((err=talkWithDriver()) < NO_ERROR) break;
    }
}

status_t IPCThreadState::talkWithDriver(bool doReceive)
{
    ...
    //这里的ioctl就是系统操作了,这里完成的操作就是将用户空间的数据写到内核空间中的binder驱动中
    ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr);
    ...
}
  1. 将binder驱动中的数据发送到服务端

在servicemanager进程启动流程中提到,在servicemanager启动后,注册了回调方法来监听binder驱动中是否有数据写入,并开启Looper等待处理客户端发送(写入)的数据,在上一节中已经将数据写到驱动中,接下来进入监听函数:

//文件路径 frameworks\native\cmds\servicemanager\main.cpp     
class BinderCallback : public LooperCallback {
public:

    // 当binder驱动发来消息后,就可以通过次函数接收处理了
    int handleEvent(int /* fd */, int /* events */, void* /* data */) override {
        //处理消息
        IPCThreadState::self()->handlePolledCommands();
        return 1;  // Continue receiving callbacks.
    }
};

继续来看收到消息后的具体处理:

// frameworks\native\libs\binder\IPCThreadState.cpp
status_t IPCThreadState::handlePolledCommands()
{
    status_t result;
    // 当读缓存中数据未消费完时,持续循环
    do {
        result = getAndExecuteCommand();
    } while (mIn.dataPosition() < mIn.dataSize());

    // 当我们清空执行完所有的命令后,最后处理BR_DECREFS和BR_RELEASE
    processPendingDerefs();
    flushCommands();
    return result;
}

继续跟进:

status_t IPCThreadState::getAndExecuteCommand()
{
    status_t result;
    int32_t cmd;
    // 从binder驱动中读写数据并写入mIn(理论来说此时写缓存dataSize为0,也就是只读数据)
    result = talkWithDriver();
    ...
    cmd = mIn.readInt32();
    //执行读到的命令
    result = executeCommand(cmd);
    ...
}

executeCommand()主要任务就是根据binder驱动中读出的命令去执行对应的操作:

status_t IPCThreadState::executeCommand(int32_t cmd)
{
   switch ((uint32_t)cmd) {
      ...
      //以本案例,是处理这个命令
      case BR_TRANSACTION:
        {
            ...
            Parcel buffer;
            //读取数据到缓冲区
            //实例化了一个Parcel对象作为缓冲区,从binder_transaction_data中将实际数据读取出来
            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);
            Parcel reply;
           
            //对于ServiceManager的binder节点来说,是没有ptr的
            if (tr.target.ptr) {
                // We only have a weak reference on the target object, so we must first try to
                // safely acquire a strong reference before doing anything else with it.
                // 对于其他binder服务端来说,tr.cookie为本地BBinder对象指针
                if (reinterpret_cast<RefBase::weakref_type*>(
                        tr.target.ptr)->attemptIncStrong(this)) {
                    error = reinterpret_cast<BBinder*>(tr.cookie)->transact(tr.code, buffer,
                            &reply, tr.flags);
                    reinterpret_cast<BBinder*>(tr.cookie)->decStrong(this);
                } else {
                    error = UNKNOWN_TRANSACTION;
                }

            } else { //对于serviceManager来说the_context_object就是BBinder对象,
                     //在main()中创建了ServiceManager对象并赋值给了the_context_object
                error = the_context_object->transact(tr.code, buffer, &reply, tr.flags);
            }
            ...
        }
        break;
 
   }


}

但我们在ServiceManager中并没有找到transact()方法,它定义在ServiceManager的父类BnServiceManager的父类Binder(Binder.cppframeworks\native\libs\binder\Binder.cpp)中:

status_t BBinder::transact(
    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
    data.setDataPosition(0);

    status_t err = NO_ERROR;
    switch (code) {
        ...
        //进到这里
        default:
            err = onTransact(code, data, reply, flags);
            break;
    }
    ...
    return err;
}

而在它的子类中重写了onTransact(),来到BnServiceManager,但这个类不在AOSP中,而是通过

(frameworks\native\libs\binder\aidl\android\os\IserviceManager.aidl)生成的:

::android::status_t BnServiceManager::onTransact(uint32_t _aidl_code, const ::android::Parcel& _aidl_data, ::android::Parcel* _aidl_reply, uint32_t _aidl_flags) {
  ::android::status_t _aidl_ret_status = ::android::OK;
  switch (_aidl_code) {
      case ::android::IBinder::FIRST_CALL_TRANSACTION + 1 /* checkService */:
  {
    ...
    // 这里调用的是子类(即实现类 ServceManager)的checkService(0
    ::android::binder::Status _aidl_status(checkService(in_name, &_aidl_return));
    ...
  }
  break;
  }
}

来到frameworks\native\cmds\servicemanager\ServiceManager.cpp

Status ServiceManager::getService(const std::string& name, sp<IBinder>* outBinder) {
    *outBinder = tryGetService(name, true);
    // returns ok regardless of result for legacy reasons
    return Status::ok();
}

sp<IBinder> ServiceManager::tryGetService(const std::string& name, bool startIfNotFound) {
    auto ctx = mAccess->getCallingContext();

    sp<IBinder> out;
    Service* service = nullptr;
    //在android系统初始化的时候,所有的系统服务启动后都会以键值对的方式注册(保存)到ServiceManager中的mNameToService集合中
    //这里的name是我们从java层传递下来的Context.ACTIVITY_SERVICE = “activity”,他对应的是ActivityManagerService的Binder对象
    if (auto it = mNameToService.find(name); it != mNameToService.end()) {
        service = &(it->second);

        if (!service->allowIsolated) {
            uid_t appid = multiuser_get_app_id(ctx.uid);
            bool isIsolated = appid >= AID_ISOLATED_START && appid <= AID_ISOLATED_END;

            if (isIsolated) {
                return nullptr;
            }
        }
        out = service->binder;
    }

    if (!mAccess->canFind(ctx, name)) {
        return nullptr;
    }

    if (!out && startIfNotFound) {
        tryStartService(name);
    }

    if (out) {
        // Setting this guarantee each time we hand out a binder ensures that the client-checking
        // loop knows about the event even if the client immediately drops the service
        service->guaranteeClient = true;
    }

    return out;
}

到此将AMS的Binder对象返回给了客户端,有了AMS的Binder对象就可以使用AMS提供的服务(功能)了。

下图画出了跨进程通信中每层的关键流程。

七、AIDL文件生成c++文件

#aidl程序  设置生成的语言  aidl文件路径 aidl文件        输出路径   头文件输出路径
#sdk/build-tools
aidl.exe  --lang=cpp -I E:\src E:\src\test.aidl -o E:\dst --head_out E:\dst

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/6969.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

ChatGPT遭禁用、抵制后又停止Plus付费发生了?

ChatGPT相关信息 2023年2月27日消息&#xff0c;Snapchat 正在推出一个基于 OpenAI 的 ChatGPT 最新版本的聊天机器人。 这款名为“My AI”的机器人将被固定在应用界面的聊天选项卡上&#xff0c;虽然最初仅适用于每月3.99美元的SnapchatPlus付费订阅用户&#xff0c;但最终目…

图像分类综述

一、图像分类介绍 什么是图像分类&#xff0c;核心是从给定的分类集合中给图像分配一个标签的任务。实际上&#xff0c;这意味着我们的任务是分析一个输入图像并返回一个将图像分类的标签。标签来自预定义的可能类别集。 示例&#xff1a;我们假定一个可能的类别集categories …

Vue3+vite2 博客前端开发

Vue3vite2 博客前端开发 文章目录Vue3vite2 博客前端开发前言页面展示代码设计卡片设计背景&#xff08;Particles.js粒子效果&#xff09;右侧个人信息与公告内容页友链总结前言 大家是否也想拥有一个属于自己的博客&#xff1f;但是如何去开发博客&#xff0c;怎样去开发一个…

毫升 | 主成分分析(PCA)

这种方法是由Karl Pearson 介绍的。它的工作条件是&#xff0c;当高维空间中的数据映射到低维空间中的数据时&#xff0c;低维空间中数据的方差应最大。 主成分分析 (PCA) 是一种用于降低大型数据集维数的统计技术。它是机器学习、数据科学和其他处理大型数据集的领域中常用的…

如何通过C++ 将数据写入 Excel 工作表

直观的界面、出色的计算功能和图表工具&#xff0c;使Excel成为了最流行的个人计算机数据处理软件。在独立的数据包含的信息量太少&#xff0c;而过多的数据又难以理清头绪时&#xff0c;制作成表格是数据管理的最有效手段之一。这样不仅可以方便整理数据&#xff0c;还可以方便…

aspnet030高校学生团体管理系统sqlserver

net030高校学生团体管理系统 . 1.用户基本信息管理模块&#xff1a;录入、修改、删除、查询、统计、打印等功能 2.学生成绩管理模块&#xff1a;录入、修改、删除、查询、统计、打印等功能 3.学生团体信息管理模块&#xff1a;录入、修改、删除、查询、统计、打印等功能 4.教…

Excel技能之查找筛选排序,同事竖起大拇指

每天面对大量的数据&#xff0c;眼睛都看花了。头疼、脱发、颈椎病、胸闷、腰间盘突出&#xff0c;一系列并发症严重影响打工人的心情。同事看在眼里&#xff0c;痛在心里。 救救打工人吧&#xff01;打工人的福音来了&#xff0c;自从学会了查找筛选排序&#xff0c;手脚利索…

动态规划(一) part1

T1:一个数组 中的最长 升序 子序列 的长度 给你一个整数数组 nums &#xff0c;找到其中最长严格递增子序列的长度。 子序列 是由数组派生而来的序列&#xff0c;删除&#xff08;或不删除&#xff09;数组中的元素而不改变其余元素的顺序。例如&#xff0c;[3,6,2,7] 是数组…

C 非线性结构——树 万字详解(通俗易懂)

目录 一、树的介绍 1.定义 : 2.相关概念 : 3.简单分类 : 4.相关应用 : 二、树的存储 1.二叉树的存储 : 1 二叉树连续存储 2 二叉树链式存储&#xff08;常用&#xff09; 2.普通树和森林的存储 : 1 普通树的存储 2 森林的存储 三、树的遍历 1.二叉树先序遍历 : 2.二叉…

深度学习训练营之yolov5训练自己的数据集

深度学习训练营之训练自己的数据集原文链接环境介绍准备好数据集划分数据集运行voc_train.py遇到问题完整代码创建new_data.yaml文件模型训练时遇到的报错模型训练结果可视化参考链接原文链接 &#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f…

正则表达式

一、正则表达式的概述 1、概念 正则表达式通常被用来检索、替换那些符合某个模式(规则)的文本。 正则表达式是对字符串&#xff08;包括普通字符&#xff08;例如&#xff0c;a 到 z 之间的字母&#xff09;和特殊字符&#xff08;称为“元字符”&#xff09;&#xff09;操…

JVM 程序计数器(PC)

PC寄存器的概念 JVM中的程序计数寄存器&#xff08;Program Counter Register&#xff09;中&#xff0c;Register的命名源于CPU的寄存器&#xff0c;寄存器存储指令相关的现场信息。CPU只有把数据装载到寄存器才能够运行。这里&#xff0c;并非是广义上所指的物理寄存器&#…

【蓝桥杯冲刺】日期类专题特训

目录 1. 日期累加 题目描述 输入 输出 代码 2. 日期差值 题目描述 输入 输出 代码 3. 打印日期 题目描述 输入 输出 代码 写在最后&#xff1a; 1. 日期累加 题目链接&#xff1a;日期累加 题目描述 输入 1 2008 2 3 100 输出 2008-05-13 代码 #include…

如何在 Linux 中查找所有符号链接,这几个命令得会!

在Linux中&#xff0c;符号链接&#xff08;Symbolic Link&#xff09;是一种非常常见的文件类型&#xff0c;也称为软链接。符号链接是指向另一个文件的指针&#xff0c;而不是实际的数据。它允许用户创建一个指向另一个文件的虚拟文件&#xff0c;这样用户可以在不改变实际文…

JVM解析原理

目录1.JVM内存结构2.JIT及时编译器的原理&#xff0c;优化以及切换编译器类型2.1解释型语言和编译语言2.2JIT即时编译器&#xff08;Just In Time Compiler&#xff09;3.类的加载机制和类的加载器3.1类的加载机制3.2类的加载器4.双亲委派机制4.1定义4.2优点4.3总结5.虚拟机栈详…

读破万卷,神交古人,突破ChatGPT4096的Token限制,建立自己的垂直领域资料人工智能助理

ChatGPT的泛用性极高&#xff0c;上知天文&#xff0c;下通地理&#xff0c;参考古今&#xff0c;博稽中外&#xff0c;几乎无所不知&#xff0c;无所不晓。但如果涉及垂直领域的专业知识点&#xff0c;ChatGPT难免也会有语焉不详&#xff0c;闪烁其词的毛病&#xff0c;本次我…

16从零开始学Java之Java里的输入与输出语句有哪些?

作者&#xff1a;孙玉昌&#xff0c;昵称【一一哥】&#xff0c;另外【壹壹哥】也是我哦 CSDN博客专家、万粉博主、阿里云专家博主、掘金优质作者 前言 我们在前面的文章中&#xff0c;学习了如何创建Java文件&#xff0c;也学习了Java里的标识符、运算符、进制等内容。有些…

iPhone手机小技巧:使用备忘录创建清单

手机备忘录是非常常用的软件之一&#xff0c;无论是iPhone手机还是安卓系统的手机都可以下载相应的APP进行使用。它可以帮助我们记录很多琐碎的事情&#xff0c;防止我们遗忘某事。 在记备忘录的时候&#xff0c;有的人是直接打字记录的&#xff0c;也没有什么具体的格式&…

Excel–如何区分大小写、精确匹配查找?

最近经常需要用到uuid来匹配数据&#xff0c;经常会遇到两个uuid 只是大小写的区别&#xff0c;数据库里使用是没问题的&#xff0c;因为mysql是可以区分大小写的&#xff0c;但是导出后通过excel处理数据匹配数据时就会出问题 如下图所示&#xff0c;通过vlookup匹配&#xf…

文心一言 VS chatgpt (3)-- 算法导论2.1

一、以图 2-2 为模型&#xff0c;说明INSERTION-SORT 在数组 A(31&#xff0c;41&#xff0c;59&#xff0c;26&#xff0c;41&#xff0c;58)上的执行过程。 文心一言&#xff1a; 以图 2-2 为模型&#xff0c;说明INSERTION-SORT 在数组 A(31&#xff0c;41&#xff0c;59&…