Android 13(T) - binder阅读(3)- binder相关的类

这篇具有很好参考价值的文章主要介绍了Android 13(T) - binder阅读(3)- binder相关的类。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

原先准备在binder阅读(3)中记录ServiceManager的使用,但是写着写着发现,如果不了解和binder相关的类,那么阅读起来将会由很多困惑,所以就先来记录binder相关的类了。记录完发现特别凌乱…先就这样吧。

1 UML类图

从 binder阅读(1)一开始的图中可以看到,getService获得的是一个handle,要怎样才能用这个handle完成RPC呢?Android为我们提供了一套框架,以下是框架相关类的UML类图。

我们设计的service需要遵循这套框架才能注册到binder驱动中,client也要遵循这套框架才能实现对service的调用。

Android 13(T) - binder阅读(3)- binder相关的类
接下来我们将会一起了解下面这张图中的内容。

binder框架代码位置: frameworks/native/libs/binder/
我将以MediaServer为例,代码位置:frameworks/av/media/libmedia/


2 IBinder

IBinder声明于IBinder.h,实现于Binder.cpp。

想要让一个类对象能够通过binder驱动进行跨进程传输,那么这个class必须要继承自IBinder接口。

IBinder服务本体远程代理提供了基本接口,并提供了一些基础实现,本体和代理均需要实现这些接口。


2 BBinder

BBinder声明于Binder.h,实现于Binder.cpp。

BBinder服务本体IBinder的实现。BBinder覆写了localBinder方法,使其可以返回服务本体,调用BBinder对象的remoteBinder方法将会返回null。

BBinder* BBinder::localBinder()
{
    return this;
}

transact方法用于执行远程代理的调用,根据不同的code执行不同的方法,transact已经实现了一些基本的调用,服务自定义的调用需要在onTransact做实现,该工作由子类完成。

virtual status_t transact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0) final;

virtual status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0);

3 BpBinder

BpBinder声明于BpBinder.h,实现于BpBinder.cpp。

BpBinder远程代理IBinder的实现。BpBinder覆写了remoteBinder方法,使其可以返回远程代理,调用BpBinder对象的localBinder方法将会返回null。

BpBinder中封装有从ServiceManager那里获取到的HandleBpBinder提供有私有的create方法,可以很方便的帮助我们用Handle创建一个BpBinder对象。

BpBinder同样有transact方法,该方法用于和binder驱动通信,利用handle调用服务提供的方法,而BBindertransact用于执行我们的远程调用。

有这样一种情况,我们在使用远程代理进行RPC调用,但是这时候service挂了,如果我们不及时处理程序就很容易出错了。为了解决这个问题,BpBinder提供了一个linkToDeath方法,当远程服务死亡时可以通知到使用者。这个不是我们的重点,所以这里只要会用就行。

virtual status_t    linkToDeath(const sp<DeathRecipient>& recipient, void* cookie = nullptr, uint32_t flags = 0);

4 IInterface

IInterface声明于IInterface.h,实现于IInterface.cpp。

我们定义的binder服务接口需要继承自IInterfaceIInterface可以理解是服务本体远程代理的一层封装,封装的是IBinder对象,提供更高层的接口,方便我们使用。

IInterface为我们提供了asBinder方法,这个方法的实现需要依赖子类对onAsBinder的实现,从名字上可以猜到它用来获取IInterface中封装的IBinder对象。

我们以 IMediaPlayerService为例看看binder服务接口要如何声明。IMediaPlayerService继承自IInterface,除了声明虚函数接口外,还调用了一个宏 DECLARE_META_INTERFACE,这个宏为我们提供了多个方法和类成员。

class IMediaPlayerService: public IInterface
{
public:
	 DECLARE_META_INTERFACE(MediaPlayerService);
}

DECLARE_META_INTERFACE 定义在 IInterface.h,将宏参数做替换后的代码如下:

public:                                                                                          
    static const ::android::String16 descriptor;                                                 
    static ::android::sp<IMediaPlayerService> asInterface(const ::android::sp<::android::IBinder>& obj); 
    virtual const ::android::String16& getInterfaceDescriptor() const; 
    IMediaPlayerService();                                                                               
    virtual ~IMediaPlayerService();                                                                      
    static bool setDefaultImpl(::android::sp<IMediaPlayerService> impl); 
    static const ::android::sp<IMediaPlayerService>& getDefaultImpl(); 
private:                                                                                          
    static ::android::sp<IMediaPlayerService> default_impl;    

实现同样也在 IInterface.h,这里我们不做展开,后面用到了我们再看。


5 BnInterface

BnInterface声明于IInterface.h,实现于IInterface.cpp。

BnInterface服务本体IInterface接口的实现:

template<typename INTERFACE>
inline sp<IInterface> BnInterface<INTERFACE>::queryLocalInterface(
        const String16& _descriptor)
{
    if (_descriptor == INTERFACE::descriptor) return sp<IInterface>::fromExisting(this);
    return nullptr;
}

