IBinder体系中得到一个服务的过程分析:
ServiceManager是管理所有服务(如音频,相机)的一个进程,它的handle是0
一、总的来说:得到一个service很简单,分成两步,
1,得到一个默认的serviceManager;
2,然后使用serviceManger->getService(service名称)得到具体的service

二、详细分析
参照网上一些资料(感谢石头),我们也以得到AudioFlinger服务为例,详细的讲述整个过程。
1,AudioSystem.cpp中有个函数const sp<IAudioFlinger>& AudioSystem:: get_audio_flinger(),顾名思义,该函数的功能是得到AudioFlinger服务
2,查看该函数的实现,首先我们看到了一个函数调用:
sp<IServiceManager> sm = defaultServiceManager();
该函数就是我们所说的第一步---得到一个默认的serviceManager;
defaultServiceManager()的实现如下:
sp<IServiceManager> defaultServiceManager()
{
if (gDefaultServiceManager != NULL) 
return gDefaultServiceManager;

{
AutoMutex _l(gDefaultServiceManagerLock);
if (gDefaultServiceManager == NULL) {
gDefaultServiceManager = interface_cast<IServiceManager>(
ProcessState::self()->getContextObject(NULL));
}
}

return gDefaultServiceManager;
}

重点分析gDefaultServiceManager = interface_cast<IServiceManager>(
ProcessState::self()->getContextObject(NULL));
A.ProcessState::self()得到一个ProcessState的实例,在它的构造函数中通过mmap将/dev/binder文件映射到了一段内存,并将这段内存的地址保存下来,这段内存就是IBinder中进行数据客户端和服务端读写数据的地方
B.ProcessState::self()->getContextObject(NULL)); 通过getStrongProxyForHandle返回一个BpBinder对象
C.根据上面描述,该语句实际上就是interface_cast<IServiceManager>(BpBinder)
D.在此,我们有必要关注一下interface_cast,通过代码跟踪:看到它的实现
template<typename INTERFACE>
inline sp<INTERFACE> interface_cast(const sp<IBinder>& obj)
{
return INTERFACE::asInterface(obj);
}
通过模板替换就是:
inline sp< IServiceManager > interface_cast(const sp<IBinder>& obj)
{
return IServiceManager::asInterface(obj);
}
看来在asInterface是IServiceManager的一个成员函数,我们打开IServiceManager.cpp/h文件,我们并没有发现该函数,那它到底在哪儿呢,仔细观察IServiceManager.cpp,发现里面有个
IMPLEMENT_META_INTERFACE(ServiceManager, "android.os.IServiceManager");
在IServiceManager.h里面发现了
DECLARE_META_INTERFACE(ServiceManager);
通过跟踪这两个宏发现DECLARE_META_INTERFACE声明了一个变量和两个函数,代码如下:
#define DECLARE_META_INTERFACE(INTERFACE)                  \
static const String16 descriptor;                                   \
static sp<I##INTERFACE> asInterface(const sp<IBinder>& obj);        \
virtual String16 getInterfaceDescriptor() const;                    \

