Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1462895
  • 博文数量: 267
  • 博客积分: 3010
  • 博客等级: 少校
  • 技术积分: 3089
  • 用 户 组: 普通用户
  • 注册时间: 2011-06-05 17:09
个人简介

尊天命,尽人事

文章分类

全部博文(267)

文章存档

2017年(6)

2015年(4)

2014年(27)

2013年(52)

2012年(59)

2011年(120)

分类: C/C++

2012-10-29 11:40:24

研究了android binder 有两天了,感觉这是一个简单易用的东西,也许以后在非android的应用环境中也可以使用这种IPC方案,所以把一些学习记录下来,以将来备用.

   今天主要是实现了一个简单的c++ service服务程序,客户端通过binder呼叫服务上的,已经注册的接口函数。并在客户端实现了一个callback接口。

   关于callback的接口这个例子只是一个简单的实现。估计以后实际使用中还有变数。

   关于callback接口的一些想法

   a. 现有测试程序中的client端并没有启动 IPCThreadState的joinThreadPool 函数

   b. 现有测试程序中的client端并没有启动 ProcessState 的startThreadPool 函数

   c. 现有测试程序中的client端的callback触发,是通过client主动调用service端的一个函数.在这个函数内回调,之前注册的callback接口中的函数,实现的。

   d. 现在这种模式的测试通过,说明了service和client是可以双向沟通的

   e. 将来的实现模式中,如果service端在需要时主动callback回来,估计client 端就需要启动

      startThreadPool 函数了,至于   joinThreadPool 我目前的看法是没必要启动的。因为只要有了threadpool 客户端就可以实现服务了,当然,client端可不能随便退出来,至少退出来前要通知service端,自己已经退出,要不service端回调回来可就找不到北了.

   以下贴出代码,以备后用:

   一. 编写一个公用的动态库 libITestBinderInterface01

   这个动态库为service端和client端共用。

1.Android.mk

  1. LOCAL_PATH:= $(call my-dir)
  2. include $(CLEAR_VARS)
  3. LOCAL_SRC_FILES:= \
  4.  TestBinderInterface01.cpp \
  5.  ITestBinderInterface01.cpp
  6. base := /mnt/usbdisk/infoDroid2.2-1.8/infodroid-2.2/infodroid/frameworks/base/include
  7. LOCAL_C_INCLUDES := \
  8.   $(JNI_H_INCLUDE) \
  9.  $(base)
  10. LOCAL_SHARED_LIBRARIES := \
  11.     libutils \
  12.  liblog \
  13.  libbinder

  14. LOCAL_PRELINK_MODULE := false
  15. LOCAL_MODULE := libITestBinderInterface01
  16. include $(BUILD_SHARED_LIBRARY)
二.动态库的实现
ITestBinderInterface01.h

  1. #ifndef ITESTBINDERINTERFACE01_H
  2. #define ITESTBINDERINTERFACE01_H
  3. #include <utils/RefBase.h>
  4. #include <binder/IInterface.h>
  5. #include <binder/Parcel.h>
  6. #include <binder/IMemory.h>
  7. namespace android {
  8. //call back interface ,call by service
  9. class ITestBinderInterface01_CB : public IInterface
  10. {
  11.  public:
  12.     enum {
  13.         CALLBACK01 = IBinder::FIRST_CALL_TRANSACTION,
  14.   CALLBACK02
  15.     };
  16. public:
  17.     DECLARE_META_INTERFACE(TestBinderInterface01_CB);
  18.     virtual void notifyCallback01(int32_t msgType, int32_t ext1, int32_t ext2) = 0; //call from service
  19.     virtual void notifyCallback02(int32_t msgType, const sp<IMemory>& pmem) = 0; //test IMemory interface todo
  20. };
  21. class ITestBinderInterface01 : public IInterface
  22. {
  23. public:
  24.     enum {
  25.         SETCALLBACK = IBinder::FIRST_CALL_TRANSACTION,
  26.   ADD,
  27.   CALLBACKTEST
  28.     };
  29. public:
  30.     DECLARE_META_INTERFACE(TestBinderInterface01);
  31.     virtual int InitParam(const sp<ITestBinderInterface01_CB>& callback) = 0; //init parameter
  32.     virtual int Add(int a,int b) = 0; //return a+b
  33.     virtual int CallbackTest() = 0; //force callback
  34. };
  35. class BnTestBinderInterface01: public BnInterface<ITestBinderInterface01>
  36. {
  37. private:
  38. protected:
  39. public:
  40.     virtual status_t onTransact( uint32_t code,
  41.                                     const Parcel& data,
  42.                                     Parcel* reply,
  43.                                     uint32_t flags = 0);
  44. };
  45. class BnTestBinderInterface01_CB: public BnInterface<ITestBinderInterface01_CB>
  46. {
  47. private:
  48. protected:
  49. public:
  50.     virtual status_t onTransact( uint32_t code,
  51.                                     const Parcel& data,
  52.                                     Parcel* reply,
  53.                                     uint32_t flags = 0);
  54. };
  55. }; //namespace
  56. #endif
