Android Binder Mechanism (2) -- 如何获得ServiceManager的代理对象的引用

    在这篇文章中,我们将深入剖析一下Android系统的服务管理员ServiceManager。

 

    ServiceManager是Android系统服务的管理者。所有需要通过Binder机制进行进程间通信的进程都要首先获得Service Manager的代理对象才能进行Binder通讯。比如系统中有用于音频混音的AudioFlingerService,用于照相的CameraService,用于媒体文件播放的MediaPlayerService。所有这些服务都会向ServiceManager注册,因此ServiceManager就维护了系统中所有服务的一个列表。任何应用程序要想使用这些服务,首先要向ServiceManager请求获得这些服务的引用,从而建立起和这些服务的联系。

 

    在本系列的第一篇文章中,ExampleService通过如下语句向系统注册服务。

 

 

    这里有两个问题:

    1. defaultServiceManager()都完成了哪些工作,它返回的结果是什么?

    2. 为什么调用上一步返回对象的addService方法,就可以向系统注册服务?这一注册过程都完成了哪些工作?

 

    这篇文章先回答问题1。

    ServiceManager也是系统中的一个服务,那么应用程序如何和它取得联系呢?答案就是通过defaultServiceManager()函数。defaultServiceManager()是系统在Android命名空间中定义的一个全局函数,用来获得ServiceManager的代理对象的引用。我们看一下该函数的源代码。

    gDefaultServiceManager在libutil中定义,因此任何程序或库使用了libutil库都会有该变量,它在一个进程中是唯一的。gDefaultServiceManager的初始值为NULL,所以先调用ProcessState::self()方法获取一个ProcessState实例。这里用到了Singleton的设计模式,从而可知一个进程只有一个ProcessState实例。

    该ProcessState会打开/dev/binder设备供IPCThreadState使用。查看其构造函数便知。

    再看一下open_driver()方法的源代码。

    open_driver()方法打开binder设备(/dev/binder),获取binder版本号,设定最大线程个数,并返回binder设备的文件描述符。内核空间中分配约1M的连续空间(BINDER_VM_SIZE)给进程,并用mmap函数映射到进程的用户空间。该空间用于transaction交互数据用。

    回到defaultServiceManager()方法。我们可以看到defaultServiceManager()是调用ProcessState对象的getContextObject方法获得ServiceManager的代理对象。我们再看一下getContextObject函数的源代码:

    因为支持binder驱动(supportsProcesses()函数会判断binder驱动是否打开,以此来检验是否支持binder),这里是以0为参数调用getStrongProxyForHandle()方法获得ServiceManager的代理对象。我们再看一下getStrongProxyForHandle()方法的源代码:

    getStrongProxyForHandle()首先调用lookupHandleLocked()方法查找当前进程是否维护的Service代理对象的列表。我们再看一下lookupHandleLocked()方法的源代码。

    mHHandleToObject是一个以handle_entry类型为元素的Vector,维护当前进程的代理对象列表。其索引就是每个代理对象句柄的值。比如ServiceManager对应的句柄肯定是0,那么它就是这个列表的第1项。如果待查询的的句柄的值大于等于当前列表的大小,说明待创建的Service代理对象条目尚未在当前进程中创建,那么就需要插入新项。当前的列表大小是N,索引从0至N-1,如果待查询的索引是handle,那么就要插入handle-(N-1)项。如果该代理对象条目已经创建过了,那么直接返回其引用就可以了。

    注:这里的“创建”只是在列表中创建相应的条目(e.binder = NULL;e.refs = NULL;),真正的代理对象要在稍后才创建。

    现在回到getStrongProxyForHandle()方法。如果该代理对象尚未创建(e->binder==NULL),那么就创建一个,并更新代理对象列表中的相应记录。

    我们再来看一下BpBinder类的构造函数做了什么。

    这里调用了IPCThreadState类的incWeakHandle()方法来增加引用计数。我们再看看incWeakHandle()方法的源代码。

    这里incWeakHandle()在输出缓冲区增加了一条BC_INCREFS命令。

    如果该handle对应的代理对象已经创建过了,那么就增加它的引用计数。result是一个指向IBinder类型的强指针。Android系统中定义了sp(strong pointer)和wp(weak pointer)两种智能指针。注意这里的操作符"="已经被重载了。force_set是RefBase类专门为ProcessState类优化的一个方法,让我们看一下它的源代码。

    设定好引用计数之后,getStrongProxyForHandle()方法返回代理对象的句柄。接下来会通过interface_cast将其转换为IserviceManager类型。我们来看看这个转换是怎么实现的。

    interface_cast<IServiceManager>,其实调用的是IServiceManager.asInterface方法:

    查看IServiceManager的源文件,好像并没有定义asInterface方法。不要急,我们先看一下IServiceManager的定义:

    这里的宏DECLARE_META_INTERFACE在IInterface.h头文件中定义如下:

    这里,我们终于找到了asInterface方法的声明。该方法是通过在IServiceManager.cpp文件中的IMPLEMENT_META_INTERFACE宏来实现的。

    IMPLEMENT_META_INTERFACE宏定义如下:

    将上面这些宏展开后的最终结果就是,

    可见,IServiceManager::asInterface()函数最终会用一个IBinder对象创建一个BpServiceManager对象,并将它返回。

    好了,现在我们总结一下获取ServiceManager代理对象的全部过程:

defaultServiceManager();                        // 获取ServiceManager代理对象

{

    interface_cast<IServiceManager>(ProcessState::self()->getContextObject(NULL));  // 将返回的BpBinder类型的代理对象转换成ServiceManager类型的代理对象

    {

        getStrongProxyForHandle(0);         // 以0为参数即可获得ServiceManager的代理对象

        {

            lookupHandleLocked(0);

            b = new BpBinder(0);         // 新建一个代理对象

            返回根据handle生成的代理对象

        }

        返回根据handle生成的代理对象

    }

    返回转换成ServiceManager类型的代理对象

}

 

    最后,我们可以回答问题1了:

    问题: defaultServiceManager()都完成了哪些工作,它返回的结果是什么?

    答: 如果当前进程已经生成了ServiceManager的代理对象,那么该函数返回它的一个引用;如果当前进程还没有生成过ServiceManager的代理对象,那么创建它,并返回它的一个引用。

 

    我们将在下篇文章中深入剖析为什么调用该引用指向的getService方法就可以获得ExampleService的代理对象的引用。

   

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值