Binder机制编程

前面的几篇文章详细介绍了android中binder机制的方方面面,相信你对binder机制已经有了较深刻的理解。俗话说得好“学以致用”,下面我们就通过在android系统中创建一个我们自己的binder服务,来加深对binder机制的理解。

(1)添加新建的服务名称

在service_manager.c文件中有一个结构数组allowed,在allowed结构体数组中加入新建的服务名称

static struct {
 unsigned uid;
 const char *name;
} allowed[] = {
#ifdef LVMX
 { AID_MEDIA, "com.lifevibes.mx.ipc" },
#endif
 { AID_MEDIA, "media.audio_flinger" },
 { AID_MEDIA, "media.player" },
 { AID_MEDIA, "media.camera" },
 { AID_MEDIA, "media.audio_policy" },
 { AID_RADIO, "radio.phone" },
 { AID_RADIO, "radio.sms" },
 { AID_RADIO, "radio.phonesubinfo" },
 { AID_RADIO, "radio.simphonebook" },
/* TODO: remove after phone services are updated: */
 { AID_RADIO, "phone" },
 { AID_RADIO, "isms" },
 { AID_RADIO, "iphonesubinfo" },
{ AID_RADIO, "simphonebook" },
  
{AID_NEW, "newservice"}
};
  

(2)定义ImyService类

定义一个继承自IInterface的接口类,须是以大写字母I开始,以IMyService为例接口函数必须为纯虚函数,以便在子类中生产,在定义接口时将DECLARE_META_INTERFACE宏放进接口类定义中,这个宏的最重要作用是将代理对象BpBinder转化成本地封装的服务代理对象(在这里是BpMyService对象),代码大致如下:

Class ImyService:public IInterface
{
Public:
 DECLARE_META_INTERFACE(MyService);
 
 Virtual fun1() = 0;
 Virtual fun2() = 0;
}

(3)定义一个本地实现类BnMyService

在IMyService.h头文件中定义接口实现类BnMyService, 需继承自BnInterface,间接双继承了IMyService接口类和BBinder类,代码如下:

Class BnMyService:public BnInterface<IMyService>
{
Public:
 Virtual status_t onTransact(uint32_t code,
 const Parcel& data,
 Parcel* reply,
 uint32_t flags = 0);
}

(4)定义本地代理类BpMyService

在IMyService.cpp源文件中,定义接口代理类BpMyService,需继承自BpInterface。BpMyService可以提供IMyService接口所定义的接口函数。

class BpMyService: public BpInterface<IMyService>
{
public:
 BpMyService(const sp<IBinder>& impl)
 : BpInterface<IMyService>(impl)
 {
}
void fun1()
 {
 Parcel data, reply;
 …… //数据写入
 remote()->transact(枚举量, data, &reply);
 return …… //数据返回
 }
……
}

(5)加入宏定义

在IMyService.cpp源文件中,加入宏定义IMPLEMENT_META_INTERFACE()

  
IMPLEMENT_META_INTERFACE(MyService, "XXX");
  

(6)定义BnMyService的onTransact()函数

在IMyService.cpp源文件中实现接口实现类BnMyService,其中onTrasact()函数根据功能代码枚举量的不同分别执行不同的功能调用。

status_t BnMyService::onTransact(
 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
 switch(code) { //code功能代码枚举量
 case功能代码枚举量: {
 LOGV("NOTIFY_CALLBACK");
 CHECK_INTERFACE(ICameraClient, data, reply); //检查描述符字符串
 …… //参数输入,接口函数功能的真正实现
 reply->……); //返回数据
 return NO_ERROR;
 } break;
……
default:
 return BBinder::onTransact(code, data, reply, flags);
}

(7)创建真正的本地接口实现类MyService类

在头文件中定义类MyService,继承自BnInterface,定义功能函数和初始化函数instantiate():

Class MyService:public BnMyService
{
Public:
 Static void instantiate();
 
 Virtual func1();
 Virtual func2();
 ……
}
  

(8)定义MyService::instantiate()函数

void MyService::instantiate() {
 defaultServiceManager()->addService(
 String16("newservice"), new MyService());
}
 

(9)服务进程中注册服务

在服务进程A初始化时加入MyService:: instantiate()函数,注册服务,调用joinThreadPool()函数进入循环等待调用,侦听请求、处理请求。

int main(int argc, char** argv)
{
 sp<ProcessState> proc(ProcessState::self());
 sp<IServiceManager> sm = defaultServiceManager();
 LOGI("ServiceManager: %p", sm.get());
 MyService::instantiate();
 ……
 ProcessState::self()->startThreadPool();
 IPCThreadState::self()->joinThreadPool();
}

(10)客户端获取服务代理对象

客户端进程B要想和服务端通讯,首先需要获取服务管家ServiceManager的代理对象,,然后查找服务,因为服务已经注册,所以会返回一个该服务代理对象的引用,此代理对象中包含一个指向查找的服务的handle句柄。

const sp<IMyService>& MyServiceSystem::get_MyService()
{
 Mutex::Autolock _l(mLock);
 if (gMyService.get() == 0) {
 sp<IServiceManager> sm = defaultServiceManager(); //获取服务管家的代
//理对象
 sp<IBinder> binder;
 do {
 binder = sm->getService(String16("newservice")); //查找到服务后,
//返回服务的代理对象
 ……
 } while(true);
 ……
 gMyService = interface_cast<IMyService>(binder); //将其转换为本地服
//务代理对象(BpMyService)
 ……
 }
 ……
 return mMyService;
}

(11)客户端调用服务端函数

客户端进程B调用IMyService的接口函数,调用会传递给包含了服务对象handle的代理对象BpBinder,写入binder内核驱动。binder驱动知道数据传递到的对象,于是将数据传递给进程A。

服务端进程A从binder驱动中读取数据,然后处理远程调用,然后发送reply数据给binder驱动。binder驱动将reply传递给客户端进程B。进程B从binder驱动中读取数据并最终获取到reply,从而完成进程通信。

Status_t MyServiceSystem::func1()
{
 Const sp<IMyService>& af = MyServiceSystem::get_MyService();
 Af::Func1();
 ……
}

到这里,我们已经把android中的binder机制介绍完了。呵呵,本来觉得binder机制总结起来不会很难,可在写总结的过程中还是遇到了很多问题。呵呵,不过还好,都差不多一一解决了,终于写完了。总结过程中相当于又学了一边binder机制,而且还有新的收获,真的不错哦!

更多相关文章

  1. C语言函数的递归(上)
  2. Android和j2me的初级对比
  3. Android(安卓)序列化对象接口Parcelable使用方法
  4. 用Kotlin实现Android点击事件
  5. Android应用框架之应用启动过程详解
  6. Android(安卓)gradle编译指令(implementation、api、provided 等)
  7. TextView支持的HTML标签及其他
  8. Android(安卓)ListView拖动时背景颜色会变成黑色的解决办法
  9. android屏幕监控上下左右滑动

随机推荐

  1. 使用Docker Compose部署SpringBoot应用
  2. IPython高级用法及注意事项
  3. React DnD
  4. 编程语言扎堆整容,Python成整容模板
  5. Electron webview完全指南
  6. 开发者必备Mysql命令
  7. 外行人都能看懂的SpringCloud,错过了血亏!
  8. 图说yield
  9. 开发者必备Linux命令
  10. 翻译社重大改版