Binder学习笔记—— 客户端如何组织Test()请求 ?
Posted 晋文
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Binder学习笔记—— 客户端如何组织Test()请求 ?相关的知识,希望对你有一定的参考价值。
还从客户端代码看起TestClient.cpp:14
int main()
sp < IServiceManager > sm = defaultServiceManager(); // new BpServiceManager(new BpBinder(0));
sp < IBinder > binder = sm->getService(String16("service.testservice")); //
sp<ITestService> cs = interface_cast < ITestService > (binder);
cs->test();
return 0;
sm->getService(…)返回了什么?
其中第2行defaultServiceManager()
返回的是new BpServiceManager(new BpBinder(0));
这在《 defaultServiceManager()返回了什么?》中有分析。
接下来的sm->getService(...)
在《ServiceManager如何响应checkService请求》的结尾给出了ServiceManager响应checkService返回的数据,我们再进入BpServiceManager::getService(…)
frameworks/native/libs/binder/IServiceManager.cpp:134
virtual sp<IBinder> getService(const String16& name) const
unsigned n;
for (n = 0; n < 5; n++)
sp<IBinder> svc = checkService(name); // 调用下面的checkService(...)
if (svc != NULL) return svc;
ALOGI("Waiting for service %s...\\n", String8(name).string());
sleep(1);
return NULL;
virtual sp<IBinder> checkService( const String16& name) const
Parcel data, reply;
data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());
data.writeString16(name);
remote()->transact(CHECK_SERVICE_TRANSACTION, data, &reply);
return reply.readStrongBinder(); // 在这里读取了ServiceManager返回的数据
进入Parcel::readStrongBinder(),frameworks/native/libs/binder/Parcel.cpp:1334
sp<IBinder> Parcel::readStrongBinder() const
sp<IBinder> val;
unflatten_binder(ProcessState::self(), *this, &val);
return val;
进入Parcel::unflatten_binder(…),frameworks/native/libe/binder/Parcel.cpp:293
status_t unflatten_binder(const sp<ProcessState>& proc,
const Parcel& in, sp<IBinder>* out)
const flat_binder_object* flat = in.readObject(false);
if (flat)
switch (flat->type)
case BINDER_TYPE_BINDER:
*out = reinterpret_cast<IBinder*>(flat->cookie);
return finish_unflatten_binder(NULL, *flat, in);
case BINDER_TYPE_HANDLE:
*out = proc->getStrongProxyForHandle(flat->handle);
return finish_unflatten_binder(
static_cast<BpBinder*>(out->get()), *flat, in);
return BAD_TYPE;
我们看服务端返回的数据:
返回的flat_binder_object的type是BINDER_TYPE_HANDLE,于是进入ProcessState::getStrongProxyForHandle(…),frameworks/native/libs/binder/ProcessState.cpp:179
sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)
sp<IBinder> result;
AutoMutex _l(mLock);
handle_entry* e = lookupHandleLocked(handle);
if (e != NULL)
......
IBinder* b = e->binder;
if (b == NULL || !e->refs->attemptIncWeak(this))
if (handle == 0) // 显然handle是0,因为0是ServiceManager
......
b = new BpBinder(handle); // 走到这里
e->binder = b;
if (b) e->refs = b->getWeakRefs();
result = b;
else
......
result.force_set(b);
e->refs->decWeak(this);
return result;
首次执行,会创建一个新的BpBinder(handle),并缓存该节点;以后在被调用,就直接返回该节点了。Parcel::finish_unflatten_binder(…)内部没有任何调用,直接返回了。
因此客户端的getService(…)调用就返回了new BpBinder(handle);其中handle是有服务端在addService时生成(见《binder服务端是如何组织addService数据的?》尾部的addService组织的请求数据图),并由ServiceManager缓存的,binder_uintptr_t值。
interface_cast < ITestService> (binder)返回了什么?
这个函数定义在frameworks/natvie/include/binder/IInterface.h:41
template<typename INTERFACE>
inline sp<INTERFACE> interface_cast(const sp<IBinder>& obj)
return INTERFACE::asInterface(obj);
代入模板参数:
inline sp<ITestService> interface_cast(const sp<IBinder>& obj)
return ITestService::asInterface(obj);
再来看ITestService的定义,Test.h
class ITestService : public IInterface
public:
DECLARE_META_INTERFACE(TestService);
virtual void test()=0;
;
宏DECLARE_META_INTERFACE定义在frameworks/native/include/binder/IInterface.h:74,展开为:
class ITestService : public IInterface
public:
static const android::String16 descriptor;
static android::sp<ITestService> asInterface(
const android::sp<android::IBinder>& obj);
virtual const android::String16& getInterfaceDescriptor() const;
ITestService();
virtual ~ITestService();
virtual void test()=0;
;
在ITestService.cpp中只有这么一行:
IMPLEMENT_META_INTERFACE(TestService, "android.TestServer.ITestService");
展开后为:
const android::String16 ITestService::descriptor("android.TestServer.ITestService");
const android::String16& ITestService::getInterfaceDescriptor() const
return ITestService::descriptor;
android::sp< ITestService > ITestService::asInterface(
const android::sp<android::IBinder>& obj)
// obj就是在main函数中传入的binder,即 new BpBinder(handle)
android::sp< ITestService > intr;
if (obj != NULL)
intr = static_cast< ITestService *>(
obj->queryLocalInterface(ITestService::descriptor).get());
if (intr == NULL)
intr = new BpTestService(obj);
return intr;
ITestService::ITestService()
ITestService::~ITestService()
BpBinder::queryLocalInterface(…)这个函数继承自基类IBinder,它直接返回NULL
sp<IInterface> IBinder::queryLocalInterface(const String16& /*descriptor*/)
return NULL;
因此ITestService::asInterface(…)就返回了new BpTestService(new BpBinder(handle));
即:
interface_cast < ITestService > (binder)返回
new BpTestService(new BpBinder(handle));
进入cs->test()
即BpTestService::test(),TestClient.cpp
void BpTestService::test()
printf("BpTestService::test()\\n");
Parcel data, reply;
data.writeInterfaceToken(ITestService::getInterfaceDescriptor());
remote()->transact(TEST, data, &reply);
printf("reply: %d\\n", reply.readInt32());
他的remote()是什么?在《defaultServiceManager()返回了什么?》中遇到过BpInterface::remote(),它返回的是在构造函数中传入的Binder。BpTestService正是继承自BpInterface:
class BpTestService: public BpInterface<ITestService>
所以BpTestService的remote()就返回构造时传入的new BpBinder(handle)
。
在《binder客户端是如何组织checkService数据的 ?》中曾分析过,BpBinder::transact(...)
调用了IPCThreadState::transact(...)
frameworks/native/libs/binder/IPCThreadState.cpp:548
status_t IPCThreadState::transact(int32_t handle,
uint32_t code, const Parcel& data,
Parcel* reply, uint32_t flags)
// code=TEST, flags=0
status_t err = data.errorCheck();
flags |= TF_ACCEPT_FDS;
......
err = writeTransactionData(BC_TRANSACTION, flags, handle, code, data, NULL);
......
return err;
进入waitForResponse(…),frameworks/native/libs/binder/IPCThreadState.cpp:904
status_t IPCThreadState::writeTransactionData(int32_t cmd, uint32_t binderFlags,
int32_t handle, uint32_t code, const Parcel& data, status_t* statusBuffer)
// cmd=BC_TRANSACTION, code=TEST, binderFlags=TF_ACCEPT_FDS
binder_transaction_data tr;
tr.target.ptr = 0; /* Don't pass uninitialized stack data to a remote process */
tr.target.handle = handle;
tr.code = code;
tr.flags = binderFlags;
tr.cookie = 0;
tr.sender_pid = 0;
tr.sender_euid = 0;
......
tr.data_size = data.ipcDataSize();
tr.data.ptr.buffer = data.ipcData();
tr.offsets_size = data.ipcObjectsCount()*sizeof(binder_size_t);
tr.data.ptr.offsets = data.ipcObjects();
......
mOut.writeInt32(cmd);
mOut.write(&tr, sizeof(tr));
return NO_ERROR;
又是一个binder_transaction_data
数据包,不过这块数据很简单,内容如下:
TEST定义在Test.h中:
enum
TEST = IBinder::FIRST_CALL_TRANSACTION,
;
它为每一个Binder接口定义一个枚举数字。
- 轮廓渐渐清晰了:服务端通过addService向ServiceManager注册服务,后者记录下service name和服务实体(实体是什么以后再讨论)。客户端通过getService接口向ServiceManager请求获取到符合指定名称的service。之后调用service的服务接口只不过是向service发送一个数据包,该数据包中包含了指定的服务接口的序列号及参数,具体服务执行是由服务端收到该数据包后完成。
- 客户端通过getService获得service之后,客户端请求服务就直接发往service,而不再经过ServiceManager。因为上文cs->test()内调用的是new BpInterface(handle)的transact(…)函数,而不再是BpBinder(0)::transact(…),在最终组成的binder_transaction_data包中,handle也是服务端注册在ServiceManager的handle了。
因此,下一步就应该去到服务端,看它是怎么响应test()请求的。
以上是关于Binder学习笔记—— 客户端如何组织Test()请求 ?的主要内容,如果未能解决你的问题,请参考以下文章
inder学习笔记—— binder客户端是如何组织checkService数据的 ?
Binder学习笔记—— binder服务端是如何组织addService数据的?
Binder学习笔记—— 服务端如何响应Test()请求 ?
Binder学习笔记—— 服务端如何响应Test()请求 ?