ITestBinderInterface01.cpp

  1. #include <stdint.h>
  2. #include <sys/types.h>
  3. #include <binder/Parcel.h>
  4. #include <binder/IPCThreadState.h>
  5. #include <binder/IServiceManager.h>
  6. #include "ITestBinderInterface01.h"
  7. namespace android {
  8. class BpTestBinderInterface01: public BpInterface<ITestBinderInterface01>
  9. {
  10. public:
  11.     BpTestBinderInterface01(const sp<IBinder>& impl)
  12.         : BpInterface<ITestBinderInterface01>(impl)
  13.     {
  14.     }
  15.     virtual int InitParam(const sp<ITestBinderInterface01_CB>& callback) //init parameter
  16.  {
  17.   Parcel data, reply;
  18.   // data.writeInterfaceToken(ITestBinderInterface01::getInterfaceDescriptor()); //why do that?? todo
  19.         data.writeStrongBinder(callback->asBinder());
  20.         remote()->transact(ITestBinderInterface01::SETCALLBACK, data, &reply);
  21.   return (reply.readInt32());
  22.  }
  23.  virtual int Add(int a,int b) //return a+b
  24.  {
  25.   Parcel data, reply;
  26.  // data.writeInterfaceToken(ITestBinderInterface01::getInterfaceDescriptor()); //why do that?? todo
  27.         data.writeInt32(a);
  28.         data.writeInt32(b);
  29.         remote()->transact(ITestBinderInterface01::ADD, data, &reply);
  30.   return (reply.readInt32());
  31.  }
  32.  virtual int CallbackTest() //force callback
  33.  {
  34.   Parcel data, reply;
  35.  // data.writeInterfaceToken(ITestBinderInterface01::getInterfaceDescriptor()); //why do that?? todo
  36.         remote()->transact(ITestBinderInterface01::CALLBACKTEST, data, &reply);
  37.   return (reply.readInt32());
  38.  }
  39. };
  40. IMPLEMENT_META_INTERFACE(TestBinderInterface01, "android.hardware.ITestBinderInterface01");

  41. class BpTestBinderInterface01_CB: public BpInterface<ITestBinderInterface01_CB>
  42. {
  43. public:
  44.     BpTestBinderInterface01_CB(const sp<IBinder>& impl)
  45.         : BpInterface<ITestBinderInterface01_CB>(impl)
  46.     {
  47.     }
  48.     virtual void notifyCallback01(int32_t msgType, int32_t ext1, int32_t ext2)
  49.  {
  50.   Parcel data, reply;
  51. // data.writeInterfaceToken(ITestBinderInterface01_CB::getInterfaceDescriptor()); //why do that?? todo
  52.         data.writeInt32(msgType);
  53.   data.writeInt32(ext1);
  54.   data.writeInt32(ext2);
  55.         remote()->transact(ITestBinderInterface01_CB::CALLBACK01, data, &reply);
  56.  }
  57.  virtual void notifyCallback02(int32_t msgType, const sp<IMemory>& pmem) //return a+b
  58.  {
  59.   Parcel data, reply;
  60. // data.writeInterfaceToken(ITestBinderInterface01_CB::getInterfaceDescriptor()); //why do that?? todo
  61.         data.writeInt32(msgType);
  62.   data.writeStrongBinder(pmem->asBinder());
  63.         remote()->transact(ITestBinderInterface01_CB::CALLBACK02, data, &reply);
  64.  }
  65. };
  66. IMPLEMENT_META_INTERFACE(TestBinderInterface01_CB, "android.hardware.TestBinderInterface01_CB");

  67. // ----------------------------------------------------------------------
  68. status_t BnTestBinderInterface01::onTransact(
  69.     uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
  70. {
  71.     switch(code) {
  72.         case SETCALLBACK: {
  73.    sp<ITestBinderInterface01_CB> callback = interface_cast<ITestBinderInterface01_CB>(data.readStrongBinder());
  74.    reply->writeInt32(InitParam(callback));
  75.             return NO_ERROR;
  76.         } break;
  77.   case ADD: {
  78.    int a = data.readInt32();
  79.    int b = data.readInt32();
  80.    reply->writeInt32(Add(a,b));
  81.             return NO_ERROR;
  82.         } break;
  83.   case CALLBACKTEST: {
  84.    reply->writeInt32(CallbackTest());
  85.             return NO_ERROR;
  86.         } break;
  87.         default:
  88.             return BBinder::onTransact(code, data, reply, flags);
  89.     }
  90. }

  91. status_t BnTestBinderInterface01_CB::onTransact(
  92.     uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
  93. {
  94.     switch(code) {
  95.         case CALLBACK01: {
  96.             int32_t msgType = data.readInt32();
  97.             int32_t ext1 = data.readInt32();
  98.             int32_t ext2 = data.readInt32();
  99.             notifyCallback01(msgType, ext1, ext2);
  100.             return NO_ERROR;
  101.         } break;
  102.   case CALLBACK02: {
  103.    int32_t msgType = data.readInt32();
  104.             sp<IMemory> pmem = interface_cast<IMemory>(data.readStrongBinder());
  105.             notifyCallback02(msgType, pmem);
  106.    return NO_ERROR;
  107.         } break;
  108.   
  109.         default:
  110.             return BBinder::onTransact(code, data, reply, flags);
  111.     }
  112. }
  113. // ----------------------------------------------------------------------------
  114. }; // namespace android
TestBinderInterface01.h

点击(此处)折叠或打开

  1. #ifndef TESTBINDERINTERFACE01_H
  2. #define TESTBINDERINTERFACE01_H
  3. #include "ITestBinderInterface01.h"
  4. namespace android {
  5.  class TestBinderInterface01 : public BnTestBinderInterface01
  6.  {
  7.  public:
  8.   static void instantiate();
  9.   virtual int InitParam(const sp<ITestBinderInterface01_CB>& callback) ; //init parameter
  10.   virtual int Add(int a,int b) ; //return a+b
  11.   virtual int CallbackTest() ; //force callback
  12.        
  13.  private:
  14.   TestBinderInterface01();
  15.   sp<ITestBinderInterface01_CB> _callback;
  16.  public:
  17.   virtual ~TestBinderInterface01();
  18.  };
  19.  class TestBinderInterface01_CB : public BnTestBinderInterface01_CB
  20.  {
  21.  public:
  22.   virtual void notifyCallback01(int32_t msgType, int32_t ext1, int32_t ext2); //call from service
  23.   virtual void notifyCallback02(int32_t msgType, const sp<IMemory>& pmem) ; //test IMemory interface todo
  24.  public:
  25.   TestBinderInterface01_CB();
  26.   virtual ~TestBinderInterface01_CB();
  27.  };
  28. }; // namespace android
  29. #endif
  30. //---------------------------------------------------------------------
TestBinderInterface01.cpp

  1. #define LOG_TAG "TestBinderInterface01"
  2. #include <utils/Log.h>
  3. #include <binder/IServiceManager.h>
  4. #include <binder/IPCThreadState.h>
  5. #include <utils/String16.h>
  6. #include <utils/Errors.h>
  7. #include <binder/MemoryBase.h>
  8. #include <binder/MemoryHeapBase.h>
  9. #include <ui/Overlay.h>
  10. #include <hardware/hardware.h>
  11. #include "TestBinderInterface01.h"
  12. #include <cutils/atomic.h>
  13. namespace android {
  14. extern "C" {
  15. #include <stdio.h>
  16. #include <sys/types.h>
  17. #include <sys/stat.h>
  18. #include <fcntl.h>
  19. #include <pthread.h>
  20. #include <signal.h>
  21. #include <sys/ioctl.h>
  22. }

  23. void TestBinderInterface01::instantiate() {
  24.     defaultServiceManager()->addService(
  25.             String16("kali.testbinder01"), new TestBinderInterface01);
  26. }
  27. TestBinderInterface01::TestBinderInterface01() :
  28.     BnTestBinderInterface01()
  29. {
  30.     LOGI("TestBinderInterface01 started: pid=%d", getpid());
  31. }
  32. TestBinderInterface01::~TestBinderInterface01()
  33. {

  34. }
  35. int TestBinderInterface01::InitParam(const sp<ITestBinderInterface01_CB>& callback)
  36. {
  37.  _callback = callback;
  38.     printf("[service] InitParam pid=%d,tid=%d\n",getpid(),gettid());
  39.     return 0;
  40. }
  41. int TestBinderInterface01::Add(int a,int b)
  42. {
  43.     printf("[service] Add a=%d,b=%d pid=%d,tid=%d\n",a,b,getpid(),gettid());
  44.  return (a+b);
  45. }
  46. int TestBinderInterface01::CallbackTest()
  47. {
  48.     printf("[service] CallbackTest pid=%d,tid=%d\n",getpid(),gettid());
  49.  if( _callback.get() )
  50.  {
  51.          printf("[service] call notifyCallback01 \n");
  52.   _callback->notifyCallback01(0, 1, 2);
  53.  }
  54.     return 0;
  55. }
  56. TestBinderInterface01_CB::TestBinderInterface01_CB()
  57. {
  58. }
  59. TestBinderInterface01_CB::~TestBinderInterface01_CB()
  60. {
  61. }
  62. void TestBinderInterface01_CB::notifyCallback01(int32_t msgType, int32_t ext1, int32_t ext2)
  63. {
  64.  printf("is call back01: msgType=%d,ext1=%d,ext2=%d pid=%d,tid=%d\n",msgType,ext1,ext2,getpid(),gettid());
  65. }
  66. void TestBinderInterface01_CB::notifyCallback02(int32_t msgType, const sp<IMemory>& pmem)
  67. {
  68.  printf("is call back02 pid=%d,tid=%d\n",getpid(),gettid());
  69. }
  70. };//namespace android
  71. //---------------------------------------------------------------------

好了。动态库libITestBinderInterface01 实现好了,mm一下就行了。

接下来实现一个测试用的service和client。Android.mk如下。把两个程序的编译写在一起方便些

testApp/Android.mk

点击(此处)折叠或打开

  1. # Copyright (C) 2008 The Android Open Source Project
  2. # #
  3. # # Licensed under the Apache License, Version 2.0 (the "License");
  4. # # you may not use this file except in compliance with the License.
  5. # # You may obtain a copy of the License at
  6. # #
  7. # # http://www.apache.org/licenses/LICENSE-2.0
  8. # #
  9. # # Unless required by applicable law or agreed to in writing, software
  10. # # distributed under the License is distributed on an "AS IS" BASIS,
  11. # # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. # # See the License for the specific language governing permissions and
  13. # # limitations under the License.

  14.  LOCAL_PATH := $(call my-dir)

  15. # HAL module implemenation, not prelinked and stored in
  16. # hw/<HWCURSOR_HARDWARE_MODULE_ID>.<ro.product.board>.so
  17. include $(CLEAR_VARS)
  18. LOCAL_PRELINK_MODULE := false
  19. LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT_SBIN)
  20. LOCAL_SHARED_LIBRARIES := liblog libcutils liblx_ipc libITestBinderInterface01
  21. #LOCAL_SHARED_LIBRARIES := lpthread libcutils libc

  22. LOCAL_SRC_FILES := main_BinderTestService.cpp
  23. LOCAL_MODULE := BinderTestService
  24. #LOCAL_CFLAGS:= -DLOG_TAG="hwcursor"
  25. include $(BUILD_EXECUTABLE)
  26. #client
  27. include $(CLEAR_VARS)
  28. LOCAL_PRELINK_MODULE := false
  29. LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT_SBIN)
  30. LOCAL_SHARED_LIBRARIES := liblog libcutils liblx_ipc libITestBinderInterface01
  31. #LOCAL_SHARED_LIBRARIES := lpthread libcutils libc

  32. LOCAL_SRC_FILES := main_BinderTestClient.cpp
  33. LOCAL_MODULE := BinderTestClient
  34. #LOCAL_CFLAGS:= -DLOG_TAG="hwcursor"
  35. include $(BUILD_EXECUTABLE)
