前面一节我们分析了Binder通信相关的两个重要类:ProcessState 和 IPCThreadState。ProcessState负责打开Binder
驱动,每个进程只有一个。而 IPCThreadState负责提供与Binder通信相关的接口,每个线程有一个。下面我们通过具体
示例MediaPlayerService来分析我们应用程序中怎么通过Binder通信的。

frameworks/base/media/mediaserver/main_mediaserver.cpp

  1. int main(int argc, char*argv[])
  2. {
  3. sp<ProcessState> proc(ProcessState)::self(); // 获得ProcessState在构造函数中打开binder驱动
  4. sp<IServiceManager> sm = defaultServiceManager();
  5. MediaPlayService::instantiate();
  6. ProcessState::self()->startThreadPool();
  7. IPCThreadState::self()->joinThreadPool();
  8. }

1)获得ServiceManager的代理BpServiceManager

  1. sp<IServiceManager> sm = defaultServiceManager();
  2. sp<IServiceManager> defaultServiceManager()
  3. {
  4. if(gDefaultServiceManager != NULL) return gDefaultServiceManager;
  5. {
  6. AutoMutex -l(gDefaultServiceManagerLock);
  7. if(gDefaultServiceManager == NULL)
  8. gDefaultServiceManager = interface_cast<IServiceManager>(
  9. ProcessState::self()->getContextObject(NULL));
  10. }
  11. return gDefaultServiceManager;
  12. }

这里又是一个单例模式,每个进程只需要一个BpServiceManager代理,通过interface_cast获得。
首先看看ProcessState::self()->getContextObject(NULL)

  1. sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& caller)
  2. {
  3. return getStrongProxyForHandle(0);
  4. }
  5.  
  6. sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)
  7. {
  8. sp<IBinder> result;
  9. AutoMutex _l(mLock);
  10. handle_entry *e = lookupHandleLocked(handle);
  11. if( e != NULL) {
  12. IBinder* b = e->binder;
  13. if(b == NULL || !e->refs->attemptIncWeak(this)) {
  14. b = new BpBinder(handle);
  15. e->binder = b;
  16. if(b) e->refs = b->getWeakRefs();
  17. result = b;
  18. }else{
  19. result.force_set(b);
  20. e->refs->decWeak(this);
  21. }
  22. }
  23. return result;
  24. }
  25. struct handle_entry{
  26. IBinder* binder;
  27. RefBase::weakref_type* refs;
  28. }

ProcessState::handle_entry* ProcessState::lookupHandleLocked()从数组mHandleToObject里面根据handle索引,查找
一个handle_entry结构体。然后根据传入的句柄handle这里为0,表示ServiceManager,new一个BpBinder
所以现在相当于:
gDefaultServiceManager = interface_cast<IServiceManager>(new BpBinder(0));

