猜想
在native层进行Binder通信时,客户端使用的是BpBinder对象。
如
sp<IServiceManager> sm = defaultServiceManager();
sp<IBinder> service = sm->getService(String16("power"));
defaultServiceManager()的返回值是对BpBinder(0)的包装,
getService的返回对象是BpBinder(handle)。
每个服务是否有固定的整数值handle呢,我们是否可以直接使用BpBinder(handle)来构造BpBinder对象,进而跳过ServiceManager呢?
尝试
说干就干,我们来进行尝试。
在BpBinder.cpp中打开构造时的log
BpBinder::BpBinder(int32_t handle)
: mHandle(handle)
, mAlive(1)
, mObitsSent(0)
, mObituaries(NULL)
{
ALOGD("======aBinder, Creating BpBinder %p handle %d\n", this, mHandle);
extendObjectLifetime(OBJECT_LIFETIME_WEAK);
IPCThreadState::self()->incWeakHandle(handle);
}
仿照dumpsys的代码,写一个程序dumpHandle.cpp
dumpHandle.cpp
#define LOG_TAG "dumpsys"
#include <utils/Log.h>
#include <binder/Parcel.h>
#include <binder/ProcessState.h>
#include <binder/IServiceManager.h>
#include <binder/TextOutput.h>
#include <utils/Vector.h>
#include <binder/BpBinder.h>//
#include <getopt.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/time.h>
using namespace android;
int main(int argc, char* const argv[])
{
signal(SIGPIPE, SIG_IGN);
sp<IServiceManager> sm = defaultServiceManager();
fflush(stdout);
if (sm == NULL) {
ALOGE("Unable to get default service manager!");
aerr << "dumpsys: Unable to get default service manager!" << endl;
return 20;
}
if (argc <= 1)
{
printf("argc <= 1\n");
return 1;
}
Vector<String16> args;
int handle = atoi(argv[1]);
printf("handle = %d\n", handle);
IBinder * b = new BpBinder(handle);
int err = b->dump(STDOUT_FILENO, args);
if (err != 0) {
aerr << "Error dumping service info: (" << strerror(err)
<< ") " << endl;
}
return 0;
}
修改对应的Android.mk
mm dumpHandle进行编译,得到执行程序dumpHandle
把dumpHandle push到手机的/data/local/tmp路径下,
chmod 777 dumpHandle
获取handle的值
写一个app来查看在app中调用power服务构造出的BpBinder对象的handle的值
PowerManager aPowerManager = (PowerManager)getSystemService(POWER_SERVICE);
aPowerManager.isScreenOn();
查看log
01-01 12:50:05.211 13055-13055/com.example.atestbtn D/abinder: ===== aBinder, getIServiceManager().getService(name)=power
01-01 12:50:05.212 13055-13055/com.example.atestbtn D/BpBinder: ======aBinder, Creating BpBinder 0x71feeb7720 handle 22
测试
Unknown:/data/local/tmp # ./dumpHandle 22
handle = 22
Error dumping service info: (Unknown error -2147483646)
没有进行dump打印,出现了问题。
修改
增加sm->checkService(String16("power"));调用
sp<IBinder> service = sm->checkService(String16("power"));
Vector<String16> args;
int handle = atoi(argv[1]);
printf("handle = %d\n", handle);
IBinder * b = new BpBinder(handle);
int err = b->dump(STDOUT_FILENO, args);
# ./dumpHandle 22
handle = 22
Error dumping service info: (Unknown error -2147483646)
查看log
01-01 15:52:48.091 13997-13997/? D/BpBinder: ======aBinder, Creating BpBinder 0x7593848000 handle 0
01-01 15:52:48.092 13997-13997/? D/BpBinder: ======aBinder, Creating BpBinder 0x75938480a0 handle 1
01-01 15:52:48.093 13997-13997/? D/BpBinder: ======aBinder, Creating BpBinder 0x7593848140 handle 22
handle 0是defaultServiceManager()里构造的
handle 1是sm->checkService(String16("power"))构造的
handle 22是new BpBinder(22)构造的
也就是说在这个进程中,power服务对应的是BpBinder(1)
测试
# ./dumpHandle 1
handle = 1
POWER MANAGER (dumpsys power)
Power Manager State:
mDirty=0x0
… …
可以进行dump了,这个BpBinder(1)其实是沾了sm->checkService(String16("power"));的光。
分析
这个试验给了一个感性的认识,不能通过直接的构造BpBinder(handle)去进行binder通信,在client端需要通过defaultServiceManager()来进行getService操作。
BpBinder中的handle如同文件描述符fd,需要进行open操作后才可以使用,而且每个进程中对同一个文件的fd是独立的,他们的值不相关。
关于handle的值是如何按照client的请求进行分配的,需要进一步分析。