首页 > 编程语言 >Android Binder——Java层介绍(三)

Android Binder——Java层介绍(三)

时间:2024-04-01 13:29:35浏览次数:21  
标签:IServiceManager Java Stub Binder reply Android data 服务端 客户端

一、简介

        对于 Android 系统,一般是从 java 层到 native 层,再到 kernel 驱动层,形成一个完整的软件架构。Android 系统中的 Binder IPC 通信机制的整体架构也是如此,Java 和 C++ 层都定义有同样功能的供应用程序使用的 Binder 接口。然而 Java 层中 Framework 层的 ServiceManager 类与 Native 层的功能并不完全对应,Framework 层的 ServiceManager 类的实现最终是通过 BinderProxy 传递给 Native 层来完成的。

ServiceManager:通过 getIServiceManager 方法获取的是 ServiceManagerProxy 对象,ServiceManager 的 addService 和 getService 实际工作都交由 ServiceManagerProxy的相应方法来处理。
ServiceManagerProxy:其成员变量 mRemote 指向 BinderProxy 对象,ServiceManagerProxy 的 addService 和 getService 方法最终是交由 mRemote 来完成。
ServiceManagerNative:其方法 asInterface() 返回的是 ServiceManagerProxy 对象,ServiceManager 便是借助 ServiceManagerNative 类来找到 ServiceManagerProxy。
Binder:其成员变量 mObject 和方法 execTransact() 用于 native 方法。
BinderInternal:内部有一个 GcWatcher 类,用于处理和调试与 Binder 相关的垃圾回收。
IBinder:接口中常量 FLAG_ONEWAY,客户端利用 Binder 跟服务端通信是阻塞式的,但如果设置了 FLAG_ONEWAY,这成为非阻塞的调用方式,客户端能立即返回,服务端采用回调方式来通知客户端完成情况。另外 IBinder 接口有一个内部接口 DeathDecipient(死亡通告)。

1、Stub与Proxy机制

        在 Android 系统中,Binder 机制通过 Stub 和 Proxy 来实现跨进程通信(IPC)。Stub 和 Proxy 是 Binder IPC 的核心组件,它们分别代表服务端和客户端的接口。这种机制允许客户端远程调用服务端的方法,而无需知道底层的通信细节。

Stub(服务端)

        Stub 是服务端的一个本地对象,它实现了服务端暴露给客户端的接口。当客户端想要调用服务端的方法时,它实际上是调用了 Stub 对象上的方法。Stub 对象内部会处理通信的细节,包括将方法调用转换为跨进程通信的请求,并将其发送到客户端进程。

        Stub 通常是通过 aidl(Android Interface Definition Language)文件生成的。aidl文件定义了服务端暴露给客户端的接口,包括方法签名和参数类型等信息。编译 aidl 文件时,Android SDK 会生成相应的 Stub 类,这个类包含了服务端需要实现的方法。

Proxy(客户端)

        Proxy 是客户端的一个本地对象,它代表了服务端对象。客户端通过Proxy来调用服务端的方法,而 Proxy 会将方法调用转换为跨进程通信的请求,并将其发送到服务端进程。

        当客户端调用 Proxy 对象上的方法时,Binder 驱动会捕获这个调用,并将其转换为一个跨进程通信的请求。这个请求会被发送到服务端进程,由服务端的 Stub 对象接收并处理。处理完成后,服务端将结果发送回客户端进程,客户端通过 Proxy 对象接收并处理这个结果。

        Proxy 也是通过 aidl 文件生成的。编译 aidl 文件时,Android SDK 会生成相应的 Proxy 类,这个类包含了客户端用来调用服务端方法的接口。

工作流程

  • 服务端注册服务:服务端创建一个实现了特定接口的 Stub 对象,并将其注册到 Binder驱动程序中,使其可以被其他进程访问。
  • 客户端获取代理:客户端通过 bindService() 方法或其他方式获取服务端 Stub 对象的 Proxy。
  • 客户端调用方法:客户端通过 Proxy 对象调用服务端的方法。这个调用实际上被转换为跨进程通信的请求,并被发送到服务端进程。
  • 服务端处理请求:服务端的 Stub 对象接收到请求后,会将其分发到相应的线程进行处理。处理完成后,服务端将结果发送回客户端进程。
  • 客户端接收结果:客户端通过 Proxy 对象接收并处理服务端返回的结果。

        通过这种方式,Stub 和 Proxy 机制实现了客户端和服务端之间的透明通信,使得客户端可以像调用本地方法一样调用服务端的方法。