现在我们看看interface_cast是什么?

  1. frameworks/base/include/binder/IInterface.h
  2. template<typename INTERFACE>
  3. inline sp<INTERFACE> interface_cast(const sp<IBinder>& obj)
  4. {
  5. return INTERFACE::asInterface(obj);
  6. }
  7. 等价于:
  8. inline sp<IServiceManager> interface_cast(const sp<IBinder>& obj)
  9. {
  10. return IServiceManager::asInterface(obj);
  11. }
  12. 继续我们跟到IServiceManager里面去:
  13. frameworks/base/include/binder/IServiceManager.h
  14. class IServiceManager:public IInterface
  15. {
  16. public:
  17. DECLARE_META_INTERFACE(ServiceManager);// MLGB的又是宏!!!
  18. virtual status_t addService(const String16& name, const sp<IBinder>& service) = 0;
  19. virtual sp<IBinder> getService(const String16& name) const = 0;
  20. }
  21. #define DECLARE_META_INTERFACE(INTERFACE) \
  22. static const android::String16 descriptor; \
  23. static android::sp<I##INTERFACE> asInterface( \
  24. const android::sp<android::IBinder>& obj); \
  25. virtual const android::String16& getInterfaceDescriptor() const;\
  26. I##INTERFACE(); \
  27. virtual !I##INTERFACE();
  28. 替换之后就是:
  29. static const android::String16 descriptor;
  30. static android::sp<IServiceManager> asInterface(
  31. const android::sp<android::IBinder>& obj);
  32. virtual const android::String16& getInterfaceDescriptor() const;
  33. IServiceManager();
  34. virtual !IServiceManager();
  35. 都是一些函数声明,既然有声明的地方,肯定有实现的地方了。
  36. #define IMPLEMENT_META_INTERFACE(INTERFACE, NAME) \
  37. const android::String16 I##INTERFACE::descriptor(NAME); \
  38. const android::String16& \
  39. I##INTERFACE::getInterfaceDescriptor() const { \
  40. return I##INTERFACE::descriptor; \
  41. } \
  42. android::sp<I##INTERFACE> I##INTERFACE::asInterface( \
  43. const android::sp<android::IBinder>& obj) \
  44. { \
  45. android::sp<I##INTERFACE> intr; \
  46. if (obj != NULL) { \
  47. intr = static_cast<I##INTERFACE*>( \
  48. obj->queryLocalInterface( \
  49. I##INTERFACE::descriptor).get()); \
  50. if (intr == NULL) { \
  51. intr = new Bp##INTERFACE(obj); \
  52. } \
  53. } \
  54. return intr; \
  55. } \
  56. I##INTERFACE::I##INTERFACE() { } \
  57. I##INTERFACE::~I##INTERFACE() { }
  58. 继续替换:
  59. {
  60. const android::String16 IServiceManager::descriptor(NAME);
  61. const android::String16&
  62. IServiceManager::getInterfaceDescriptor() const {
  63. return IServiceManager::descriptor;
  64. }
  65. android::sp<IServiceManager> IServiceManager::asInterface(
  66. const android::sp<android::IBinder>& obj) // 参数为new BpBinder(0)
  67. {
  68. android::sp<IServiceManager> intr;
  69. if (obj != NULL) {
  70. intr = static_cast<IServiceManager*>(
  71. obj->queryLocalInterface(
  72. IServiceManager::descriptor).get());
  73. if (intr == NULL) {
  74. intr = new BpServiceManager(obj); // 原来在这里new 了一个BpServiceManager对象
  75. }
  76. }
  77. return intr;
  78. }
  79. IServiceManager::IServiceManager() { }
  80. IServiceManager::~IServiceManager() { }
  81. }

总结:根据句柄handle 0 创建一个new BpBinder(0),根据这个BpBinder创建了一个BpServiceManager代理。

下面来看看BpServiceManager代理:

  1. class BpServiceManager : public BpInterface<IServiceManager>
  2. {
  3. public:
  4. BpServiceManager(const sp<IBinder>& impl) : BpInterface<IServiceManager>(iml)
  5. {}
  6. }

这里BpInterface是一个模板类,表示这里BpServiceManager同时继承与BpInterface和IServiceManager类

  1. template<typename INTERFACE>
  2. class BpInterface : public INTERFACE, public BpRefBase
  3. {
  4. public: BpInterface(const sp<IBinder>& remote);
  5. ...
  6. }
  7. 调用了基类BpInterface构造函数:
  8. BpInterface<IServiceManager>::BpInterace(const sp<IBinder>& remote) : BpRefBase(remote)
  9. {}
  10. //这里的remote就是刚刚的new BpBinder(0)
  11. BpRefBase::BpRefBase(const sp<IBinder>& o) : mRemote(o.get()),mRefs(NULL), mState(0)
  12. {
  13. }

2)添加服务 MediaPlayerService::instantiate();

  1. frameworks/base/media/libmediaplayerservice/ibMediaPlayerService.cpp
  2. void MediaPlayerService::instantiate()
  3. {
  4. defaultServiceManager()->addService(String16("media.player"), new MediaPlayerService);
  5. }

defaultServiceManager()返回的是刚创建的BpServiceManager,调用add函数。
BpMediaPlayService作为服务代理端,那么BnMediaPlayerService一定是实现端,MediaPlayerService继承于
BnMediaPlayerService,实现了真正的业务函数。

