Android Binder Mechanism (4) -- 如何使用已注册的系统Service
2011-07-01 16:27
561 查看
上一篇文章中我们讨论了如何向系统注册Service。本篇文章我们将讨论如何使用这个已注册的系统Service。
在本系列文章的第一篇中,客户端应用程序使用如下两条语句取得了ExampleService代理对象的引用。
view plaincopy to clipboardprint?
sp<IServiceManager> sm = defaultServiceManager();
binder = sm->getService(String16("byn.example"));
第一句我们之前已经详细解释过了,全局函数defaultServiceManager()返回的是ServiceManager代理对象的引用。第二句话以ExampleService的方法名为参数调用getService()方法,返回的是ExampleService代理对象的引用。这个过程和上一篇文章介绍的addService的过程是非常类似的,这里就不详细展开了。
客户应用程序获得了ExampleService代理对象的引用之后,通过如下语句调用服务:
view plaincopy to clipboardprint?
data.writeInt32(getpid());
data.writeInt32(n);
binder->transact(0, data, &reply);
第一句话写入当前进程的进程ID,这里只是为了输出log用,没有实际意义;
第二句话写入参数n;
最后一句话调用ExampleService代理对象的transact方法发送请求。第一个参数0是请求代码(code),如果一个服务提供了多个API接口,那么服务器端就通过这个参数区分调用的是哪一个API;第二个参数打包后的调用参数;最后一个参数保存返回值。因为ExampleService代理对象继承自BpBinder,所以这里调用的是BpBinder::transact()方法,进而调用IPCThreadState::transact()方法。这个过程在上一篇文章中已经介绍过。
现在我们重点剖析一下服务器端的情况。
服务器端在向系统注册服务之后,首先调用ProcessState::self()->startThreadPool()方法启动一个线程池;然后调用IPCThreadState::self()->joinThreadPool()方法进入一个无限循环,等待其它进程的服务请求。我们看一下joinThreadPool方法的源代码:
view plaincopy to clipboardprint?
// File: frameworks/base/libs/binder/IPCThreadState.cpp
void IPCThreadState::joinThreadPool(bool isMain)
{
LOG_THREADPOOL("**** THREAD %p (PID %d) IS JOINING THE THREAD POOL/n", (void*)pthread_self(), getpid());
mOut.writeInt32(isMain ? BC_ENTER_LOOPER : BC_REGISTER_LOOPER);
status_t result;
do {
int32_t cmd;
// When we've cleared the incoming command queue, process any pending derefs
if (mIn.dataPosition() >= mIn.dataSize()) {
size_t numPending = mPendingWeakDerefs.size();
if (numPending > 0) {
for (size_t i = 0; i < numPending; i++) {
RefBase::weakref_type* refs = mPendingWeakDerefs[i];
refs->decWeak(mProcess.get());
}
mPendingWeakDerefs.clear();
}
numPending = mPendingStrongDerefs.size();
if (numPending > 0) {
for (size_t i = 0; i < numPending; i++) {
BBinder* obj = mPendingStrongDerefs[i];
obj->decStrong(mProcess.get());
}
mPendingStrongDerefs.clear();
}
}
// now get the next command to be processed, waiting if necessary
result = talkWithDriver();
if (result >= NO_ERROR) {
size_t IN = mIn.dataAvail();
if (IN < sizeof(int32_t)) continue;
cmd = mIn.readInt32();
IF_LOG_COMMANDS() {
alog << "Processing top-level Command: "
<< getReturnString(cmd) << endl;
}
result = executeCommand(cmd);
}
// After executing the command, ensure that the thread is returned to the
// default cgroup and priority before rejoining the pool. This is a failsafe
// in case the command implementation failed to properly restore the thread's
// scheduling parameters upon completion.
int my_id;
#ifdef HAVE_GETTID
my_id = gettid();
#else
my_id = getpid();
#endif
if (!set_sched_policy(my_id, SP_FOREGROUND)) {
// success; reset the priority as well
setpriority(PRIO_PROCESS, my_id, ANDROID_PRIORITY_NORMAL);
}
// Let this thread exit the thread pool if it is no longer
// needed and it is not the main process thread.
if(result == TIMED_OUT && !isMain) {
break;
}
} while (result != -ECONNREFUSED && result != -EBADF);
LOG_THREADPOOL("**** THREAD %p (PID %d) IS LEAVING THE THREAD POOL err=%p/n",
(void*)pthread_self(), getpid(), (void*)result);
mOut.writeInt32(BC_EXIT_LOOPER);
talkWithDriver(false);
}
在joinThreadPool()方法中,通过调用talkWithDriver方法与binder设备进行通信,通常Service进程会阻塞在这里;一旦客户请求到来,该方法返回,并调用后面的executeCommand()方法进行处理。我们看一下executeCommand()方法的源代码:
view plaincopy to clipboardprint?
// File: frameworks/base/libs/binder/IPCThreadState.cpp
status_t IPCThreadState::executeCommand(int32_t cmd)
{
BBinder* obj;
RefBase::weakref_type* refs;
status_t result = NO_ERROR;
switch (cmd) {
case BR_ERROR:
result = mIn.readInt32();
break;
case BR_OK:
break;
case BR_ACQUIRE:
refs = (RefBase::weakref_type*)mIn.readInt32();
obj = (BBinder*)mIn.readInt32();
LOG_ASSERT(refs->refBase() == obj,
"BR_ACQUIRE: object %p does not match cookie %p (expected %p)",
refs, obj, refs->refBase());
obj->incStrong(mProcess.get());
IF_LOG_REMOTEREFS() {
LOG_REMOTEREFS("BR_ACQUIRE from driver on %p", obj);
obj->printRefs();
}
mOut.writeInt32(BC_ACQUIRE_DONE);
mOut.writeInt32((int32_t)refs);
mOut.writeInt32((int32_t)obj);
break;
case BR_RELEASE:
refs = (RefBase::weakref_type*)mIn.readInt32();
obj = (BBinder*)mIn.readInt32();
LOG_ASSERT(refs->refBase() == obj,
"BR_RELEASE: object %p does not match cookie %p (expected %p)",
refs, obj, refs->refBase());
IF_LOG_REMOTEREFS() {
LOG_REMOTEREFS("BR_RELEASE from driver on %p", obj);
obj->printRefs();
}
mPendingStrongDerefs.push(obj);
break;
case BR_INCREFS:
refs = (RefBase::weakref_type*)mIn.readInt32();
obj = (BBinder*)mIn.readInt32();
refs->incWeak(mProcess.get());
mOut.writeInt32(BC_INCREFS_DONE);
mOut.writeInt32((int32_t)refs);
mOut.writeInt32((int32_t)obj);
break;
case BR_DECREFS:
refs = (RefBase::weakref_type*)mIn.readInt32();
obj = (BBinder*)mIn.readInt32();
// NOTE: This assertion is not valid, because the object may no
// longer exist (thus the (BBinder*)cast above resulting in a different
// memory address).
//LOG_ASSERT(refs->refBase() == obj,
// "BR_DECREFS: object %p does not match cookie %p (expected %p)",
// refs, obj, refs->refBase());
mPendingWeakDerefs.push(refs);
break;
case BR_ATTEMPT_ACQUIRE:
refs = (RefBase::weakref_type*)mIn.readInt32();
obj = (BBinder*)mIn.readInt32();
{
const bool success = refs->attemptIncStrong(mProcess.get());
LOG_ASSERT(success && refs->refBase() == obj,
"BR_ATTEMPT_ACQUIRE: object %p does not match cookie %p (expected %p)",
refs, obj, refs->refBase());
mOut.writeInt32(BC_ACQUIRE_RESULT);
mOut.writeInt32((int32_t)success);
}
break;
case BR_TRANSACTION:
{
binder_transaction_data tr;
result = mIn.read(&tr, sizeof(tr));
LOG_ASSERT(result == NO_ERROR,
"Not enough command data for brTRANSACTION");
if (result != NO_ERROR) break;
Parcel buffer;
buffer.ipcSetDataReference(
reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer),
tr.data_size,
reinterpret_cast<const size_t*>(tr.data.ptr.offsets),
tr.offsets_size/sizeof(size_t), freeBuffer, this);
const pid_t origPid = mCallingPid;
const uid_t origUid = mCallingUid;
mCallingPid = tr.sender_pid;
mCallingUid = tr.sender_euid;
//LOGI(">>>> TRANSACT from pid %d uid %d/n", mCallingPid, mCallingUid);
Parcel reply;
IF_LOG_TRANSACTIONS() {
TextOutput::Bundle _b(alog);
alog << "BR_TRANSACTION thr " << (void*)pthread_self()
<< " / obj " << tr.target.ptr << " / code "
<< TypeCode(tr.code) << ": " << indent << buffer
<< dedent << endl
<< "Data addr = "
<< reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer)
<< ", offsets addr="
<< reinterpret_cast<const size_t*>(tr.data.ptr.offsets) << endl;
}
if (tr.target.ptr) {
sp<BBinder> b((BBinder*)tr.cookie);
const status_t error = b->transact(tr.code, buffer, &reply, 0);
if (error < NO_ERROR) reply.setError(error);
} else {
const status_t error = the_context_object->transact(tr.code, buffer, &reply, 0);
if (error < NO_ERROR) reply.setError(error);
}
//LOGI("<<<< TRANSACT from pid %d restore pid %d uid %d/n",
// mCallingPid, origPid, origUid);
if ((tr.flags & TF_ONE_WAY) == 0) {
LOG_ONEWAY("Sending reply to %d!", mCallingPid);
sendReply(reply, 0);
} else {
LOG_ONEWAY("NOT sending reply to %d!", mCallingPid);
}
mCallingPid = origPid;
mCallingUid = origUid;
IF_LOG_TRANSACTIONS() {
TextOutput::Bundle _b(alog);
alog << "BC_REPLY thr " << (void*)pthread_self() << " / obj "
<< tr.target.ptr << ": " << indent << reply << dedent << endl;
}
}
break;
case BR_DEAD_BINDER:
{
BpBinder *proxy = (BpBinder*)mIn.readInt32();
proxy->sendObituary();
mOut.writeInt32(BC_DEAD_BINDER_DONE);
mOut.writeInt32((int32_t)proxy);
} break;
case BR_CLEAR_DEATH_NOTIFICATION_DONE:
{
BpBinder *proxy = (BpBinder*)mIn.readInt32();
proxy->getWeakRefs()->decWeak(proxy);
} break;
case BR_FINISHED:
result = TIMED_OUT;
break;
case BR_NOOP:
break;
case BR_SPAWN_LOOPER:
mProcess->spawnPooledThread(false);
break;
default:
printf("*** BAD COMMAND %d received from Binder driver/n", cmd);
result = UNKNOWN_ERROR;
break;
}
if (result != NO_ERROR) {
mLastError = result;
}
return result;
}
这里,函数会根据一系列枚举值作相应的处理。在binder协议中:
BR_XXX等宏为BinderDriverReturnProtocol,表示Binder驱动返回协议。
BC_XXX等宏为BinderDriverCommandProtocol,表示Binder驱动命令协议。
因为这里是收到命令请求后要做相应的处理,所以这里的宏都是以BR开头的。这里会走到BR_TRANSACTION这个分支,调用BBinder的transact()方法做处理(b->transact(tr.code, buffer, &reply, 0))。我们看一下BBinder::transact()方法的源代码:
view plaincopy to clipboardprint?
// File: frameworks/base/libs/binder/binder.cpp
status_t BBinder::transact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
data.setDataPosition(0);
status_t err = NO_ERROR;
switch (code) {
case PING_TRANSACTION:
reply->writeInt32(pingBinder());
break;
default:
err = onTransact(code, data, reply, flags);
break;
}
if (reply != NULL) {
reply->setDataPosition(0);
}
return err;
}
我们看到调用的是虚函数onTransact()。因为ExampleService类继承自BBinder类,并改写了onTransact()方法,所以这里会调用到ExampleService::onTransact()方法。
view plaincopy to clipboardprint?
status_t ExampleService::onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
switch(code)
{
case 0: {
pid_t pid = data.readInt32();
int num = data.readInt32();
num = num + 100;
reply->writeInt32(num);
return NO_ERROR;
}
break;
default:
return BBinder::onTransact(code, data, reply, flags);
}
}
看到这里首先根据请求代码作相应的处理。还记得我们发送请求时用的是代码0,所以这里会走到"case0"这个分支。程序先顺序读出两个参数:进程ID和被加数,将被加数加上100之后返回。至此,服务器端完成了客户端的服务请求。
我们将总共四篇文章涉及到的主要类用下面的类图作一总结:
说明:
1. Android系统使用binder机制实现进程间通信(IPC),这里主要涉及到以下几个类:
1.1 IBinder是Android系统对binder机制的抽象,任何一个向系统注册的Service都必须继承IBinder接口(如:ExampleService继承BBinder,而BBinder继承IBinder)
1.2 IInterface我们在这一系列文章里没有过多涉及。它的目的是进一步抽象binder机制。比如要使用我们的ExampleService,客户端应用程序必须显式调用IPCThreadState::transaction()方法,对用户来说还是不太友好。如果我们定义一个新的类IExampleServiceInterface继承Interface,在这个类中定义add100()接口,ExampleService的代理对象也拥有该接口,那么客户端应用程序直接调用代理对象的add100()方法就好了,这样做对用户更友好。比如ServiceManager就是这样实现的(IServiceManager继承IInterface)。客户端调用的是addService接口而不是transaction方法。
1.3 ProcessState类是一个singleton类型,每个进程只能创建一个实例,它的作用是管理当前进程中的所有Service代理对象(BpBinder对象)。任何一个使用binder机制的进程都必须创建一个该类的实例。
1.4 IPCThreadState类是processState类的友元类,它的作用是封装对binder设备的I/O操作。客户端通过调用它的transact()方法完成发送请求;服务器端调用他的joinThreadState()方法等待客户端的服务请求。
2. Android的binder机制本质上是Proxy模式的一个具体实现。
3. ServiceManager是整个Android系统的Service管理员,任何一个系统Service首先要向它注册才能提供服务。注册时,首先要获得它的代理对象(BpServiceManager),然后通过调用它的addService()方法完成注册。客户端通过调用它的getService()获取系统服务的代理兑现。ServiceManager在系统中始终对应句柄0。
4. 客户端通过调用IPCThreadState的transaction方法发送请求;服务器端通过改写BBinder的onTransaction()方法实现接受请求。
(全文完)
在本系列文章的第一篇中,客户端应用程序使用如下两条语句取得了ExampleService代理对象的引用。
view plaincopy to clipboardprint?
sp<IServiceManager> sm = defaultServiceManager();
binder = sm->getService(String16("byn.example"));
第一句我们之前已经详细解释过了,全局函数defaultServiceManager()返回的是ServiceManager代理对象的引用。第二句话以ExampleService的方法名为参数调用getService()方法,返回的是ExampleService代理对象的引用。这个过程和上一篇文章介绍的addService的过程是非常类似的,这里就不详细展开了。
客户应用程序获得了ExampleService代理对象的引用之后,通过如下语句调用服务:
view plaincopy to clipboardprint?
data.writeInt32(getpid());
data.writeInt32(n);
binder->transact(0, data, &reply);
第一句话写入当前进程的进程ID,这里只是为了输出log用,没有实际意义;
第二句话写入参数n;
最后一句话调用ExampleService代理对象的transact方法发送请求。第一个参数0是请求代码(code),如果一个服务提供了多个API接口,那么服务器端就通过这个参数区分调用的是哪一个API;第二个参数打包后的调用参数;最后一个参数保存返回值。因为ExampleService代理对象继承自BpBinder,所以这里调用的是BpBinder::transact()方法,进而调用IPCThreadState::transact()方法。这个过程在上一篇文章中已经介绍过。
现在我们重点剖析一下服务器端的情况。
服务器端在向系统注册服务之后,首先调用ProcessState::self()->startThreadPool()方法启动一个线程池;然后调用IPCThreadState::self()->joinThreadPool()方法进入一个无限循环,等待其它进程的服务请求。我们看一下joinThreadPool方法的源代码:
view plaincopy to clipboardprint?
// File: frameworks/base/libs/binder/IPCThreadState.cpp
void IPCThreadState::joinThreadPool(bool isMain)
{
LOG_THREADPOOL("**** THREAD %p (PID %d) IS JOINING THE THREAD POOL/n", (void*)pthread_self(), getpid());
mOut.writeInt32(isMain ? BC_ENTER_LOOPER : BC_REGISTER_LOOPER);
status_t result;
do {
int32_t cmd;
// When we've cleared the incoming command queue, process any pending derefs
if (mIn.dataPosition() >= mIn.dataSize()) {
size_t numPending = mPendingWeakDerefs.size();
if (numPending > 0) {
for (size_t i = 0; i < numPending; i++) {
RefBase::weakref_type* refs = mPendingWeakDerefs[i];
refs->decWeak(mProcess.get());
}
mPendingWeakDerefs.clear();
}
numPending = mPendingStrongDerefs.size();
if (numPending > 0) {
for (size_t i = 0; i < numPending; i++) {
BBinder* obj = mPendingStrongDerefs[i];
obj->decStrong(mProcess.get());
}
mPendingStrongDerefs.clear();
}
}
// now get the next command to be processed, waiting if necessary
result = talkWithDriver();
if (result >= NO_ERROR) {
size_t IN = mIn.dataAvail();
if (IN < sizeof(int32_t)) continue;
cmd = mIn.readInt32();
IF_LOG_COMMANDS() {
alog << "Processing top-level Command: "
<< getReturnString(cmd) << endl;
}
result = executeCommand(cmd);
}
// After executing the command, ensure that the thread is returned to the
// default cgroup and priority before rejoining the pool. This is a failsafe
// in case the command implementation failed to properly restore the thread's
// scheduling parameters upon completion.
int my_id;
#ifdef HAVE_GETTID
my_id = gettid();
#else
my_id = getpid();
#endif
if (!set_sched_policy(my_id, SP_FOREGROUND)) {
// success; reset the priority as well
setpriority(PRIO_PROCESS, my_id, ANDROID_PRIORITY_NORMAL);
}
// Let this thread exit the thread pool if it is no longer
// needed and it is not the main process thread.
if(result == TIMED_OUT && !isMain) {
break;
}
} while (result != -ECONNREFUSED && result != -EBADF);
LOG_THREADPOOL("**** THREAD %p (PID %d) IS LEAVING THE THREAD POOL err=%p/n",
(void*)pthread_self(), getpid(), (void*)result);
mOut.writeInt32(BC_EXIT_LOOPER);
talkWithDriver(false);
}
在joinThreadPool()方法中,通过调用talkWithDriver方法与binder设备进行通信,通常Service进程会阻塞在这里;一旦客户请求到来,该方法返回,并调用后面的executeCommand()方法进行处理。我们看一下executeCommand()方法的源代码:
view plaincopy to clipboardprint?
// File: frameworks/base/libs/binder/IPCThreadState.cpp
status_t IPCThreadState::executeCommand(int32_t cmd)
{
BBinder* obj;
RefBase::weakref_type* refs;
status_t result = NO_ERROR;
switch (cmd) {
case BR_ERROR:
result = mIn.readInt32();
break;
case BR_OK:
break;
case BR_ACQUIRE:
refs = (RefBase::weakref_type*)mIn.readInt32();
obj = (BBinder*)mIn.readInt32();
LOG_ASSERT(refs->refBase() == obj,
"BR_ACQUIRE: object %p does not match cookie %p (expected %p)",
refs, obj, refs->refBase());
obj->incStrong(mProcess.get());
IF_LOG_REMOTEREFS() {
LOG_REMOTEREFS("BR_ACQUIRE from driver on %p", obj);
obj->printRefs();
}
mOut.writeInt32(BC_ACQUIRE_DONE);
mOut.writeInt32((int32_t)refs);
mOut.writeInt32((int32_t)obj);
break;
case BR_RELEASE:
refs = (RefBase::weakref_type*)mIn.readInt32();
obj = (BBinder*)mIn.readInt32();
LOG_ASSERT(refs->refBase() == obj,
"BR_RELEASE: object %p does not match cookie %p (expected %p)",
refs, obj, refs->refBase());
IF_LOG_REMOTEREFS() {
LOG_REMOTEREFS("BR_RELEASE from driver on %p", obj);
obj->printRefs();
}
mPendingStrongDerefs.push(obj);
break;
case BR_INCREFS:
refs = (RefBase::weakref_type*)mIn.readInt32();
obj = (BBinder*)mIn.readInt32();
refs->incWeak(mProcess.get());
mOut.writeInt32(BC_INCREFS_DONE);
mOut.writeInt32((int32_t)refs);
mOut.writeInt32((int32_t)obj);
break;
case BR_DECREFS:
refs = (RefBase::weakref_type*)mIn.readInt32();
obj = (BBinder*)mIn.readInt32();
// NOTE: This assertion is not valid, because the object may no
// longer exist (thus the (BBinder*)cast above resulting in a different
// memory address).
//LOG_ASSERT(refs->refBase() == obj,
// "BR_DECREFS: object %p does not match cookie %p (expected %p)",
// refs, obj, refs->refBase());
mPendingWeakDerefs.push(refs);
break;
case BR_ATTEMPT_ACQUIRE:
refs = (RefBase::weakref_type*)mIn.readInt32();
obj = (BBinder*)mIn.readInt32();
{
const bool success = refs->attemptIncStrong(mProcess.get());
LOG_ASSERT(success && refs->refBase() == obj,
"BR_ATTEMPT_ACQUIRE: object %p does not match cookie %p (expected %p)",
refs, obj, refs->refBase());
mOut.writeInt32(BC_ACQUIRE_RESULT);
mOut.writeInt32((int32_t)success);
}
break;
case BR_TRANSACTION:
{
binder_transaction_data tr;
result = mIn.read(&tr, sizeof(tr));
LOG_ASSERT(result == NO_ERROR,
"Not enough command data for brTRANSACTION");
if (result != NO_ERROR) break;
Parcel buffer;
buffer.ipcSetDataReference(
reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer),
tr.data_size,
reinterpret_cast<const size_t*>(tr.data.ptr.offsets),
tr.offsets_size/sizeof(size_t), freeBuffer, this);
const pid_t origPid = mCallingPid;
const uid_t origUid = mCallingUid;
mCallingPid = tr.sender_pid;
mCallingUid = tr.sender_euid;
//LOGI(">>>> TRANSACT from pid %d uid %d/n", mCallingPid, mCallingUid);
Parcel reply;
IF_LOG_TRANSACTIONS() {
TextOutput::Bundle _b(alog);
alog << "BR_TRANSACTION thr " << (void*)pthread_self()
<< " / obj " << tr.target.ptr << " / code "
<< TypeCode(tr.code) << ": " << indent << buffer
<< dedent << endl
<< "Data addr = "
<< reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer)
<< ", offsets addr="
<< reinterpret_cast<const size_t*>(tr.data.ptr.offsets) << endl;
}
if (tr.target.ptr) {
sp<BBinder> b((BBinder*)tr.cookie);
const status_t error = b->transact(tr.code, buffer, &reply, 0);
if (error < NO_ERROR) reply.setError(error);
} else {
const status_t error = the_context_object->transact(tr.code, buffer, &reply, 0);
if (error < NO_ERROR) reply.setError(error);
}
//LOGI("<<<< TRANSACT from pid %d restore pid %d uid %d/n",
// mCallingPid, origPid, origUid);
if ((tr.flags & TF_ONE_WAY) == 0) {
LOG_ONEWAY("Sending reply to %d!", mCallingPid);
sendReply(reply, 0);
} else {
LOG_ONEWAY("NOT sending reply to %d!", mCallingPid);
}
mCallingPid = origPid;
mCallingUid = origUid;
IF_LOG_TRANSACTIONS() {
TextOutput::Bundle _b(alog);
alog << "BC_REPLY thr " << (void*)pthread_self() << " / obj "
<< tr.target.ptr << ": " << indent << reply << dedent << endl;
}
}
break;
case BR_DEAD_BINDER:
{
BpBinder *proxy = (BpBinder*)mIn.readInt32();
proxy->sendObituary();
mOut.writeInt32(BC_DEAD_BINDER_DONE);
mOut.writeInt32((int32_t)proxy);
} break;
case BR_CLEAR_DEATH_NOTIFICATION_DONE:
{
BpBinder *proxy = (BpBinder*)mIn.readInt32();
proxy->getWeakRefs()->decWeak(proxy);
} break;
case BR_FINISHED:
result = TIMED_OUT;
break;
case BR_NOOP:
break;
case BR_SPAWN_LOOPER:
mProcess->spawnPooledThread(false);
break;
default:
printf("*** BAD COMMAND %d received from Binder driver/n", cmd);
result = UNKNOWN_ERROR;
break;
}
if (result != NO_ERROR) {
mLastError = result;
}
return result;
}
这里,函数会根据一系列枚举值作相应的处理。在binder协议中:
BR_XXX等宏为BinderDriverReturnProtocol,表示Binder驱动返回协议。
BC_XXX等宏为BinderDriverCommandProtocol,表示Binder驱动命令协议。
因为这里是收到命令请求后要做相应的处理,所以这里的宏都是以BR开头的。这里会走到BR_TRANSACTION这个分支,调用BBinder的transact()方法做处理(b->transact(tr.code, buffer, &reply, 0))。我们看一下BBinder::transact()方法的源代码:
view plaincopy to clipboardprint?
// File: frameworks/base/libs/binder/binder.cpp
status_t BBinder::transact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
data.setDataPosition(0);
status_t err = NO_ERROR;
switch (code) {
case PING_TRANSACTION:
reply->writeInt32(pingBinder());
break;
default:
err = onTransact(code, data, reply, flags);
break;
}
if (reply != NULL) {
reply->setDataPosition(0);
}
return err;
}
我们看到调用的是虚函数onTransact()。因为ExampleService类继承自BBinder类,并改写了onTransact()方法,所以这里会调用到ExampleService::onTransact()方法。
view plaincopy to clipboardprint?
status_t ExampleService::onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
switch(code)
{
case 0: {
pid_t pid = data.readInt32();
int num = data.readInt32();
num = num + 100;
reply->writeInt32(num);
return NO_ERROR;
}
break;
default:
return BBinder::onTransact(code, data, reply, flags);
}
}
看到这里首先根据请求代码作相应的处理。还记得我们发送请求时用的是代码0,所以这里会走到"case0"这个分支。程序先顺序读出两个参数:进程ID和被加数,将被加数加上100之后返回。至此,服务器端完成了客户端的服务请求。
我们将总共四篇文章涉及到的主要类用下面的类图作一总结:
说明:
1. Android系统使用binder机制实现进程间通信(IPC),这里主要涉及到以下几个类:
1.1 IBinder是Android系统对binder机制的抽象,任何一个向系统注册的Service都必须继承IBinder接口(如:ExampleService继承BBinder,而BBinder继承IBinder)
1.2 IInterface我们在这一系列文章里没有过多涉及。它的目的是进一步抽象binder机制。比如要使用我们的ExampleService,客户端应用程序必须显式调用IPCThreadState::transaction()方法,对用户来说还是不太友好。如果我们定义一个新的类IExampleServiceInterface继承Interface,在这个类中定义add100()接口,ExampleService的代理对象也拥有该接口,那么客户端应用程序直接调用代理对象的add100()方法就好了,这样做对用户更友好。比如ServiceManager就是这样实现的(IServiceManager继承IInterface)。客户端调用的是addService接口而不是transaction方法。
1.3 ProcessState类是一个singleton类型,每个进程只能创建一个实例,它的作用是管理当前进程中的所有Service代理对象(BpBinder对象)。任何一个使用binder机制的进程都必须创建一个该类的实例。
1.4 IPCThreadState类是processState类的友元类,它的作用是封装对binder设备的I/O操作。客户端通过调用它的transact()方法完成发送请求;服务器端调用他的joinThreadState()方法等待客户端的服务请求。
2. Android的binder机制本质上是Proxy模式的一个具体实现。
3. ServiceManager是整个Android系统的Service管理员,任何一个系统Service首先要向它注册才能提供服务。注册时,首先要获得它的代理对象(BpServiceManager),然后通过调用它的addService()方法完成注册。客户端通过调用它的getService()获取系统服务的代理兑现。ServiceManager在系统中始终对应句柄0。
4. 客户端通过调用IPCThreadState的transaction方法发送请求;服务器端通过改写BBinder的onTransaction()方法实现接受请求。
(全文完)
相关文章推荐
- Android Binder Mechanism (4) -- 如何使用已注册的系统Service
- Android Binder Mechanism (4) -- 如何使用已注册的系统Service
- Android Binder Mechanism (3) -- 如何向系统注册Service
- Android Binder Mechanism (3) -- 如何向系统注册Service
- Android Binder Mechanism (3) -- 如何向系统注册Service
- Android 使用多个Intent 进行activity跳转 而没有finish的情况,如何直接退出系统
- android 5.1 如何添加一个系统service
- 如何使用android系统隐藏hide的类和方法
- Android 通过系统使用NotificationListenerService 监听各种Notification的使用方法
- Android使用binder访问service的方式(一)
- 如何通过使用fiddler对Android系统设备抓包总结
- Android------Binder 如何在binder架构下写service
- Android系统移植与调试之------->如何使用PhotoShop转换24位的bmp图片为16位bmp图片
- 如何使用Jdbc和Servlet操作Mysql数据库,编写Android登录注册服务端?
- Android Binder分析二:Natvie Service的注册
- Android系统的Binder机制之四——系统Service
- android binder机制,注册系统服务---Java层注册系统服务
- android Bound Service使用:继续Binder类绑定服务
- android开发如何保证service不被系统杀死
- Android系统的Binder机制之四——系统Service