2、ServiceManager

        ServiceManager 是 Binder 机制的大管家,管理着 android 系统的各种 Service。Service 向 ServiceManager 注册,当 Client 需要调用 Service 时,先通过 ServiceManager 查询到该 Service,Client 接着再与 Service 通信。这些 Service 有 Java 层也有 Native 层的。Native 层通过 BpServiceManager/BnServiceManager 实现的 Service 与 ServiceManager 的交互。

3、Client和Service通信机制

        Binder 通信的实现同 Native 层类似,Java 层 AIDL 脚本依据 IServiceManager.aidl 生成 IServiceManager 接口类,包含子类 IServiceManager.Stub 和 IServiceManager.Stub.Proxy,两者都实现了 IServiceManager 接口,前者代表 Server 端,后者代表 Client 端。

public interface IServiceManager extends android.os.IInterface {
    public static abstract class Stub extends android.os.Binder implements android.os.IServiceManager {
        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 IServiceManager){
                return (IServiceManager)iin;
            }
            return new IServiceManager.Stub.Proxy(obj);
        }
           
        public boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException
        {
            String descriptor = DESCRIPTOR;
            ……
            switch (code){
                case TRANSACTION_getService: {
                    String _arg0;
                    _arg0 = data.readString();
                    data.enforceNoDataAvail();
                    IBinder _result = getService(_agr0);
                    reply.writeNoException();
                    reply.writeStrongBinder(_result);
                    break;
                }
                ……
            }
        }
    }
        
    private static class Proxy implements IServiceManager {
        private IBinder mRemote;
        Proxy(IBinder remote) {
            mRemote = remote;
        }
            
        @Override
        public IBinder getService(String name) throws RemoteException {
            Parcel _data = Parcel.obtain();
            Parcel _reply = Parcel.obtain();
            IBinder _result;
            try {
                _data.writeInterfaceToken(DESCRIPTOR);
                _data.writeString(name);
                boolean _status = mRemote.transact(Stub.TRANSACTION_getService, _data, _reply, 0);
                _reply.readException();
                _result = _reply.readStrongBinder();
             } finally {
                _reply.recycle();
                _data.recycle();
            }
            return _result;
        }
            
        @Override
        public IBinder checkService(String name) throws RemoteException {
            Parcel _data = Parcel.obtain();
            Parcel _reply = Parcel.obtain();
            IBinder _result;
            try {
                _data.writeInterfaceToken(DESCRIPTOR);
                _data.writeString(name);
                boolean _status = mRemote.transact(Stub.TRANSACTION_checkService, _data, _reply, 0);
                _reply.readException();
                _result = _reply.readStrongBinder();
            } finally {
                _reply.recycle();
                _data.recycle();
            }
            return _result;
        }
    }
}

ServiceManager

源码位置:/frameworks/base/core/java/android/os/ServiceManager.java

        Java 层使用 ServiceManager 类实现 servicemanager 的 Client 端,通过getIServiceManager() 获取 servicemanager 的代理类,其中 BinderInternal.getContextObject() 通过 JNI 创建一个 BinderProxy 对象。

        这里 BinderProxy 本来就是 Java 类,通过 JNI 创建目的是创建 BinderPrxoy 对象的同时,也创建一个 BpBinder 对象,BinderProxy 和 BpBinder 是一一对应的关系。同理,创建 Java 层 Binder 对象时,也会通过 Jni 创建一个 BBinder 对象。我们可以理解为 BinderProxy/Binder 封装了 BpBinder/BBinder,实际工作的是后者。

public final class ServiceManager {
    private static IServiceManager sServiceManager;
    
    private static IServiceManager getIServiceManager(){
        if (sServiceManager != null){
            return sServiceManager;
        }
        // 找到服务管理器
        sServiceManager = ServiceManagerNative.asInterface(Binder.allowBlocing(BinderInternal.getContextObject()));
        return sServiceManager;
    }
    
    // 返回对具有给定名称的服务的引用
    public static IBinder getService(String name){
        try {
            IBinder service = sCache.get(name);
            if (service != null){
                return service;
            } else {
                return Binder.allowBlocking(rawGetServices(name));
            }
        } catch (RemoteException e){
            Log.e(TAG, "error in getService", e);
        }
        return null;
    }
    