IMPLEMENT_META_INTERFACE这个宏是对上面声明的实现
#define IMPLEMENT_META_INTERFACE(INTERFACE, NAME)         \
const String16 I##INTERFACE::descriptor(NAME);                  \
String16 I##INTERFACE::getInterfaceDescriptor() const {             \
return I##INTERFACE::descriptor;                          \
}                                                       \
sp<I##INTERFACE> I##INTERFACE::asInterface(const sp<IBinder>& obj)  \
{                                                    \
sp<I##INTERFACE> intr;                                \
if (obj != NULL) {                                       \
intr = static_cast<I##INTERFACE*>(                     \
obj->queryLocalInterface(                         \
I##INTERFACE::descriptor).get());         \
if (intr == NULL) {                                    \
intr = new Bp##INTERFACE(obj);                \
}                                                \
}                                             \
return intr;                                      \
}                                                   \
interface_cast<IServiceManager>实际上返回了一个BpServiceManager,在创建一个BpServiceManager时,有些细节还是需要注意:
BpServiceManager(const sp<IBinder>& impl): BpInterface<IServiceManager>(impl){}
BpInterface<IServiceManager>(impl)中的impl实际就是一个BpBinder,它调用了BpInterface的构造函数,然后调用了BpRefBase(remote),从而把一个BpBinder赋值给了mRemote,这个变量会在后面传输的时候用到

3,AudioSystem.cpp文件中紧接着就执行了 binder = sm->getService(String16("media.audio_flinger")); //参数是服务名称
我们知道了sm就是一个BpServiceManager,可以在BpServiceManager类中看到getService的实现,它调用了checkService,checkService先将数据打包成Parcel格式,然后调用remote()->transact(CHECK_SERVICE_TRANSACTION, data, &reply);进行传输,remote()是BpServiceManager父类BpRefBase的一个成员函数,作用是返回mRemote(在上面讲过它就是一个BpBinder),那么我们就去BpBinder.cpp中去寻找transact的实现,代码如下:
status_t BpBinder::transact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
// Once a binder has died, it will never come back to life.
if (mAlive) {
status_t status = IPCThreadState::self()->transact(
mHandle, code, data, reply, flags);
if (status == DEAD_OBJECT) mAlive = 0;
return status;
}

return DEAD_OBJECT;
}
IPCThreadState是专门负责进程间通讯的,包括进程间的数据传输,查看IPCThreadState::self()->transact(mHandle, code, data, reply, flags)的实现,提取两行和我们相关的代码
………………..
Err = writeTransactionData(BC_TRANSACTION, flags, handle, code, data, NULL);
……………………….
err = waitForResponse(reply);
writeTransactionData的作用是把数据写到类型为Parcel的mOut容器中去,方便ServiceManager读取
waitForResponse等待ServiceManager找到具体的服务,并把结果传回来
查看status_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult)的实现,里面调用了函数talkWithDriver(),该函数通过ioctl将mOut中的数据写到Binder driver中去,同时等待将返回的数据写入mIn。此时,数据的发送就算完成。
再来看看ServiceManager是怎么读取该数据的,在Service_manager.c中,调用了binder_loop(bs, svcmgr_handler),binder_loop其实就是一直在等待数据的到来,到来就就从驱动中读取数据,然后调用binder_parser解析,在binder_parser中
case BR_TRANSACTION:
…………………..
res = func(bs, txn, &msg, &reply);//这里的func就是svcmgr_handler
binder_send_reply(bs, &reply, txn->data, res); //将结果返回到Binder driver中
svcmgr_handler在getService的情况下,就是从服务链表中根据名称找到对应的服务的节点,然后转化成binder_object的格式后返回回去

waitForResponse中将返回结果写到reply中,然后从reply中就结果返回给调用者

其实简单来说,就是在打开一个设备的时候,android的设计是将该设备的信息(服务)均记录下来,这样你在打开一个设备的时候,首先先去检查系统中是否支持该设备的服务,如果支持的话,那么调用getSerive创建一条Binder通道(由processstate创建一个实例,维护一条内存通道)。然后服务器端返回一个IBinder给客户端,那么客户端就可以得到该服务的代理,以后通信都是通过该代理来与服务器通信。

Android中主要通过2种方法来获得service IBinder:

1.       通过ServiceManager.getService(String Descriptor)来获得Service Manager管理的service的IBinder。
2.       Client获得Application Service的IBinder,如下图描述的binder service流程。