来看看BpServiceManager的addService()函数:

  1. virtual status_t addService(const String16& name, const sp<IBinder>& service)
  2. {
  3. Parcel data, reply;
  4. data.writeInterfaceToken(IServiceManager.getInterfaceDescriptor()); // android.os.IServiceManager
  5. data.writeString16(name); // media.player
  6. data.writeStrongBinder(service); // 也就是MediaPlayerService
  7. status_t err = remote()->transact(ADD_SERVICE_TRANSACTION, data, &reply);
  8. return err == NO_ERROR ? reply.readInt32() : err;
  9. }

这里remote()就是前面创建的BpBinder(0)对象。

  1. status_t BpBinder::transact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
  2. {
  3. IPCThreadState::self()->transact(mHandle, code, data, reply, flags);
  4. }
  5. status_t IPCThreadState::transact(int32_t handle, uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
  6. {
  7. // 发送ADD_SERVICE_TRANSACTION请求
  8. writeTransactionData(BC_TRANSACTION, flags, handle, code, data, NULL);
  9. if(reply) // 等待响应
  10. waitForResponse(NULL, reply);
  11. }
  12.  
  13. status_t IPCThreadState::writeTransactionData(int32_t cmd, uint32_t binderFlags, int32_t handle,
  14. uint32_t code, const Parcel& data, status_t *statusBuffer)
  15. {
  16. // cmd BC_TRANSACTION 应用程序向BINDER发送的命令
  17. binder_transaction_data tr;
  18. tr.target.handle = handle; // 0
  19. tr.code = code; // ADD_SERVICE_TRANSACTION
  20. tr.flags = binderFlags;
  21. // 把命令和数据一起发送到 Parcel mOut中
  22. mOut.writeInt32(cmd);
  23. mOut.write(&tr, sizeof(tr));
  24. }
  25. status_t IPCThreadState::waitForResponse(Parcel* reply, status_t *acquireResult)
  26. {
  27. int32_t cmd;
  28.  
  29. while(1)
  30. talkWithDriver();
  31. cmd = mIn.readInt32();
  32. switch(cmd) {
  33. case BR_TRANSACTION_COMPLETE:
  34. ...
  35. break;
  36. }
  37. {
  38. return err;
  39. }
  40. status_t IPCThreadState::talkWithDriver(bool doReceive)
  41. {
  42. binder_write_read bwr;
  43.  
  44. bwr.write_size = outAvail;
  45. bwr.write_buf = (long unsigned int)mOut.data(); // 写入mOut的数据
  46. bwr.read_size = mIn.dataCapacity;
  47. bwr.read_buffer = (long unsigned int)mIn.data();
  48. ioctl(mProcess->mDriverFD, BINDER_WRITE_READm &bwr); // 把mOut写到Binder,并读取mIn数据
  49. }

3)IPCThreadState::joinThreadPool(), ProcessState::self()->startThreadPool()
进入线程循环talkWithDriver 等待客户端Client请求,从Binder读取命令请求进行处理。

到现在为止MediaPlayerService的服务端已经向服务总管ServiceManager注册了,下面我们看看客户端是如何获得服务的代理并和服务端通信的。
我们以MediaPlayer的业务函数decode解析播放一个URL为例

  1. sp<IMemory> MediaPlayer::decode(const char*url, uint32_t *pSampleRate, ...)
  2. {
  3. sp<IMemory> p;
  4. const sp<IMediaPlayerService>& service = getMediaPlayerService(); // 获得BpMediaPlayerSerivce代理
  5. if(service != 0)
  6. p = service->decode(url, ....);
  7. return p;
  8. }

这里我们主要分析getMediaPlayerService,客户端是如何向ServiceManager总管查询服务并获得代理的。

  1. sp<IMediaPlayerService>& IMediaDeathNotifier::getMediaPlayerService()
  2. {
  3. sp<IServiceManager> sm = defaultServiceManager(); // 生成一个BpServiceManager代理对象
  4. sp<IBinder> binder;
  5. do {
  6. binder = sm->getService(String16("media.player"));
  7. if(binder != 0)
  8. break;
  9. usleep(500000)
  10. } while(true);
  11. sMediaPlayerService = interface_cast<IMediaPlayerService>(binder);
  12. return sMediaPlayerService;
  13. }

1)首先获得BpServiceManager的代理,然后调用getService()函数向服务总管ServiceManager查询服务。
frameworks/base/libs/binder/IServiceManager.cpp

  1. class BpServiceManager : public BpInterface<IServiceManager>
  2. {
  3. public:
  4. virtual sp<IBinder> getService(const String16& name) const
  5. {
  6. for(n = 0; n < 5; n++) {
  7. sp<IBinder> svc = checkService(name); // 调用checkService函数
  8. if(svc != NULL) return svc;
  9. sleep(1);
  10. }
  11. return NULL;
  12. }
  13. virtual sp<IBinder> checkService(const String16& name) const
  14. {
  15. Parcel data, reply;
  16. data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());
  17. // 首先调用data.writeInt32(IPCThreadState::self()->getStrictModePolicy())
  18. // 然后再写入android.os.IServiceManager
  19. data.writeString16(name); // 写入 media.player
  20. remote()->transact(CHECK_SERVICE_TRANSACTION, data, &reply);
  21. return reply.readStrongBinder();
  22. }
  23. }