    private static IBinder rawGetService(String name) throws RemoteException  {
        final IBinder binder = getIServiceManager().getService(name);
        ……
        return binder;
    }
}

        这里,获取到的 servicemanager 的代理类 IServiceManagerProxy(BinderProxy)。

ServiceManagerNative

源码位置:/frameworks/base/core/java/android/os/ServiceManagerNative.java

public final class ServiceManagerNative {
    private ServiceManagerNative(){}
    
    public static IServiceManager asInterface(IBinder obj){
        if (obj == null){
            return null;
        }
        // ServiceManager永远不是本地的
        return new ServiceManagerProxy(obj);
    }
    
    // 当mRemote不再被使用时,该类应该被删除并替换为IServiceManager.Stub
    class ServiceManagerProxy implements IServiceManager {
        public ServiceManagerProxy(IBinder remote){
            mRemote = remote;
            // servicemanager实际的代理类
            mServiceManager = IServiceManager.Stub.asInterface(remote);
        }
        
        public IBinder getService(String name) throws RemoteException {
            // 与checkService相同(旧版本的servicemanager有这两种方法)。
            return mServiceManager.checkService(name);
        }
        ……
        // 和mServiceManager一样,但被应用使用。
        // 一旦这个可以删除,ServiceManagerProxy应该被完全删除
        private IBinder mRemote;
        private IServiceManager mServiceManager;
    }
}

        这样,我们使用 ServiceManager.addService()/getService() 等方法时,会走到 BinderProxy的 transact() -> transactNative()。

BinderProxy

源码位置:/frameworks/base/core/java/android/os/BinderProxy.java

public boolean transact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
    ……
    try {
        return transactNative(code, data, reply, flags);
    } finally {
        ……
    }
}

public native boolean transactNative(int code, Parcel data, Parecl reply, int flags) throws RemoteException;

        最终通过 Jni 进入 Native 层,通过 BpBinder.transact() -> IPCThreadState.transact() -> writeTransactionData() -> waitForResponse() 进入 binder 驱动层,与 servicemanager 进程通信,等待返回结果。

        这里的 servicemanager 的服务端,使用的是 Native 层的 BnServiceManager,并没有使用到Java 层的 IServiceManager.Stub。servicemanager 接收到请求后,执行相应的操作IPCThreadState::executeCommand() -> BBinder::transact() -> BnServiceManager::onTransact(),具体的实现方法在 ServiceManager.cpp 中,这里不详细开展了。

::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 BnServiceManager::TRANSACTION_getService:
        ::std::string in_name;
        ::android::sp<::android::IBinder> _aidl_return;
        ...
        _aidl_ret_status = _aidl_data.readUtf8FromUtf16(&in_name);
        ...
        ::android::binder::Status _aidl_status(getService(in_name, &_aidl_return));
        ...
        _aidl_ret_status = _aidl_reply->writeStrongBinder(_aidl_return);
        break;
     case BnServiceManager::TRANSACTION_checkService:
     ...
    }
}

        数据组装完毕后,回到 IPCThreadState::executeCommand(),执行 sendReply()。

IPCThreadState.cpp 

源码位置:/system/libhwbinder/IPCThreadState.cpp

sendReply
status_t IPCThreadState::sendReply(const Parcel& reply, uint32_t flags){
    status_t err;
    status_t statusBuffer;
    err = writeTransactionData(BC_REPLY, flags, -1, 0, reply, &statusBuffer);
    if (err < NO_ERROR) return err;
    
    return waitForResponse(nullptr, nullptr);
}

        通过 Binder 驱动,将请求的结果返回给 Client 端,如下所示,返回的结果写入了 Parcel 中。

waitForResponse
status_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult){
    ……
    while(1){
        if ((err=talkWithDriver()) < NO_ERROR) break;
        ……
        cmd = (uint32_t)mIn.readInt32();
        switch(cmd){
        ……
        case BR_REPLY:
            binder_transaction_data tr;
            err = mIn.read(&tr, sizeof(tr));
            ……
            if(reply){
                if((tr.flags & TF_STATUS_CODE) == 0){
                    reply->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);
                } else {
                    ……
                }
            }else{
                ……
            }
            goto finish;
        }
    }
  finish:
      if (err != NO_ERROR){
          ……
      }
      return err;
}

        接着进入 IServiceManager.Stub.Proxy 类的方法中,通过 Parcel.readStrongBinder() 获取到与 servicemanager 通信的结果。

        总结:servicemanager 在管理 Java 层 Service 时,目前只使用了 IServiceManager.Stub.Proxy 作为代理类,并没有使用 IServiceManager.Stub 作为服务类,服务类使用的依然是 Native 层 BnServiceManager。