分析IBinder体系中getService的流程相关推荐

  1. android6.0中app crash流程分析

    要根据这个流程分析一下如何在应用中截获系统的app crash弹框,然后做到更人性化 基于Android 6.0的源码剖析, 分析Android应用Crash是如何处理的. /frameworks/b ...

  2. 带你从源码角度分析ViewGroup中事件分发流程

    序言 这篇博文不是对事件分发机制全面的介绍,只是从源码的角度分析ACTION_DOWN.ACTION_MOVE.ACTION_UP事件在ViewGroup中的分发逻辑,了解各个事件在ViewGroup ...

  3. 【Android 逆向】整体加固脱壳 ( DEX 优化流程分析 | DexPrepare.cpp 中 dvmContinueOptimizati() 函数分析 )

    文章目录 前言 一.DexPrepare.cpp 中 dvmContinueOptimizati() 方法分析 前言 上一篇博客 [Android 逆向]整体加固脱壳 ( DEX 优化流程分析 | D ...

  4. CE5.0 - eboot汇编Startup.s中MMU设置流程详细分析

    CE5.0 - eboot汇编Startup.s中MMU设置流程详细分析   以下为SMDK开发板startup.s部分启动代码.   ;------------------------------- ...

  5. FSSC22000认证咨询,本程序适用与食品安全体系中的产品危害信息收集、分析和评估等所有活动

    4.8 原计划的评估改进 4.8.1 评估原管理执行情况应该包含在公司FSSC周期性评估范围内.食品安全小组应根据公司产品原含量检测报告.客户投诉或相关部门反馈情况和公司内外反应信息对原管理执行效果进 ...

  6. 【Android 安全】DEX 加密 ( Application 替换 | 分析 ContentProvider 组件中调用 getApplication() 获取的 Application )

    文章目录 一. ContentProvider 创建过程分析 二. ActivityThread 中的 H 处理 BIND_APPLICATION 消息 三. ActivityThread 中的 ha ...

  7. 【Android 安全】DEX 加密 ( Application 替换 | 分析 BroadcastReceiver 组件中调用 getApplication() 获取的 Application )

    文章目录 一. Service 中的 getApplication() 方法分析 二. ActivityThread 中的 H 处理 RECEIVER 消息 三. ActivityThread 中的 ...

  8. 【Android 安全】DEX 加密 ( Application 替换 | 分析 Service 组件中调用 getApplication() 获取的 Application 是否替换成功 )

    文章目录 一. Service 中的 getApplication() 方法分析 二. ActivityThread 中的 H 处理 CREATE_SERVICE 消息 三. ActivityThre ...

  9. 【Android 安全】DEX 加密 ( Application 替换 | 分析 Activity 组件中获取的 Application | ActivityThread | LoadedApk )

    文章目录 一. Activity 中的 getApplication() 方法分析 二. ActivityThread 中的 H 处理 消息及 handleLaunchActivity 方法操作 三. ...

最新文章

  1. JavaScript 中运算符的优先级
  2. memcached监控的几种方法(nagios等)
  3. oracle查看临时表空间文件,Oracle-临时表空间
  4. 计算机转集成光学,集成光学
  5. Java 洛谷 P2141 珠心算测验
  6. boost::histogram::axis::integer用法的测试程序
  7. 《金色梦乡》金句摘抄(九)
  8. java awt文件上传_springMVC实现前台带进度条文件上传的示例代码
  9. Atitit 项目中的勋章体系,,mvp建设 ,荣典体系建设
  10. VCC,GND,VSS,VDD的理解
  11. linux进程终止命令,Linux kill命令:终止进程
  12. 计算机光纤接口网卡,光纤网卡是什么?
  13. 【粉丝福利】第二波 | 当当购书狂欢,满 400 减 230!下单充电速来!
  14. 为什么阿里巴巴规定禁止超过三张表 join
  15. 股票入门:股票交易手续费用怎么算(转)
  16. Ford-Fulkerson 标号法求网络最大流
  17. 发光字招牌制作底板的种类
  18. 基于视觉导航的自主机器人简介(一)
  19. linux 存储映射lun 给_LINUX系统下添加映射存储LUN(无需重启)
  20. 解读新零售:什么叫做人货场的重构

热门文章

  1. linux内核代码研读与实战,Linux内核源码研读与实战演练
  2. MYSQL 时间格式化
  3. 2020Revit又是怎样进行正向建模的呢?适合Revit建模插件工具
  4. python窗口界面自适应_自适应页面的实现方式
  5. java集成seetaface_开源人脸识别seetaface入门教程(一)
  6. UI自动化测试工具Airtest
  7. Stack Overflow简单介绍
  8. python毕业论文开题报告_本科毕业论文开题报告怎么写-如何写毕业设计的开题报告?...
  9. 基于STM32蓝牙无线手环脉搏心率计步器体温监测设计
  10. Chrome浏览器更新