这里首先将请求打包成Parcel各式,然后调用remote()->transact()函数,前面我们分析过BpServiceManager::remote()返回
的就是前面new BpBinder(0)对应句柄为ServiceManager。继续去BpBinder中寻找实现代码:
frameworks/base/libs/binder/BpBinder.cpp

  1. status_t BpBinder::transact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
  2. {
  3. IPCThreadState::self()->transact(mHandle, code, data, reply, flags);
  4. }

最后调用的IPCThreadState的transact()函数,IPCThreadState是专门提供通过Binder进程间通信的接口的。

  1. status_t IPCTheadState::transact(int32_t handle, uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
  2. {
  3. // 填充binder_transaction_data 结构体,写入到mOut中去
  4. writeTransactionData(BC_TRANSACTION, flags, handle, code, data, NULL);
  5.  
  6. // 调用talkWithDriver() 将mOut写到Binder驱动,并从Binder驱动读取mIn数据
  7. waitForResponse(reply);
  8. }

首先通过writeTransactionData函数来填充mOut结构体,mOut里面内容为:
 mOut.writeInt32(BC_TRANSACTION);
 mOut.write(&tr, sizeof(tr));
这里binder_transaction_data tr内容为:
 tr.target.handle = 0; // 表面是发往ServiceManager的
 tr.code = CHECK_SERVICE_TRANSACTION;
 tr.flags = 0;
tr.data内容为:
 data.writeInt32(IPCThreadState::self()->getStrictModePolicy() | STRICT_MODE_PENALTY_GATHER);
 data.writeString16("android.os.IServiceManager");
 data.writeString16("media.player");
根据前面Android开发之ServiceManager一章中我们分析,svcmgr_handler处理从句柄为0的Binder的请求:
strict_policy = bio_get_string32();
s = bio_get_string16(); // 就是上面的android.os.IServiceManager
s = bio_get_string16(); // 就是上面的 media.player
根据media.player遍历全局链表svclist找到相应的服务,调用bio_put_ref(reply, ptr) 返回目标Binder实体。

这个waitForResponse()函数是关键:

  1. status_t IPCThreadState::waitForResponse(Parcel* reply)
  2. {
  3. while(1) {
  4. talkWithDriver(); // 输入mOut 输出mIn
  5. cmd = mIn.readInt32();
  6. switch(cmd) {
  7. case BR_REPLY:
  8. {
  9. binder_transaction_data tr;
  10. mIn.read(&tr, sizeof(tr));
  11. if(reply) {
  12. reply->ipcSetDataReference(reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer),
  13. tr.data.size, reinterpret_cast<const size_t*>(tr.data.ptr.offsets),
  14. tr.offsets_size/sizeof(sizt_t), freeBuffer, this);
  15. } else {
  16. err = *static_cast<const status_t*>(tr.data.ptr.buffer);
  17. freeBuffer(NULL, reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer),
  18. tr.data.size, reinterpret_cast<const size_t*>(tr.data.ptr.offsets),
  19. tr.offsets_size/sizeof(sizt_t), freeBuffer, this)
  20. }
  21. }
  22. }
  23. }
  24. }
  25. 最后返回的是:return reply.readStrongBinder();进入到ParcelreadStrongBinder()函数
  26. sp<IBinder> Parcel::readStrongBinder() const
  27. {
  28. sp<IBinder> val;
  29. unflatten_binder(ProcessState::self(), *this, &val);
  30. return val;
  31. }
  32. status_t unflatten_binder(const sp<ProcessState>& proc, const Parcel& in, sp<IBinder>* out)
  33. {
  34. const flat_binder_object* flat = in.readObject(false);
  35. if(flat) {
  36. switch(flat->type) {
  37. case BINDER_TYPE_BINDER:
  38. *out = static_cast<IBinder*>(flat->cookie);
  39. return finish_unflatten_binder(NULL, *flat, in);
  40. case BINDER_TYPE_HANDLE:
  41. *out = proc->getStrongProxyForHandle(flat->handle);
  42. return finish_unflatten_binder(static_cast<BpBinder*>(out->get()), *flat, in);
  43. }
  44. }
  45. }