简单的service端:
testApp/main_BinderTestService.cpp

点击(此处)折叠或打开

  1. #include <sys/types.h>
  2. #include <unistd.h>
  3. #include <grp.h>
  4. #include <binder/IPCThreadState.h>
  5. #include <binder/ProcessState.h>
  6. #include <binder/IServiceManager.h>
  7. #include <utils/Log.h>
  8. #include "../TestBinderInterface01.h"
  9. using namespace android;
  10. int main(int argc, char** argv)
  11. {
  12.    
  13.     sp<ProcessState> proc(ProcessState::self());
  14.     sp<IServiceManager> sm = defaultServiceManager();
  15.     printf("TestBinderInterface01 pid=%d,tid=%d, is running...\n",getpid(),gettid());
  16.     LOGI("ServiceManager: %p", sm.get());
  17.     TestBinderInterface01::instantiate();
  18.     ProcessState::self()->startThreadPool(); //启动线程池.这样binder驱动在需要时可以随时从驱动里返回 BR_SPAWN_LOOPER 让IPCThreadState类的executeCommand 函数响应,并可以执行case BR_SPAWN_LOOPER:mProcess->spawnPooledThread(false);break;看了半天才知道这个线程池是这么用的。不容易啊

  19.     IPCThreadState::self()->joinThreadPool(); //我试过,换成while(1) usleep(100); 一样可行,因为上面的threadpool已经启动了,驱动可以主要要求启线程了
  20. }
  21. //------------------------------------------------------------
