一身转战三千里,一剑曾当百万师。这篇文章主要讲述android binder 基础实例及解析相关的知识,希望能为你提供帮助。
本文转载自:http://blog.csdn.net/newchenxf/article/details/49359283#insertcode
原文网址(转载请注明出处):
http://blog.csdn.net/newchenxf/article/details/49359283
众所周知,binder是android最难啃的骨头,本人深有体会,分析framework的代码很痛苦,搞不清函数到底怎么从一个进程调用到另一个进程。
所以,我不得不冷静一下,仔细分析binder到底怎么用,并写了一些sample code,作为实验。
网上已有各位大神对binder做深入分析,比如
【Android深入浅出之Binder机制】
http://www.cnblogs.com/innost/archive/2011/01/09/1931456.html
【Binder详解】
http://blog.csdn.net/yangzhiloveyou/article/details/14043801
【Android Binder机制(超级详尽)】
http://blog.csdn.net/coding_glacier/article/details/7520199
感谢他们的分享。
本文将提供一个最基础的binder例子,并对应的做分析,慢慢拨开binder的神秘面纱。
例子的目录结构。
Android.mk
client->
Android.mk, main_client.cpp)
interface->
IXXXXService.cpp, IXXXXService.h
server->
Android.mk, XXXXService.cpp, XXXXService.h, main_XXXXService.cpp
a) 第一步,定义接口 IXXXXService.h首先,要用binder,第一件事就是定义一个接口,把你想要做的事情(API)写在这个接口里。本例就2个,setSomething和getSomething。
#ifndef IXXXXService_H
#define IXXXXService_H #include <
binder/IInterface.h>
namespace android {
class IXXXXService : public IInterface {
public:
DECLARE_META_INTERFACE(XXXXService);
virtual int setSomething(int a) = 0;
virtual int getSomething() = 0;
};
class BnXXXXService : public BnInterface<
IXXXXService>
{
public:
virtual status_tonTransact( uint32_t code,
const Parcel&
data,
Parcel* reply,
uint32_t flags = 0);
};
}
#endif
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
IXXXXService,这个类必须继承IInterface,然后把你想要的API都写在这个接口里。谁会继承这个接口?有2个,一个是BpXXXXService,一个是BnXXXXService。
BnXXXXService。这个必须继承模板类BnInterface。
该模板的定义是
template<
typename INTERFACE>
class BnInterface : public INTERFACE, public BBinder
- 1
- 2
奇怪的是,为啥BnInterface 需要把它写在头文件,而BpXXXXService不用呢?因为BpXXXXService对别人是透明的,客户端甚至都不需要知道它的存在。那你就要问了,不知道存在的话,我还怎么new他?
其实android给你包好了,当你客户端调用interface_cast(*)时,就会帮你new BpXXXXService。
但BnXXXXService就不一样,还有真正的XXXXService必须继承BnXXXXService,从而去实现真正的API函数,所以就必须放在头文件。
没看明白没关系,后文会慢慢告诉你具体意思的。
继续,这个头文件最神秘的是DECLARE_META_INTERFACE,它定义在IInterface.h, 且看其定义。
#define DECLARE_META_INTERFACE(INTERFACE)\\
static const android::String16 descriptor;
\\
static android::sp<
I##INTERFACE>
asInterface(\\
const android::sp<
android::IBinder>
&
obj);
\\
virtual const android::String16&
getInterfaceDescriptor() const;
\\
I##INTERFACE();
\\
virtual ~I##INTERFACE();
\\
- 1
- 2
- 3
- 4
- 5
- 6
- 7
static const android::String16 descriptor;
static android::sp<
IXXXXService>
asInterface(
const android::sp<
android::IBinder>
&
obj);
virtual const android::String16&
getInterfaceDescriptor() const;
IXXXXService();
virtual ~IXXXXService();
- 1
- 2
- 3
- 4
- 5
- 6
根据定义,我们可以总结,IXXXXService有如下几个函数。
setSomething
getSomething
asInterface
getInterfaceDescriptor。
还有个静态变量descriptor,这个不管是派生类BpXXXXService还是派生类BnXXXXService,都一样的。
b) 第二步,IXXXXServie.cpp这个文件主要实现BpXXXXService和BnXXXXService
#include "IXXXXService.h"
#include <
binder/Parcel.h>
#include <
binder/IInterface.h>
#include <
utils/Log.h>
#define LOG_NDEBUG 0
#define LOG_TAG "chenxf: IXXXXService"namespace android {enum {
SET_SOMETHING = IBinder::FIRST_CALL_TRANSACTION,
GET_SOMETHING,
};
//------------------------------------proxy side--------------------------------class BpXXXXService : public BpInterface<
IXXXXService>
{
public:
BpXXXXService(const sp<
IBinder>
&
impl)
: BpInterface<
IXXXXService>
(impl) {
}
virtual int setSomething(int a) {
ALOGD(" BpXXXXService::setSomething a = %d ", a);
Parcel data,reply;
data.writeInt32(a);
remote()->
transact(SET_SOMETHING,data,&
reply);
return reply.readInt32();
}
virtual int getSomething() {
ALOGD(" BpXXXXService::getSomething ");
Parcel data,reply;
data.writeInterfaceToken(IXXXXService::getInterfaceDescriptor());
remote()->
transact(GET_SOMETHING,data,&
reply);
return reply.readInt32();
}
};
//---------------------- interface--------------------
IMPLEMENT_META_INTERFACE(XXXXService, "chenxf.binder.IXXXXService");
//------------------------------------server side--------------------------------
status_t BnXXXXService::onTransact (
uint32_t code, const Parcel&
data, Parcel* reply, uint32_t flags){
switch (code) {
case SET_SOMETHING: {
ALOGD("BnXXXXService::onTransactSET_SOMETHING ");
reply->
writeInt32(setSomething((int) data.readInt32()));
return NO_ERROR;
} break;
case GET_SOMETHING: {
ALOGD("BnXXXXService::onTransactGET_SOMETHING ");
reply->
writeInt32(getSomething());
return NO_ERROR;
} break;
}
return BBinder::onTransact(code, data, reply, flags);
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
来看一下他的定义(IInterface.h)
#define IMPLEMENT_META_INTERFACE(INTERFACE, NAME)\\
const android::String16 I##INTERFACE::descriptor(NAME);
\\
const android::String16&
\\
I##INTERFACE::getInterfaceDescriptor() const {\\
return I##INTERFACE::descriptor;
\\
}\\
android::sp<
I##INTERFACE>
I##INTERFACE::asInterface(\\
const android::sp<
android::IBinder>
&
obj)\\
{\\
android::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;
\\
}\\
I##INTERFACE::I##INTERFACE() { }\\
I##INTERFACE::~I##INTERFACE() { }\\
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
const android::String16 IXXXXService::descriptor("chenxf.binder.IXXXXService");
const android::String16&
IXXXXService::getInterfaceDescriptor() const {
return IXXXXService::descriptor;
}
android::sp<
IXXXXService>
IXXXXService::asInterface(
const android::sp<
android::IBinder>
&
obj)
{
android::sp<
IXXXXService>
intr;
if (obj != NULL) {
intr = static_cast<
IXXXXService>
(
obj->
queryLocalInterface(
IXXXXService::descriptor).get());
if (intr == NULL) {
intr = new BpXXXXService(obj);
}
}
return intr;
}
IXXXXService::IXXXXService() { }
IXXXXService::~IXXXXService() { }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
此外,函数asInterface会实现new BpXXXXService。
这个文件还实现了BnXXXXService的onTransact函数。这个函数主要就是处理proxy发来的调用。比如proxy发了想要调用服务端的setSomething函数,它发起了
remote()-> transact(SET_SOMETHING,data,& reply);
那么,经过binder驱动,将会回调到onTransact。这个函数只负责把客户的需求处理,比如,如果是SET_SOMETHING,那就执行
setSomething((int) data.readInt32())
至于setSomething要做什么,那么就不关BnXXXXService的事了,它还是有虚函数setSomething,所以可以预知肯定有别的派生类要继承并实现它。那就是传说中的XXXXService。
c) 第三步,XXXXService.h【android binder 基础实例及解析】这是XXXXService的头文件,主要就是声明XXXXService,继承BnXXXXService。
#include "../interface/IXXXXService.h"
#include <
binder/BinderService.h>
namespace android {
class XXXXService : public BinderService<
XXXXService>
, public BnXXXXService {
public:
XXXXService();
static const char* getServiceName() { return "XXXXService";
}//will be the service name
virtual int setSomething(int a);
virtual int getSomething();
protected:
int myParam;
};
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
既然要继承BinderService,那就要写一个getServiceName函数,其返回值就是该服务注册到ServiceManager的名字。
d) 第四步,XXXXService.cpp这就要具体实现说好的setSomething和getSomething函数了。
本例比较简单,调用过来,就加1,如果你有需要,可以做更多事情。
#include <
binder/IPCThreadState.h>
#include <
binder/IServiceManager.h>
#include <
utils/Log.h>
#include <
binder/Parcel.h>
#include <
binder/IPCThreadState.h>
#include <
utils/threads.h>
#include <
cutils/properties.h>
#include "XXXXService.h"
#define LOG_NDEBUG 0
#define LOG_TAG "chenxf: XXXXService"namespace android {
XXXXService::XXXXService() {
myParam = 0;
}int XXXXService::setSomething(int a) {
ALOGD(" XXXXService::setSomething a = %d myParam %d", a, myParam);
myParam += a;
return 0;
//OK
}
int XXXXService::getSomething() {
ALOGD("#XXXXService::getSomething myParam = %d", myParam);
return myParam;
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
1. 一个标准的接口,IXXXXService;
代理端的实现BpXXXXService。对他来说,他继承了IXXXXService接口的函数,比如setSomething,但对他来说,实现这个接口主要就是传输调用remote()-> transact(….),告诉服务程序有这么一个请求调用。
2. 服务端的中间实现BnXXXXService。对他来说,继承了模板类BnInterace,相当于继承了IXXXXService和BBinder,但不去实现IXXXXService的函数,而主要实现BBinder的onTransact函数,用于处理刚才说的remote()-> transact(….)。
3. 服务端的真正实现XXXXService。他继承了BnXXXXService和BinderService。并且会实现接口的函数,比如setSomething。
请注意,BpXXXXService实现的setSomething和XXXXService实现的setSomething没有直接关系喔,他们属于不同的进程,而且各自实现该函数。BpXXXXService的setSomething主要是传递个消息,告诉binder驱动,有这么一个事情要办,binder驱动会告诉服务进程,有人找上门了,要setSomething,麻烦XXXXService去做一下。
d) 第五步,main_XXXXService.cpp开始服务进程,启动XXXXService,并注册到ServiceManager,让所有人都可以找到他.
既然我们都写好了XXXXService,那总得有人new他吧?那必须的。
我们写一个main,起一个新的进程,该进程会new XXXXService,并注册到ServiceManager。
#include <
binder/IPCThreadState.h>
#include <
binder/ProcessState.h>
#include <
binder/IServiceManager.h>
#include <
utils/Log.h>
#include "XXXXService.h"
#define LOG_NDEBUG 0
#define LOG_TAG "chenxf: XXXXService-main"#define EASY_START_BINDER_SERVICE 0using namespace android;
int main(int argc, char** argv)
{
#if EASY_START_BINDER_SERVICE
XXXXService::publishAndJoinThreadPool();
//使用了父类BinderService的函数
#else
sp<
ProcessState>
proc(ProcessState::self());
sp<
IServiceManager>
sm(defaultServiceManager());
sm->
addService(String16(XXXXService::getServiceName()), new XXXXService());
ProcessState::self()->
startThreadPool();
IPCThreadState::self()->
joinThreadPool();
#endifreturn 0;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
//BinderService
static void publishAndJoinThreadPool(bool allowIsolated = false) {
publish(allowIsolated);
joinThreadPool();
}static status_t publish(bool allowIsolated = false) {
sp<
IServiceManager>
sm(defaultServiceManager());
return sm->
addService(
String16(SERVICE::getServiceName()),
new SERVICE(), allowIsolated);
//SERVICE是模板,对本例来说,就是XXXXService
}static void joinThreadPool() {
sp<
ProcessState>
ps(ProcessState::self());
ps->
startThreadPool();
ps->
giveThreadPoolName();
IPCThreadState::self()->
joinThreadPool();
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
5.1) sp proc(ProcessState::self())
请看定义:
sp<
ProcessState>
ProcessState::self()
{
Mutex::Autolock _l(gProcessMutex);
if (gProcess != NULL) {
return gProcess;
}
gProcess = new ProcessState;
return gProcess;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
这个ProcessState干了一个最重要的事情,那就是打开binder驱动。
请看其构造函数。
ProcessState::ProcessState()
: mDriverFD(open_driver())
, mVMStart(MAP_FAILED)
, mManagesContexts(false)
, mBinderContextCheckFunc(NULL)
, mBinderContextUserData(NULL)
, mThreadPoolStarted(false)
, mThreadPoolSeq(1)
{
......
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
static int open_driver()
{
int fd = open("/dev/binder", O_RDWR);
if (fd >
= 0) {
......
size_t maxThreads = 15;
result = ioctl(fd, BINDER_SET_MAX_THREADS, &
maxThreads);
if (result == -1) {
ALOGE("Binder ioctl to set max threads failed: %s", strerror(errno));
}
} else {
ALOGW("Opening \'/dev/binder\' failed: %s\\n", strerror(errno));
}
return fd;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
5.2) sp sm(defaultServiceManager())
这个其实没话说啦,就是获得ServiceManager的客户端,其实本进程和ServiceManager通信,也是用binder,一样是client/server模式。
5.3) sm-> addService(String16(XXXXService::getServiceName()), new XXXXService())
很明显,实例化了XXXXService,并且注册到ServiceManager,名字就是刚才在XXXXService.h强调要写的getServiceName的返回值。本例设置的名字就是“XXXXService”。别的进程要找到它,只要找ServiceManager,告诉ServiceManager需要一个名字叫“XXXXService”的服务员^_^。
5.4) ProcessState::self()-> startThreadPool()
恩,ProcessState::self()就是全局变量gProcess,刚才第一步已经初始化过啦。
所以其实第一步不做,也是可以的,只是咱为了代码清晰,还是写着吧。
void ProcessState::startThreadPool()
{
AutoMutex _l(mLock);
if (!mThreadPoolStarted) {
mThreadPoolStarted = true;
spawnPooledThread(true);
}
}//spawnPooledThread
void ProcessState::spawnPooledThread(bool isMain)
{
if (mThreadPoolStarted) {
String8 name = makeBinderThreadName();
ALOGV("Spawning new pooled thread, name=%s\\n", name.string());
sp<
Thread>
t = new PoolThread(isMain);
t->
run(name.string());
}
}
//makeBinderThreadName
String8 ProcessState::makeBinderThreadName() {
int32_t s = android_atomic_add(1, &
mThreadPoolSeq);
String8 name;
name.appendFormat("Binder_%X", s);
return name;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
这就是为啥,我们看android服务程序的某个服务程序,比如mediaserver,经常可以看到Binder_1等子线程。
#top -t | grep mediase
......
14458720% S 147108K11936Kfg mediaBinder_1/system/bin/mediaserver
- 1
- 2
- 3
我们知道,PoolThread继承了Thread,所以当执行run以后,将会threadLoop函数。
来看PoolThread的threadLoop函数。
// define in ProcessState.cpp
virtual bool threadLoop()
{
IPCThreadState::self()->
joinThreadPool(mIsMain);
return false;
}
- 1
- 2
- 3
- 4
- 5
- 6
5.5) IPCThreadState::self()-> joinThreadPool()
虽然说上一步也会调用,但我们还是分析一下他吧。
首先还是来个self()
IPCThreadState* IPCThreadState::self()
{
if (gHaveTLS) {
restart:
const pthread_key_t k = gTLS;
IPCThreadState* st = (IPCThreadState*)pthread_getspecific(k);
if (st) return st;
return new IPCThreadState;
}if (gShutdown) return NULL;
pthread_mutex_lock(&
gTLSMutex);
if (!gHaveTLS) {
if (pthread_key_create(&
gTLS, threadDestructor) != 0) {
pthread_mutex_unlock(&
gTLSMutex);
return NULL;
}
gHaveTLS = true;
}
pthread_mutex_unlock(&
gTLSMutex);
goto restart;
}
//constructor of IPCThreadState
IPCThreadState::IPCThreadState()
: mProcess(ProcessState::self()),
mMyThreadId(androidGetTid()),
mStrictModePolicy(0),
mLastTransactionBinderFlags(0)
{
pthread_setspecific(gTLS, this);
clearCaller();
mIn.setDataCapacity(256);
mOut.setDataCapacity(256);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
简单,看构造函数就知道,IPCThreadState的mProcess就是唯一的ProcessState实例。
好,继续看joinThreadPool
void IPCThreadState::joinThreadPool(bool isMain)
{
......
do {
processPendingDerefs();
// now get the next command to be processed, waiting if necessary
result = getAndExecuteCommand();
}} while (result != -ECONNREFUSED &
&
result != -EBADF);
}//getAndExecuteCommand
status_t IPCThreadState::getAndExecuteCommand()
{
status_t result;
int32_t cmd;
result = talkWithDriver();
if (result >
= NO_ERROR) {
size_t IN = mIn.dataAvail();
if (IN <
sizeof(int32_t)) return result;
cmd = mIn.readInt32();
IF_LOG_COMMANDS() {
alog <
<
"Processing top-level Command: "
<
<
getReturnString(cmd) <
<
endl;
}
result = executeCommand(cmd);
}return result;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
来看一下这个函数。
status_t IPCThreadState::executeCommand(int32_t cmd)
{
BBinder* obj;
RefBase::weakref_type* refs;
status_t result = NO_ERROR;
switch (cmd) {
case BR_TRANSACTION:
{
binder_transaction_data tr;
result = mIn.read(&
tr, sizeof(tr));
if (tr.target.ptr) {
p<
BBinder>
b((BBinder*)tr.cookie);
error = b->
transact(tr.code, buffer, &
reply, tr.flags);
}
......
}
return result;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
BBinder的transact函数。
status_t BBinder::transact(
uint32_t code, const Parcel&
data, Parcel* reply, uint32_t flags)
{
......
err = onTransact(code, data, reply, flags);
return err;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
注意BBinder的onTransact是虚函数,虽然他也实现了onTransact,但真正实现的是派生类XXXXService(继承关系:XXXXService-> BnXXXXService-> BnInterface-> BBinder)。所以呢,最后就调用了XXXXService的onTransact,也就是我们写在IXXXXService的onTransact。绕了半天,终于水落石出啦!
e) 第六步,main_client.cpp,客户端开始使用binder
#include <
stdio.h>
#include "../interface/IXXXXService.h"#define LOG_NDEBUG 0
#define LOG_TAG "chenxf: Client-main"using namespace android;
sp<
IXXXXService>
mXXXXService;
void initXXXXServiceClient() {
int count = 10;
if (mXXXXService == 0) {
sp<
IServiceManager>
sm = defaultServiceManager();
sp<
IBinder>
binder;
do {
binder = sm->
getService(String16("XXXXService"));
if (binder != 0)
break;
ALOGW("XXXXService not published, waiting...");
sleep(1);
// 1 s
count++;
} while (count <
20);
mXXXXService = interface_cast<
IXXXXService>
(binder);
}
}int main(int argc, char* argv[]) {
initXXXXServiceClient();
if(mXXXXService ==NULL) {
ALOGW("cannot find XXXXService");
return 0;
}while(1) {
mXXXXService->
setSomething(1);
sleep(1);
ALOGD("getSomething %d", mXXXXService->
getSomething());
}
return 0;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
首先,要用binder,就得找ServiceManager(sp sm = defaultServiceManager(); ),告诉他我们需要一个名字为XXXXService的服务员( binder = sm-> getService(String16(“XXXXService”)); )
这2句话看似简单,其实很深奥。
6.1 sp sm = defaultServiceManager()
sp<
IServiceManager>
defaultServiceManager()
{
if (gDefaultServiceManager != NULL) return gDefaultServiceManager;
{
AutoMutex _l(gDefaultServiceManagerLock);
while (gDefaultServiceManager == NULL) {
gDefaultServiceManager = interface_cast<
IServiceManager>
(
ProcessState::self()->
getContextObject(NULL));
if (gDefaultServiceManager == NULL)
sleep(1);
}
}return gDefaultServiceManager;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
6.2) binder = sm-> getService(String16(“XXXXService”)
由于服务端已经做过
sm-> addService(String16(XXXXService::getServiceName()), new XXXXService()),因此我们很容易就获得了service。
那返回的binder是啥?他其实是BpBinder实例。它是ServiceManager返回的,这个具体内容要说,又得说一天,而本文侧重实例,所以这里先给出结论,那就是返回的是一个BpBinder()。
6.3)mXXXXService = interface_cast(binder)
interface_cast是啥?他是一个函数模板,且看定义
//IInterface.h
template<
typename INTERFACE>
inline sp<
INTERFACE>
interface_cast(const sp<
IBinder>
&
obj)
{
return INTERFACE::asInterface(obj);
}
- 1
- 2
- 3
- 4
- 5
- 6
inline sp<
IXXXXService>
interface_cast(const sp<
IBinder>
&
obj)
{
return IXXXXService::asInterface(obj);
}
- 1
- 2
- 3
- 4
mXXXXService = IXXXXService::asInterface(binder)。
还记得前文第二步没,在IXXXXService.cpp里,加了个宏IMPLEMENT_META_INTERFACE,该宏实现了asInterface函数。
根据其定义,就是
mXXXXService = new BpXXXXService(binder)。
至此,我们终于完成任务了!
总结一个最最基本的binder程序写好了,结构还是很简单的。
我们来看一下,当客户端发起一个调用setSomething,程序会怎么走。
程序流程首先,咱有2个进程,一个是客户端进程,main_client.cpp,一个是服务端进程,main_XXXXService.cpp。
客户端进程:
1. 客户端调用mXXXXService-> setSomething(1)
2. 程序走到BpXXXXService的setSomething函数。
virtual int setSomething(int a) {
ALOGD(" BpXXXXService::setSomething a = %d ", a);
Parcel data,reply;
data.writeInt32(a);
remote()->
transact(SET_SOMETHING,data,&
reply);
return reply.readInt32();
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
remote()其实就是BpBinder实例。
3. 程序走到BpBinder的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;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
每个进程都有一个IPCThreadState实例,对client这个进程也一样。
通过他的transact函数,往binder驱动写数据。完事。
服务端进程:
1. 服务端的子线程通过执行executeCommand,不断的从binder驱动读取数据,如果发现是送给自己的,就处理数据,即执行了BBinder::transact,从而执行派生类BnXXXXService的onTransact。
2. BnXXXXService的onTransact分析数据,发现有人要调用setSomething(即发送代号是SET_SOMETHING),于是乎,解包Parcel拿出函数参数,调用setSomething,其具体实现在XXXXService。
3. XXXXService执行setSomething。完事。
ProcessState和IPCThreadState前文分析ProcessState和IPCThreadState有点乱,所以我这里再总结一下他们的关系。
每个进程只有唯一的ProcessState对象。客户端和服务端都有。
只要进程调用了defaultServiceManager(),就一定会调用到
ProcessState::self(),从而实例化ProcessState。
ProcessState实例来描述当前进程在binder通信时的binder状态。
ProcessState有如下3个主要功能:
1. 打开binder驱动。
2. 创建一个thread,名字为PoolThread,该线程负责与binder驱动进行通信;这个线程的实现主体是一个IPCThreadState对象。
3. 为指定的handle创建一个BpBinder对象,并管理该进程中所有的BpBinder对象。
那一个进程有几个IPCThreadState对象?
理论上至少有一个,那就是ProcessState启动PoolThread线程是创建的。但如果用于还在主进程调用了
IPCThreadState::self()-> joinThreadPool();
那就有2个对象,因为查看IPCThreadState::self()的定义,就知道他是线程独立的。
比如我们的server进程,执行了
ProcessState::self()-> startThreadPool();
IPCThreadState::self()-> joinThreadPool();
那必将有2个IPCThreadState对象。
但client进程,主进程或者没有任何子线程调用IPCThreadState::self()-> joinThreadPool()
因此只有一个IPCThreadState对象。
其实呢,咱一般就当做一个进程只有一个ProcessState和IPCThreadState吧。
IPCThreadState中有2个Parcel成员,mIn和mOut,IPCThreadState会不停的查询binder驱动中是否有数据可读,如果有将其读出并保存到mIn,同时不停的检查mOut是否有数据需要向BD发送,如果有,则将其内容写入到binder驱动中,总而言之,binder驱动中读出的数据保存到mIn,待写入到binder驱动中的数据保存在了mOut中。
ProcessState中生成的BpBinder实例通过调用IPCThreadState的transact函数来向IPCThreadState的mOut中写入数据,这样的话这个binder IPC过程的client端的调用请求的发送过程就明了了。
下图给出ProcessState与IPCThreadState在client进程和server进程的存在方式。
文章图片
由图中可知,对于client进程,IPCThreadState是主线程创建的,运行在主线程中。主线程将会调用其transact函数,而如上文所说,transact主要调用talkWithDriver,发送数据到driver,然后获得reply,由waitForResponse处理。
可见,对于client进程,并不需要起单独的线程不断的监听数据,毕竟,他只是client。
对于server进程,IPCThreadState是子线程PoolThread创建的。(假设咱main_XXXXService.cpp不写IPCThreadState::self()-> joinThreadPool())。
并且,子线程通过joinThreadPool函数,起一个while循环,不断的talkWithDriver,监听driver数据,有数据后,通过executeCommand处理,如果是有效数据,调用BBinder-> transact,进而调用BBidner-> onTransact,最后走到派生类BnXXXXService的onTransact。
client进程与server进程的关系说了这么多,总得给一个总框图吧。别人都是一开始给出,我就最后给出吧。^^
文章图片
测试结果程序都写好了,总得能跑对吧,恩,首先启动2个进程:
root@sprint:/ # test_binder_server &
[1] 2784
root@sprint:/ # test_binder_client &
[2] 2786
然后看log
root@sprint:/ # logcat -v threadtime
10-24 06:08:40.71127862786 D chenxf: IXXXXService:BpXXXXService::setSomething a = 1
10-24 06:08:40.71127842784 D chenxf: IXXXXService: BnXXXXService::onTransactSET_SOMETHING
10-24 06:08:40.71127842784 D chenxf: XXXXService:XXXXService::setSomething a = 1 myParam 0
10-24 06:08:41.71227862786 D chenxf: IXXXXService:BpXXXXService::getSomething
10-24 06:08:41.71227842785 D chenxf: IXXXXService: BnXXXXService::onTransactGET_SOMETHING
10-24 06:08:41.71227842785 D chenxf: XXXXService: #XXXXService::getSomething myParam = 1
10-24 06:08:41.71227862786 D chenxf: Client-main: getSomething 1
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
附录3个Android.mk一并贴出。
Android.mk
include $(call all-subdir-makefiles)
- 1
LOCAL_PATH:= $(call my-dir)
#LOCAL_CFLAGS_ALL :=-I. -I$(LOCAL_PATH)/..include $(CLEAR_VARS)LOCAL_SRC_FILES:= \\
main_client.cpp \\
../interface/IXXXXService.cpp \\
../interface/ICallback.cpp \\
Callback.cppLOCAL_SHARED_LIBRARIES := \\
libui libcutils libutils libbinderLOCAL_C_INCLUDES := \\
frameworks/base/include \\
frameworks/native/include \\
$(VENDOR_SDK_INCLUDES)LOCAL_MODULE:= test_binder_client
LOCAL_MODULE_TAGS := optionalinclude $(
推荐阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Android中dpdpi与px的关系
- 判断手机是否安装某app,有就打开,没有就去下载
- 设计模式与Android责任链模式——曹瞒兵败走华容
- popwindow在安卓7.0手机 显示错位的处理
- Android CameraManager 类
- Auto updater for my side loaded UWP apps
- 5+ App开发入门指南
- APP 自动化测试封装结构模式
- Android studio安装配置