这里flat->type是BINDER_TYPE_HANDLE,所以调用ProcessState::getStrongProxyForHandle()函数

  1. sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)
  2. {
  3. sp<IBinder> result;
  4.  
  5. handle_entry* e = lookupHandleLocked(handle);
  6. if(e != NULL) {
  7. IBinder* b = e->binder;
  8. if(b == NULL || !e->refs->attemptIncWeak(this)) {
  9. b = new BpBinder(handle);
  10. e->binder = b;
  11. if( b ) e->refs = e->getWeakRefs();
  12. result = b;
  13. } else {
  14. result.force_set(b);
  15. e->refs->decWeak(this);
  16. }
  17. }
  18. return result;
  19. }

这里的handle就是ServiceManager内维护的MediaPlayerService对应的Binder句柄,这个ProcessState根据这个句柄
new 了一个BpBinder,并将其保存起来,这样下次需要从ServiceManager请求获取到相同句柄的时候就可以直接返回了。
最后根据这个返回的BpBinder获得MediaPlayerService的代理:
sMediaPlayerService = interface_cast<IMediaPlayerService>(binder);
根据前面ServiceManager一样,最后调用的是IMediaPlayerService的asInterface()宏函数

  1. android::sp<IMediaPlayerService> IMediaPlayerService::asInterface(const android::sp<android::IBinder>& obj)
  2. {
  3. android::sp<IMediaPlayerService> intr;
  4. if(obj != NULL ) {
  5. intr = static_cast<IMediaPlayerService>(
  6. obj->queryLocalInterface(IMediaPlayerService::descriptor).get);
  7. if (intr == NULL) {
  8. intr = new BpMediaPlayerService(obj);
  9. }
  10. }
  11. return intr;
  12. }

这样我就获得了一个代理BpMediaPlayerService对象,它的remote()为BpBinder(handle),这个handle就是向服务总共ServiceManager
查询到的MediaPlayerService对应的Binder句柄。

下一章我们分析,客户端如何通过这个BpServiceManager代理对象调用服务端MediaPlayerService的业务函数的?