testApp/main_BinderTestClient.cpp  一个简单的客户端

  1. #include <sys/types.h>
  2. #include <unistd.h>
  3. #include <grp.h>
  4. #include <binder/IPCThreadState.h>
  5. #include <binder/ProcessState.h>
  6. #include <binder/IServiceManager.h>
  7. #include <utils/Log.h>
  8. #include "../TestBinderInterface01.h"
  9. using namespace android;
  10. Mutex mLock;
  11. sp<ITestBinderInterface01> getTestService() {
  12.   Mutex::Autolock _l(mLock);
  13.   sp<ITestBinderInterface01> pTestService;
  14.         sp<IServiceManager> sm = defaultServiceManager();
  15.         sp<IBinder> binder;
  16.         do {
  17.             binder = sm->getService(String16("kali.testbinder01"));
  18.             if (binder != 0)
  19.                 break;
  20.             LOGW("kali.testbinder01 not published, waiting...");
  21.             usleep(500000); // 0.5 s
  22.         } while(true);
  23.        
  24.         pTestService = interface_cast<ITestBinderInterface01>(binder);
  25.     LOGE_IF(pTestService==0, "no FingerScanService!?");
  26.     return pTestService;
  27. }
  28. int main(int argc, char** argv)
  29. {
  30. // sp<ProcessState> proc(ProcessState::self());
  31.     sp<ITestBinderInterface01> pTestService = getTestService();
  32.     printf("[client] running pid=%d,tid=%d\n",getpid(),gettid());
  33.     printf("[client] call InitParam\n");
  34.     pTestService->InitParam(new TestBinderInterface01_CB());
  35.     printf("[client] call Add result =%d \n",pTestService->Add(10,20));

  36.     printf("[client] call CallbackTest\n");
  37.  pTestService->CallbackTest();
  38.     printf("[client] end\n");
  39.   // TestBinderInterface01::instantiate();
  40.   // ProcessState::self()->startThreadPool();
  41.   // IPCThreadState::self()->joinThreadPool();
  42. }

  1. mm 一下,生成
  2. BinderTestService
  3. BinderTestClient
  4. libITestBinderInterface01.so
  5. 运行
  6. BinderTestService &
  7. BinderTestClient &
  8. 输出结果如下:
  9. # ./BinderTestService &
  10. # TestBinderInterface01 pid=2503,tid=2503, is running...
  11. #
  12. # ./BinderTestClient &
  13. # [client] running pid=2506,tid=2506
  14. [client] call InitParam
  15. [service] InitParam pid=2503,tid=2504
  16. [service] Add a=10,b=20 pid=2503,tid=2505
  17. [client] call Add result =30
  18. [client] call CallbackTest
  19. [service] CallbackTest pid=2503,tid=2504
  20. [service] call notifyCallback01
  21. is call back01: msgType=0,ext1=1,ext2=2 pid=2506,tid=2506
  22. [client] end
不错,结果是想像中的那样。我好像对IMemory 这个接口还不太会用,这个接口从名字上来看,应该很有用,可以高效传输大内存块的.过两天有空了再学学
阅读(3562) | 评论(1) | 转发(0) |
给主人留下些什么吧!~~