一直对android的binder机制比较困惑,出了问题时也手足无措。看了一些资料,感觉似懂非懂,于是萌生了一个想法,一定要自己跟一根binder流程,这样有个亲身经历后,能够加深对binder的了解。
这里以surfaceflinger的远程调用为例,分析一下binder流程。碰巧手头上有一个anr trace文件,里面有surfaceflinger native端的stack trace。从trace更能印证自己总结的东西。
1. binder概述
binder涉及到proxy端和native端。proxy为client侧,native为server侧。
拿SurfaceFlinger类来讲,要实现binder远程调用,需要继承自BnXXX类:
frameworks/native/services/surfaceflinger/SurfaceFlinger.h
class SurfaceFlinger : public BinderService,
public BnSurfaceComposer,
这里的关键就是BnSurfaceComposer。继承了BinderService后,程序可以通过一种简单方式来publish服务:
frameworks/native/cmds/surfaceflinger/main_surfaceflinger.cpp
main()
SurfaceFlinger::publishAndJoinThreadPool(true);
这个函数会创建一个SurfaceFlinger对象,并通过远程调用将它注册到service manager中:
static void publishAndJoinThreadPool(bool allowIsolated = false) {
sp sm(defaultServiceManager());
sm->addService(String16(SERVICE::getServiceName()), new SERVICE(), allowIsolated);
ProcessState::self()->startThreadPool();
IPCThreadState::self()->joinThreadPool();
}
好了,回过头来看看BnSurfaceComposer。
frameworks/native/include/gui/ISurfaceComposer.h
class ISurfaceComposer: public IInterface
class BnSurfaceComposer: public BnInterface
在frameworks/native/include/binder/IInterface.h中, BnInterface为声明为:
template
class BnInterface : public INTERFACE, public BBinder
继续看各类的父类,可以看到BnSurfaceComposer的继承关系为:
BnSurfaceComposer -> BnInterface -> ISurfaceComposer & BBinder
ISurfaceComposer -> IInterface -> RefBase
BBinder -> IBinder -> RefBase
在以上这些类中,我们需要实现BnSurfaceComposer和ISurfaceComposer,其它的都是android库提供实现。BnSurfaceComposer实现了onTransact(),会调用子类的override函数来处理。这里子类就是SurfaceFlinger。
对于Proxy端,我们需要实现BpXXX类:
class BpSurfaceComposer : public BpInterface
BpSurfaceComposer的继承关系为:
BpSurfaceComposer -> BpInterface -> ISurfaceComposer & BpRefBase
BpRefBase -> RefBase
这里我们需要实现BpSurfaceComposer。在BpSurfaceComposer的函数中,一般都是通过remote()->transact()将命令发送到服务端:
virtual sp createConnection()
{
uint32_t n;
Parcel data, reply;
data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
remote()->transact(BnSurfaceComposer::CREATE_CONNECTION, data, &reply);
return interface_cast(reply.readStrongBinder());
}
总结一下,要实现native端,需要以下几步:
(1) 实现ISurfaceComposer
(2) 实现BpSurfaceComposer,里面各调用通过remote()->transact()发送到服务端
(3) 实现BnSurfaceComposer,里面实现onTransact()来处理命令
(4) SurfaceFlinger继承BnSurfaceComposer,然后实例化SurfaceFlinger并注册到service manager
2. 注册和获取服务
注册服务的代码如下:
sp sm(defaultServiceManager());
sm->addService(String16(SERVICE::getServiceName()), new SERVICE(), allowIsolated);
这里其实也用到了binder机制,因为服务端和service manager是不同的进程。
defaultServiceManager(),BinderService.h
gDefaultServiceManager = interface_cast(ProcessState::self()->getContextObject(NULL));
getStrongProxyForHandle(0),ProcessState.cpp
return gDefaultServiceManager;
sp ProcessState::getStrongProxyForHandle(int32_t handle)
{
sp result;
AutoMutex _l(mLock);
handle_entry* e = lookupHandleLocked(handle);
if (e != NULL) {
// We need to create a new BpBinder if there isn't currently one, OR we
// are unable to acquire a weak reference on this current one. See comment
// in getWeakProxyForHandle() for more info about this.
IBinder* b = e->binder;
if (b == NULL || !e->refs->attemptIncWeak(this)) {
b = new BpBinder(handle);
e->binder = b;
if (b) e->refs = b->getWeakRefs();
result = b;
} else {
// This little bit of nastyness is to allow us to add a primary
// reference to the remote proxy when this team doesn't have one
// but another team is sending the handle to us.
result.force_set(b);
e->refs->decWeak(this);
}
}
return result;
}
看到了吗,这里根据handle创建了一个BpBinder对象并返回。返回的对象被interface_cast转换,之后就可以通过IServiceManager进行远程调用了。注册服务和获取服务的服务端都在service manager中,代码位于:
frameworks/base/cmds/servicemanager/service_manager.c
注册服务时,需要传入服务名和对象,服务名由SERVICE::getServiceName()获得。
获取服务时,需要指定服务名:
frameworks/native/libs/gui/SurfaceComposerClient.cpp
void ComposerService::connectLocked() {
const String16 name("SurfaceFlinger");
while (getService(name, &mComposerService) != NO_ERROR) {
usleep(250000);
}
frameworks/native/include/binder/IServiceManager.h
template
status_t getService(const String16& name, sp* outService)
{
const sp sm = defaultServiceManager();
if (sm != NULL) {
*outService = interface_cast(sm->getService(name));
if ((*outService) != NULL) return NO_ERROR;
}
return NAME_NOT_FOUND;
}
调用到IServiceManager类:
frameworks/native/libs/binder/IServiceManager.cpp
virtual sp getService(const String16& name) const
{
unsigned n;
for (n = 0; n < 5; n++){
sp svc = checkService(name);
if (svc != NULL) return svc;
ALOGI("Waiting for service %s...\n", String8(name).string());
sleep(1);
}
return NULL;
}
checkService()的实现:
virtual sp 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();
}
在结尾,根据service manager的返回调用readStrongBinder:
sp Parcel::readStrongBinder()
status_t unflatten_binder(const sp
& proc, const Parcel& in, wp* out)
sp ProcessState::getStrongProxyForHandle(int32_t handle) // 或者为getWeakProxyForHandle
这里,getStrongProxyForHandle会根据handle来创建一个BpBinder,该binder就表示客户端需要的服务,与提供的名称对应。binder随后被interface_cast转换为INTERFACE类型,这里就是ISurfaceComposer。转换时调用到了以下函数:
template
inline sp interface_cast(const sp& obj)
{
return INTERFACE::asInterface(obj);
}
进而调用到ISurfaceComposer::asInterface。在frameworks/native/libs/gui/ISurfaceComposer.cpp中,使用到了IMPLEMENT_META_INTERFACE:
IMPLEMENT_META_INTERFACE(SurfaceComposer, "android.ui.ISurfaceComposer");
该宏在IInterface.h中被扩展,其中包含asInterface函数:
android::sp I##INTERFACE::asInterface( \
const android::sp
& obj) \
{ \
android::sp intr; \
if (obj != NULL) { \
intr = static_cast( \
obj->queryLocalInterface( \
I##INTERFACE::descriptor).get()); \
if (intr == NULL) { \
intr = new Bp##INTERFACE(obj); \
} \
} \
return intr; \
}
在这里,创建了BpSurfaceComposer并返回,参数为getService返回的IBinder对象。
3. 客户端远程调用
远程调用是BpSurfaceComposer中通过remote()->transact()
remote()->transact(BnSurfaceComposer::CREATE_CONNECTION, data, &reply);
这里有命令,传给服务端的数据data,以及返回的结果reply。这里的remote()返回什么对象呢?
BpSurfaceComposer的继承关系为:
BpSurfaceComposer -> BpInterface
BpInterface -> ISurfaceComposer & BpRefBase
BpRefBase -> RefBase
remote()为BpRefBase的成员函数,返回mRemote:
inline IBinder* remote() { return mRemote; }
BpRefbase的构造函数中,mRemote被赋值为sp&的参数:
BpRefBase::BpRefBase(const sp& o)
: mRemote(o.get()), mRefs(NULL), mState(0)
从前一节的分析得知,获取远程对象时,返回的IBinder对象作为参数传到BpSurfaceComposer构造函数,从而导致基类BpRefBase的构造函数被调用。因此,此处的mRemote极为service manager返回的IBinder对象,其实就是new的BpBinder(handle)。
所以,remote()->transact()调用到了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;
}
继续往下跟会发现,transact调用会将command/data/reply等参数写入到/dev/binder节点,将这些参数传入内核。
下面是一个anr traces文件中截取的system_server中WindowManager线程的stack trace:
"WindowManager" prio=5 tid=14 NATIVE | group="main" sCount=1 dsCount=0 obj=0x41306db8 self=0x40e41b30 | sysTid=413 nice=-4 sched=0/0 cgrp=apps handle=1754226200 | state=S schedstat=( 4332243000 4585147000 20578 ) utm=321 stm=112 core=1 #00 pc 00016fe4 /system/lib/libc.so (__ioctl+8) #01 pc 0002a97d /system/lib/libc.so (ioctl+16) #02 pc 00016ba1 /system/lib/libbinder.so (android::IPCThreadState::talkWithDriver(bool)+132) #03 pc 0001709d /system/lib/libbinder.so (android::IPCThreadState::waitForResponse(android::Parcel*, int*)+44) #04 pc 000172b7 /system/lib/libbinder.so (android::IPCThreadState::transact(int, unsigned int, android::Parcel const&, android::Parcel*, unsigned int)+114) #05 pc 00014a3b /system/lib/libbinder.so (android::BpBinder::transact(unsigned int, android::Parcel const&, android::Parcel*, unsigned int)+34) #06 pc 000265d7 /system/lib/libgui.so #07 pc 00028073 /system/lib/libgui.so (android::SurfaceComposerClient::destroySurface(int)+14) #08 pc 0002749f /system/lib/libgui.so (android::SurfaceControl::destroy()+14) #09 pc 00058139 /system/lib/libandroid_runtime.so #10 pc 0001e290 /system/lib/libdvm.so (dvmPlatformInvoke+112) #11 pc 0004d411 /system/lib/libdvm.so (dvmCallJNIMethod(unsigned int const*, JValue*, Method const*, Thread*)+396) #12 pc 00038c05 /system/lib/libdvm.so (dvmCheckCallJNIMethod(unsigned int const*, JValue*, Method const*, Thread*)+8) #13 pc 000276a0 /system/lib/libdvm.so #14 pc 0002b57c /system/lib/libdvm.so (dvmInterpret(Thread*, Method const*, JValue*)+184) #15 pc 0005fc31 /system/lib/libdvm.so (dvmCallMethodV(Thread*, Method const*, Object*, bool, JValue*, std::__va_list)+272) #16 pc 0005fc5b /system/lib/libdvm.so (dvmCallMethod(Thread*, Method const*, Object*, JValue*, ...)+20) #17 pc 000547d7 /system/lib/libdvm.so #18 pc 0000e3d8 /system/lib/libc.so (__thread_entry+72) #19 pc 0000dac4 /system/lib/libc.so (pthread_create+160) at android.view.Surface.nativeDestroy(Native Method) at android.view.Surface.destroy(Surface.java:395) at com.android.server.wm.WindowStateAnimator.destroySurfaceLocked(WindowStateAnimator.java:795) at com.android.server.wm.WindowManagerService.performLayoutAndPlaceSurfacesLockedInner(WindowManagerService.java:9451) at com.android.server.wm.WindowManagerService.performLayoutAndPlaceSurfacesLockedLoop(WindowManagerService.java:8286) at com.android.server.wm.WindowManagerService.performLayoutAndPlaceSurfacesLocked(WindowManagerService.java:8229) at com.android.server.wm.WindowManagerService.access$300(WindowManagerService.java:172) at com.android.server.wm.WindowManagerService$H.handleMessage(WindowManagerService.java:7715) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loop(Looper.java:137) at android.os.HandlerThread.run(HandlerThread.java:60)
4. 服务端处理命令
对于SurfaceComposer来讲,服务端为运行在进程/system/bin/surfaceflinger中的SurfaceFlinger对象。/system/bin/surfaceflinger的main函数如下:
frameworks/native/cmds/surfaceflinger/main_surfaceflinger.cpp
int main(int argc, char** argv) {
SurfaceFlinger::publishAndJoinThreadPool(true);
// When SF is launched in its own process, limit the number of
// binder threads to 4.
ProcessState::self()->setThreadPoolMaxThreadCount(4);
return 0;
}
publishAndJoinThreadPool会启动一个线程池:
ProcessState::self()->startThreadPool();
该调用会创建一个名为Binder_1的线程,该线程的作用就是不停读写binder,并处理命令:
void IPCThreadState::joinThreadPool(bool isMain)
{
result = talkWithDriver();
if (result >= NO_ERROR) {
//...
result = executeCommand(cmd);
}
}
由于此时参数为true,这是主线程,它还负责创建新的线程来处理客户端的命令。如果由新的客户端连入,executeCommand收到内核发出的BR_SPAWN_LOOPER命令时,会创建一个新线程,线程名依次为Binder_2, Binder_3, ...
status_t IPCThreadState::executeCommand(int32_t cmd)
{
case BR_SPAWN_LOOPER:
mProcess->spawnPooledThread(false);
break;
}
对于普通的命令,executeCommand会从binder_transaction_data中获取BBinder对象,调用其transact函数:
sp b((BBinder*)tr.cookie);
const status_t error = b->transact(tr.code, buffer, &reply, tr.flags);
if (error < NO_ERROR) reply.setError(error);
在Binder.cpp中,transact调用到onTransact():
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) {
default:
err = onTransact(code, data, reply, flags);
break;
}
}
该远程对象实际为一个BnSurfaceComposer对象,因此,onTransact()调用的是子类的函数。在BnSurfaceComposer::onTransact中,各命令被处理,对应到了SurfaceFinger类的各函数。
下面是一个anr traces文件中截取的surfaceflinger中Binder_1线程的stack trace:
"Binder_1" sysTid=283 #00 pc 0000dc70 /system/lib/libc.so (__futex_syscall3+8) #01 pc 00012e14 /system/lib/libc.so (__pthread_cond_timedwait_relative+48) #02 pc 00012e70 /system/lib/libc.so (__pthread_cond_timedwait+60) #03 pc 0001c713 /system/lib/libgui.so (android::BufferQueue::dequeueBuffer(int*, unsigned int, unsigned int, unsigned int, unsigned int)+554) #04 pc 0001e0e9 /system/lib/libgui.so (android::BnSurfaceTexture::onTransact(unsigned int, android::Parcel const&, android::Parcel*, unsigned int)+236) #05 pc 000143c9 /system/lib/libbinder.so (android::BBinder::transact(unsigned int, android::Parcel const&, android::Parcel*, unsigned int)+60) #06 pc 00016fad /system/lib/libbinder.so (android::IPCThreadState::executeCommand(int)+520) #07 pc 000173d5 /system/lib/libbinder.so (android::IPCThreadState::joinThreadPool(bool)+184) #08 pc 0001b179 /system/lib/libbinder.so #09 pc 00010f57 /system/lib/libutils.so (android::Thread::_threadLoop(void*)+114) #10 pc 00010abd /system/lib/libutils.so #11 pc 00012dd0 /system/lib/libc.so (__thread_entry+48) #12 pc 00012528 /system/lib/libc.so (pthread_create+172)