[置顶] Android开发之MediaPlayerService服务详解(一)的更多相关文章

  1. [置顶] Android开发之serviceManager分析

    Android 开发之serviceManager分析 在Android系统中用到最多的通信机制就是Binder,Binder主要由Client.Server.ServiceManager和Binde ...

  2. [置顶] Android开发之XML文件的解析

    Android系统开发之XML文件的解析 我们知道Http在网络传输中的数据组织方式有三种分别为:XML方式.HTML方式.JSON方式.其中XML为可扩展标记语言,如下: <?xml vers ...

  3. Android开发之EditText属性详解

    1.EditText输入的文字为密码形式的设置 (1)通过.xml里设置: 把该EditText设为:android:password="true" // 以”.”形式显示文本 ( ...

  4. 【转】 Android开发之EditText属性详解

    原文网址:http://blog.csdn.net/qq435757399/article/details/7947862 1.EditText输入的文字为密码形式的设置 (1)通过.xml里设置: ...

  5. [置顶] Android开发之ProcessState和IPCThreadState类分析

    在Android中ProcessState是客户端和服务端公共的部分,作为Binder通信的基础,ProcessState是一个singleton类,每个 进程只有一个对象,这个对象负责打开Binde ...

  6. [置顶] Android开发之Thread类分析

    在我们Linux系统中创建线程函数为:pthread_create(),在Android中我们为线程封装了一个类Thread,实际调用的还是pthread_create() 当我们想创建线程的时候,只 ...

  7. android开发之onCreate( )方法详解

    这里我们只关注一句话:This is where you should do all of your normal static set up.其中我们只关注normal static,normal: ...

  8. Android开发之MediaRecorder类详解

    MediaRecorder类介绍: MediaRecorder类是Android sdk提供的一个专门用于音视频录制,一般利用手机麦克风采集音频,摄像头采集图片信息. MediaRecorder主要函 ...

  9. android开发之Parcelable使用详解

    想要在两个activity之间传递对象,那么这个对象必须序列化,android中序列化一个对象有两种方式,一种是实现Serializable接口,这个非常简单,只需要声明一下就可以了,不痛不痒.但是a ...

随机推荐

  1. Linux系统上安装Python

    1.下载Python安装包,官网下:http://www.python.org/getit/ http://jingyan.baidu.com/article/eae07827f7f2d01fec54 ...

  2. Selenium2Library系列 keywords 之 _SelectElementKeywords 之 unselect_from_list(self, locator, *items)

    def unselect_from_list(self, locator, *items): """Unselects given values from select ...

  3. vim中编码方式---不完整总结

    关于编码,总有很多故事,这里只是记录下暂时的东西. 1.关于查看文件的编码 在查看文件编码的时候,总是倾向于使用file来进行查看,然而使用file命令的时候,并没有什么卵用: 在查看细节的时候,可以 ...

  4. ps 图片提取线稿方法2种 转

  5. BITED-Windows8应用开发学习札记之一:Win8应用开发入门

    基于WinRT的Metro应用是我对Windows8的第一印象,简洁方块配以简单色调真的有沁人心脾的美感. 非常幸运,BITED在这个暑假的这个小学期里有幸学习到一门课程:软件工程基础实践,老师邀请了 ...

  6. phpcms学习总结

    文件目录结构 根目录 | – api 接口文件目录 | – caches 缓存文件目录 | – configs 系统配置文件目录 | – caches_* 系统缓存目录 | – phpcms phpc ...

  7. 【转】Struts2中的MethodFilterInterceptor(转)

    这是一个Struts2.1.8.1应用,代码如下 首先是web.xml文件 view plaincopy to clipboardprint?01.<?xml version="1.0 ...

  8. java 编写hadoop程序中使用第三方libxx.so库

    在使用java编写hadoop处理程序时遇到了,java使用依赖的第三方libxx.so库的情况,找到了一种可行的方法,记录一下,希望对别人也有帮助: 加入需要使用的lib库为libxxx.so 1. ...

  9. 把数组A的奇数放在左边,偶数放在右边

    这也是一道面试题,是不是easy到爆,但是渣渣我面试时一点算法状态都没有 这道题和上一篇博客里那道题的解法一模一样 # include <iostream> using namespace ...

  10. REST四种请求(get,delete,put,post) 收集整理 之一

    转自:http://blog.csdn.net/cloudcraft/article/details/10087033 资源是REST中最关键的抽象概念,它们是能够被远程访问的应用程序对象.一个资源就 ...