template<typename INTERFACE>
inline const String16& BnInterface<INTERFACE>::getInterfaceDescriptor() const
{
    return INTERFACE::getInterfaceDescriptor();
}

template<typename INTERFACE>
IBinder* BnInterface<INTERFACE>::onAsBinder()
{
    return this;
}

覆写了IBinder接口queryLocalInterface用于返回服务本体(BnInterface)
覆写了IInterface接口onAsBinder,用于返回服务本体(IBinder)

我们在这里看下上面的宏定义实现展开:

const ::android::String16& IMediaPlayerService::getInterfaceDescriptor() const { return IMediaPlayerService::descriptor;} 

::android::sp<IMediaPlayerService> IMediaPlayerService::asInterface(const ::android::sp<::android::IBinder>& obj) {        
    ::android::sp<IMediaPlayerService> intr;                                                                 
    if (obj != nullptr) {
    	// 尝试将IBinder对象转换为BnMediaPlayerService对象                                                                
        intr = ::android::sp<IMediaPlayerService>::cast(obj->queryLocalInterface(IMediaPlayerService::descriptor));        
        if (intr == nullptr) { 
        	// 如果为null,则将IBinder对象转换为BpMediaPlayerService对象                                                                
            intr = ::android::sp<BpMediaPlayerService>::make(obj);                                           
        }                                                                                      
    }                                                                                          
    return intr;                                                                               
}  

template<typename INTERFACE>
inline sp<INTERFACE> interface_cast(const sp<IBinder>& obj)
{
    return INTERFACE::asInterface(obj);
}

我们从ServiceManager获取到的服务其实是一个IBinder对象,有了它我们还不能执行RPC,需要将它转换为BpInterface对象或者是说代理实现,该对象内完成了参数的封装以及对Handle的调用。那我们应该如何转换呢?用这里的两个方法asInterfaceinterface_cast 就可以了。


6 BpInterface

BpInterface声明于IInterface.h,实现于IInterface.cpp。

BpInterface指的是远程代理,除了实现了IInterface接口外,还继承了BpRefBase

BpRefBase声明于Binder.h,实现于Binder.cpp。BpRefBase用于管理远程代理的生命周期,用handle创建的BpBinder对象就存储于BpRefBaseBpRefBase的remote方法返回的就是BpBinder

template<typename INTERFACE>
inline BpInterface<INTERFACE>::BpInterface(const sp<IBinder>& remote)
    : BpRefBase(remote)
{}

template<typename INTERFACE>
inline IBinder* BpInterface<INTERFACE>::onAsBinder()
{
    return remote();
}

inline IBinder* remote() const { return mRemote; }

说到生命周期,BpRefBase 的用法我没太看懂什么意思。

BpRefBase::BpRefBase(const sp<IBinder>& o)
    : mRemote(o.get()), mRefs(nullptr), mState(0)
{
    extendObjectLifetime(OBJECT_LIFETIME_WEAK);

    if (mRemote) {
        mRemote->incStrong(this);           // Removed on first IncStrong().
        mRefs = mRemote->createWeak(this);  // Held for our entire lifetime.
    }
}

不过我猜是将BpRefBaseIBinder 的生命周期绑定,因为BpRefBaseIBinder需要相互依赖,IBinder释放了BpRefBase也就无法工作了,BpRefBase释放了IBinder同样也没有意义了。


7 Parcel

RPC调用时少不了要传输数据,server端如何才能够识别client端写过去的数据呢?这就需要他们做一个约定,按照既定的数据格式传输数据。

Parcel就是用于帮我们做数据格式化的工作的,包括输入数据的封装与输出数据的解压。我们按什么顺序写入数据,就要按照什么顺序读取数据。

Parcel声明于Parcel.h,实现于Parcel.cpp。

现在我们可以使用aidl生成binder接口,但是aidl文件中我们只能使用Parcel中已经定义的基础数据类型,而不能使用任意类型,这是因为Parcel并不知道要按照什么规则写入我们想要使用的数据。


8 IPCThreadState / ProcessState

我们的老朋友了,ProcessState用于打开关闭binder驱动程序,IPCThreadState用于与操作binder驱动,与之沟通。


写在最后:这一篇笔记记录了一些零零碎碎的内容,主要了解了一些类的接口含义与使用。写到这我有点凌乱了,因为这篇仅仅是流水账式的记录,并没有什么章法可言,我应该也没有理解为什么binder框架这么设计。

现在回过头又想了一些,不知是对是错,就先记录在这里:文章来源地址https://www.toymoban.com/news/detail-508397.html

  1. binder驱动中传输的对象之所以要继承自IBinder,是因为传输的对象有可能是代理,也有可能是服务实体,我们得区分他们,IBinder为我们提供了区分他们的方法;
  2. 远端代理 和 本地服务 实际的执行者不同,所以又区分了BBinderBpBinderBBinder中是一个实例化的提供服务的对象,而BpBinder存储的是服务的引用handle;
  3. 为了保证远端代理 和 本地服务的接口保持一致,所以他们都继承了IInterface
  4. 远端的接口和本地的服务接口实际完成的工作不一样,所以区分出了BnInterfaceBpInterfaceBpInterface需要组织数据并且向handle发送数据,BnInterface需要根据发来的数据做真正的函数调用。