标签:IServiceManager,Java,Stub,Binder,reply,Android,data,服务端,客户端
From: https://blog.csdn.net/c19344881x/article/details/137217931

相关文章

  • Android+Fragment与Activity之间的信息传递——笔记3
    通过Bundle,Fragment与Activity之间的信息传递protectedvoidonCreate(BundlesavedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);btn2=findViewById(R.id.btn2);btn3=findViewById(R.......
  • Java从萌新小白到顶级大牛(4更新中)
    自定义异常Java标准库定义的常用异常包括:Exception│├─RuntimeException│ ││ ├─NullPointerException│ ││ ├─IndexOutOfBoundsException│ ││ ├─SecurityException│ ││ └─IllegalArgumentException│    ││ ......
  • JavaWeb学习笔记——第十一天
    SpringBootWeb案例(二)新增员工实现EmpController:@PostMappingpublicResultadd(@RequestBodyEmpemp){log.info("新增员工:{}",emp);empService.add(emp);returnResult.success();}EmpService:voidadd(Empemp);EmpServiceImpl:@Overri......
  • Android-Frida环境部署
    前言什么是Android逆向开发?Android逆向开发是指对已发布的Android应用进行分析和破解,以了解应用程序的内部工作原理,获取应用程序的敏感信息,或者修改应用程序的行为。逆向开发可以帮助开发人员了解他人的代码目录安装ADB安装python和Friday模拟器安装Friday-server......
  • 系统学习Java:构建坚实的编程基础
    Java是一种广泛使用的编程语言,以其跨平台性、强大的生态系统和稳健的性能而受到开发者的青睐。无论你是编程新手还是希望转战Java的经验丰富的开发者,系统学习Java都需要一个明确的学习路径。本文将为你提供一个全面的指南,帮助你从多个关键方面入手,构建坚实的Java编程基础。......
  • java中展开树集合
    /***java中展开树集合**@paramchildrenKey子集key*@paramtreeData树数据*@paramresult集合数据*@param<T>List*/publicstatic<T>List<T>treeToList(StringchildrenKey,List<T>treeData,List<T>result){for......
  • Java毕业设计-基于springboot开发的致远汽车租赁系统平台-毕业论文+答辩PPT(附源代码+
    文章目录前言一、毕设成果演示(源代码在文末)二、毕设摘要展示1、开发说明2、需求分析3、系统功能结构三、系统实现展示1、系统功能模块2、管理员功能模块3、业务员功能模块3、用户功能模块四、毕设内容和源代码获取总结Java毕业设计-基于springboot开发的致远汽车租......
  • Java毕业设计-基于springboot开发的智慧外贸平台-毕业论文+答辩PPT(附源代码+演示视频)
    文章目录前言一、毕设成果演示(源代码在文末)二、毕设摘要展示1、开发说明2、需求分析3、系统功能结构三、系统实现展示1、系统功能模块2、后台功能模块2.1管理员功能2.2买家功能2.3商家功能四、毕设内容和源代码获取总结Java毕业设计-基于springboot开发的智慧外贸......
  • 深入解析Java中的核心数据结构:从基础到进阶实战
    在软件开发领域,熟悉并掌握数据结构对于提升程序性能和优化算法至关重要。本文将全面介绍Java中常用的核心数据结构,辅以示例代码和概念图解,以帮助读者更好地理解和应用这些数据结构。1.数组(Array)数组是Java中最基础的数据结构之一,它是在内存中一块连续区域存放相同类型元......
  • 【JavaEE】计算机是如何工作的
    文章目录一、计算机发展史二、冯诺依曼体系(VonNeumannArchitecture)三、CPU基本工作流程一、计算机发展史计算的需求在人类的历史中是广泛存在的,发展大体经历了从一般计算工具到机械计算机到目前的电子计算机的发展历程。二、冯诺依曼体系(VonNeumannArchitectur......