到了这里,关于Android 13(T) - binder阅读(3)- binder相关的类的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Android 13 网络 Adb相关流程深入分析研究

    通过代码分析发现Android13 上对 网络adb 进行了限制! Android13原生代码要求:必现连接上某个wifi,才能进行adb ,并且切换wifi或者关闭wifi都是会停止adb。 并且Android13 上 wifi adb 端口号每次是变化的,这个也是很不方便的! 如果要做成Android11 或者之前一样,设备连接WiFi/有线网

    2024年02月09日
    浏览(33)
  • Android13关于获取外部存储文件的相关问题及解决方案记录

      Android的学习路上... 测试设备:vivo X90s 安卓版本: Android13 开发环境:AndroidStudio Flamingo SDK:33 最近我在Android13的环境下尝试写一个 文件选择器 ,以便日后的开发使用。但是我们知道,从Android13 (API33) 开始,外部存储权限发生了变化,要想读取外部存储文件,使用原来的权

    2024年01月15日
    浏览(36)
  • android 13 WMS/AMS系统开发-窗口层级相关DisplayArea,WindowContainer

    官方注释: 给可以直接持有窗口的自己或它的孩子定义了一些公共的方法和属性,像RootWindowContainer、DisplayContent、DisplayArea、DisplayArea.Tokens、TaskDisplayArea、Task、ActivityRecord、WindowToken、WindowState都是直接或间接的继承该类。 这里面主要的重要要成员变量就是mParent和mChildren,一

    2024年02月16日
    浏览(25)
  • android 13 WMS/AMS系统开发-窗口层级相关DisplayArea,WindowContainer第二节

    接着上一节课学习,我们已经清楚的知道了层级结构应该怎么看,根据dumpsys的输出可以完美复原出层级结构树,也理解了结构树对于层级结构的控制作用。但还没有从源码部分对这个结构树进行一个分析,即分析生成这个结构树的源码部分。 结下来调用是实现类DefaultProvid

    2024年02月15日
    浏览(29)
  • 【Android】Binder(一)Binder的介绍和AIDL使用Binder的实例

    Android 中的 Binder 是一个进程间通信机制,它允许不同进程之间相互调用方法和传递数据。Binder 主要用于实现系统服务和应用程序之间的通信,以及实现 IPC(Inter-Process Communication,进程间通信)。 Binder 的核心是 Binder 驱动程序,它负责管理不同进程之间的通信。每个进程都可

    2024年02月07日
    浏览(27)
  • 【Android】深入Binder拦截

    ☞ Github ☜ ☞ Gitee ☜ Binder 作为 Android 系统跨进程通信的核心机制。网上也有很多深度讲解该机制的文章,如: Android跨进程通信详解Binder机制原理 Android系统核心机制Binder【系列】 这些文章和系统源码可以很好帮助我们理解Binder的实现原理和设计理念,为拦截做准备。借助

    2024年02月03日
    浏览(26)
  • Android Binder小结

    Binder是Android中一种跨进程通信方式,Binder也是一个虚拟设备,对于客户端来说Bidner是一个可以跨进程通信的一个类 Android底层是Linux,但是Linux已有的跨进程通信方式都不能满足Android移动设备的需求,在Android中跨进程通信方式,要求是CS的一对多的架构、需要保证安全,并且

    2023年04月08日
    浏览(25)
  • Android 进阶——Binder IPC之Binder IPC架构及原理概述(九)

    前面几篇文章,为我们学习Binder IPC通信机制提供了扎实的理论基础,接下来将正式进入Binder IPC通信架构及原理的解读。 Binder 是基于 C/S 架构的,由一系列的组件组成,包括 Client进程、Server进程、Service Manager进程、Binder 驱动。其中 Client进程、Server进程、Service Manager进程运行

    2023年04月09日
    浏览(31)
  • 13.Netty源码之Netty中的类与API

    Bootstrap 意思是引导,一个 Netty 应用通常由一个 Bootstrap 开始,主要作用是配置整个 Netty 程序,串联各个组件,Netty 中ServerBootstrap 是服务端启动引导类。 java //泛型 AbstractBootstrapB extends AbstractBootstrapB, C, C extends Channel ​ ServerBootstrap extends AbstractBootstrapServerBootstrap, ServerChannel ​

    2024年02月15日
    浏览(38)
  • Android 基础技术——Binder 机制

    笔者希望做一个系列,整理 Android 基础技术,本章是关于Binder 机制 什么是Binder 机制:Binder 是一种进程间通信机制 驱动:Binder 是一个虚拟物理设备驱动 应用层:Binder 是一个能发起通信的 Java 类 为什么要使用Binder 图解析: 性能上:  binder小于共享内存 优于其他ipc 共

    2024年02月19日
    浏览(24)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包