声明
- 其实对于Android系统Binder通信的机制早就有分析的想法,记得2019年6、7月份Mr.Deng离职期间约定一起对其进行研究的,但因为我个人问题没能实施这个计划,留下些许遗憾…
- 文中参考了很多书籍及博客内容,可能涉及的比较多先不具体列出来了;
- 本文使用的代码是LineageOS的cm-14.1,对应Android 7.1.2,可以参考我的另一篇博客:cm-14.1 Android系统启动过程分析(1)-如何下载Nexus5的LineageOS14.1(cm-14.1)系统源码并编译、刷机
1 Binder封装库
在 Android 系统中,在各个层次都有和 Binder 有关的实现。其中主要的 Binder 库由本地原生代码实现。Binder库核心部分的各个头文件结构如下所示:
- Parcel.h : 定义类 Parcel,为在 IPC 中传输的数据定义容器。
- IBinder.h : 定义类 IBinder,是 Binder 对象的抽象接口。
- Binder.h : 定义类 BBinder 和 BpRefBase 分别为 IBinder 类的继承者和服务器端使用的基类。
- BpBinder.h : 定义类 BpBinder,为客户端基类。
- IInterface.h : 定义类 IInterface、模板类 BnInterface、模板类 BpInterface,这几个类是具体 Binder 实现中需要使用的内容。
- ProcessState.h : 定义类ProcessState,表示进程的状态。
- IPCThreadState.h : 定义类 IPCThreadState,表示 IPC 线程的状态。
从 Binder 系统对外接口的角度,IInterface 用于表示一个“接口”;BnInterface<>模板类用于表示本地的服务器端,它继承自IBinder; BpInterface 模板类用于表示客户端的代理者,它可以指向一个IBinder。
从 Binder 实现的角度,核心的内容是 BBinder 和 BpBinder 两个类,它们分别代表了最基本的服务器端及客户端。在使用的过程中,通常函数调用动作及参数都被转换成用 index 标记的数据流,通过 BpBinder.transact() 传输到远程 BBinder.onTransact(),由其完成实际操作,再将返回值写回。
ProcessState 和 IPCThreadState 实际上是 Binder 的适配层,它们和 Linux 内核中的 Binder 驱动打交道,提供 Binder 系统实现的支持。
1.1 Binder的3层结构
在Android 系统中,Java 和C++层都定义有同样功能的供应用程序使用的 Binder 接口,它们实际上都是调用原生 Binder 库的实现。
- Binder 驱动部分
驱动部分位于 Binder 结构的最底层,这部分用于实现 Binder的设备驱动,主要实现如下功能。- 组织Binder的服务节点。
- 调用Binder相关的处理线程。
- 完成实际的 Binder传输。
- Binder Adapter 层
Binder Adapter 层是对 Binder 驱动的封装,主要功能是操作 Binder 驱动。应用程序无须直接和 Binder 驱动程序关联,关联文件包括 IPCThreadState.cpp、ProcessStatecpp 和 Parcel.cpp 中的一些内容。Binder 核心库是 Binder 框架的核心实现,主要包括IBinder、Binder (服务器端)和 BpBinder (客户端)。 - 顶层
顶层的 Binder 框架和具体的客户端/服务端都分别有 Java 和 C++ 两种实现方案,主要供应用程序使用,例如:摄像头和多媒体,这部分通过调用 Binder 的核心库来实现。
在文件 frameworks/native/include/binder/IBinder.h 中定义了IBinder类,基本结构如下:
class IBinder : public virtual RefBase
{
public:
enum {
FIRST_CALL_TRANSACTION = 0x00000001,
LAST_CALL_TRANSACTION = 0x00ffffff,
PING_TRANSACTION = B_PACK_CHARS('_','P','N','G'),
DUMP_TRANSACTION = B_PACK_CHARS('_','D','M','P'),
SHELL_COMMAND_TRANSACTION = B_PACK_CHARS('_','C','M','D'),
INTERFACE_TRANSACTION = B_PACK_CHARS('_', 'N', 'T', 'F'),
SYSPROPS_TRANSACTION = B_PACK_CHARS('_', 'S', 'P', 'R'),
// Corresponds to TF_ONE_WAY -- an asynchronous call.
FLAG_ONEWAY = 0x00000001
};
IBinder();
/**
* Check if this IBinder implements the interface named by
* @a descriptor. If it does, the base pointer to it is returned,
* which you can safely static_cast<> to the concrete C++ interface.
*/
virtual sp<IInterface> queryLocalInterface(const String16& descriptor);
/**
* Return the canonical name of the interface provided by this IBinder
* object.
*/
virtual const String16& getInterfaceDescriptor() const = 0;
virtual bool isBinderAlive() const = 0;
virtual status_t pingBinder() = 0;
virtual status_t dump(int fd, const Vector<String16>& args) = 0;
static status_t shellCommand(const sp<IBinder>& target, int in, int out, int err,
Vector<String16>& args,
const sp<IResultReceiver>& resultReceiver);
virtual status_t transact( uint32_t code,
const Parcel& data,
Parcel* reply,
uint32_t flags = 0) = 0;
......
class DeathRecipient : public virtual RefBase
{
public:
virtual void binderDied(const wp<IBinder>& who) = 0;
};
}
......
IBinder 可以视为一个 Binder 通信中的传输工具。其中的 transact() 函数用于通信,当调用这个函数时,表示通过通信进行远程的调用,data 和 reply 参数分别表示参数和返回值。IBinder 类中的大多数函数为纯虚函数 (virtal ······ = 0) 是没有实现的,需要继承者来实现。
在文件 frameworks/native/include/binder/IInterface.h 中,分别定义了类 IInterface、类模板 BnInterface 和 BpInterface 。其中,类模板 BnInterface 和 BpInterface 用于实现 Service 组件和 Client 组件。
class IInterface : public virtual RefBase
{
public:
IInterface();
static sp<IBinder> asBinder(const IInterface*);
static sp<IBinder> asBinder(const sp<IInterface>&);
protected:
virtual ~IInterface();
virtual IBinder* onAsBinder() = 0;
};
template<typename INTERFACE>
class BnInterface : public INTERFACE, public BBinder
{
public:
virtual sp<IInterface> queryLocalInterface(const String16& _descriptor);
virtual const String16& getInterfaceDescriptor() const;
protected:
virtual IBinder* onAsBinder();
};
template<typename INTERFACE>
class BpInterface : public INTERFACE, public BpRefBase
{
public:
BpInterface(const sp<IBinder>& remote);
protected:
virtual IBinder* onAsBinder();
};
在使用这两个模板时,起到了双继承的作用。使用者定义一个接口 interface,然后使用 BnInterface 和 BpInterface 两个模板结合自己的接口,构建自己的 BnXXX 和 BpXXX 两个类。
1.2 BBinder类
类模板 BnInterface 继承于类 BBinder,BBinder 是服务的载体,和 binder 驱动共同工作,保证客户的请求最终是对一个 Binder 对象 (BBinder 类) 的调用。从 Binder 驱动的角度,每一个服务就是一个BBinder 类,Binder 驱动负责找出服务对应的 BBinder 类,然后把这个 BBinder 类返回给 IPCThreadState,IPCThreadState 调用 BBinder 的 transact() 。BBinder 的 transact() 又会调用 onTransact() 。BBinder::onTransact() 是虚函数,所以实际是调用 BnXXXService::onTransact(),这样就可在 BnXXXService::onTransact() 中完成具体的服务函数的调用。整个 BnXXXService 的类关系图如下所示。
Server组件的实现原理:
Client组件的实现原理:
由图可知,BnXXXService 包含如下两部分:
- IXXXService:服务的主体的接口。
- BBinder:是服务的载体,和 Binder 驱动共同工作,保证客户的请求最终是对一个 Binder 对象(BBinder类)的调用。
每一个服务就是一个 BBinder 类,Binder 驱动负责找出服务对应的 BBinder 类,然后把这个 BBinder 类返回给 IPCThreadState,IPCThreadState 调用 BBinder 的 transact() 。BBinder 的 transact() 又会调用 onTransact() 。 BBinderon::Transact() 是虚函数,所以实际是调用 BnXXXService::onTransact() ,这样就可在 BnXXXService::onTransact() 中完成具体的服务函数的调用。代码位置:frameworks/native/include/binder/Binder.h
class BBinder : public IBinder
{
public:
BBinder();
virtual const String16& getInterfaceDescriptor() const;
virtual bool isBinderAlive() const;
virtual status_t pingBinder();
virtual status_t dump(int fd, const Vector<String16>& args);
virtual status_t transact( uint32_t code,
const Parcel& data,
Parcel* reply,
uint32_t flags = 0);
virtual status_t linkToDeath(const sp<DeathRecipient>& recipient,
void* cookie = NULL,
uint32_t flags = 0);
virtual status_t unlinkToDeath( const wp<DeathRecipient>& recipient,
void* cookie = NULL,
uint32_t flags = 0,
wp<DeathRecipient>* outRecipient = NULL);
virtual void attachObject( const void* objectID,
void* object,
void* cleanupCookie,
object_cleanup_func func);
virtual void* findObject(const void* objectID) const;
virtual void detachObject(const void* objectID);
virtual BBinder* localBinder();
protected:
virtual ~BBinder();
virtual status_t onTransact( uint32_t code,
const Parcel& data,
Parcel* reply,
uint32_t flags = 0);
private:
BBinder(const BBinder& o);
BBinder& operator=(const BBinder& o);
class Extras;
std::atomic<Extras*> mExtras;
void* mReserved0;
};
在类 BBinder 中当一个 Binder 代理对象通过 Binder 驱动程序向一个 Binder 本地对象发出一个进程通信请求时,Binder 驱动程序会调用该 Binder 本地对象的成员函数 transac() 来处理这个请求。函数 transact() 在文件 frameworks/native/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;
}
在上述代码中,PING_TRANSACTION 请求用来检查对象是否还存在,此处只是简单地把 pingBinder 的返回值返回给调用者,将其他的请求交给 onTransact 来处理。onTransact 是在 BBinder 中声明的一个 protected 类型的虚函数,此功能在其子类中实现,功能是分发和业务相关的进程间通信请求。具体实现代码如下:
status_t BBinder::onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t /*flags*/)
{
switch (code) {
case INTERFACE_TRANSACTION:
reply->writeString16(getInterfaceDescriptor());
return NO_ERROR;
case DUMP_TRANSACTION: {
int fd = data.readFileDescriptor();
int argc = data.readInt32();
Vector<String16> args;
for (int i = 0; i < argc && data.dataAvail() > 0; i++) {
args.add(data.readString16());
}
return dump(fd, args);
}
case SHELL_COMMAND_TRANSACTION: {
int in = data.readFileDescriptor();
int out = data.readFileDescriptor();
int err = data.readFileDescriptor();
int argc = data.readInt32();
Vector<String16> args;
for (int i = 0; i < argc && data.dataAvail() > 0; i++) {
args.add(data.readString16());
}
sp<IResultReceiver> resultReceiver = IResultReceiver::asInterface(
data.readStrongBinder());
// XXX can't add virtuals until binaries are updated.
//return shellCommand(in, out, err, args, resultReceiver);
if (resultReceiver != NULL) {
resultReceiver->send(INVALID_OPERATION);
}
}
case SYSPROPS_TRANSACTION: {
report_sysprop_change();
return NO_ERROR;
}
default:
return UNKNOWN_TRANSACTION;
}
}
1.3 类BpRefBase
类模板 BpInterface 继承于类 BpRefBase,起到代理作用。BpReBase 以上是业务逻辑(要实现什么功能),BpRefBase 以下是数据传输(通过 binder 如何将功能实现)。在文件 frameworks/native/include/binder/Binder.h 中,定义类BpRefBase 的代码。
class BpRefBase : public virtual RefBase
{
protected:
BpRefBase(const sp<IBinder>& o);
virtual ~BpRefBase();
virtual void onFirstRef();
virtual void onLastStrongRef(const void* id);
virtual bool onIncStrongAttempted(uint32_t flags, const void* id);
//BpRefBase 类当中的 remote() 函数指向了一个IBinder。BpRefBase给代理端使用,代理端获得IBinder之后使用它来进行传输。
inline IBinder* remote() { return mRemote; }
inline IBinder* remote() const { return mRemote; }
private:
BpRefBase(const BpRefBase& o);
BpRefBase& operator=(const BpRefBase& o);
IBinder* const mRemote;
RefBase::weakref_type* mRefs;
std::atomic<int32_t> mState;
};
类 BpRefBase 中的成员函数 transact() 用于向运行在 Server 进程中的 Service 组件发送进程之间的通信请求,这是通过 Binder 驱动程序间接实现的。函数 transact() 的具体实现代码如下。
/*
code: 表示请求的ID号
data: 表示请求的参数
reply: 表示返回的结果
flags: 是一些额外的标识,例如FLAG_ONEWAY,通常为 0
*/
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.4 类IPCThreadState
前面介绍的类 BBinder 和类 BpRefBase 都是通过类 IPCThreadState 和 Binder 的驱动程序交互实现的。类 IPCThreadState 在文件 frameworks/native/include/binder/IPCThreadState.h 中实现,具体实现代码如下。
namespace android {
class IPCThreadState
{
public:
static IPCThreadState* self();
static IPCThreadState* selfOrNull(); // self(), but won't instantiate
sp<ProcessState> process();
status_t clearLastError();
pid_t getCallingPid() const;
uid_t getCallingUid() const;
void setStrictModePolicy(int32_t policy);
int32_t getStrictModePolicy() const;
void setLastTransactionBinderFlags(int32_t flags);
int32_t getLastTransactionBinderFlags() const;
int64_t clearCallingIdentity();
void restoreCallingIdentity(int64_t token);
int setupPolling(int* fd);
status_t handlePolledCommands();
void flushCommands();
void joinThreadPool(bool isMain = true);
// Stop the local process.
void stopProcess(bool immediate = true);
status_t transact(int32_t handle,
uint32_t code, const Parcel& data,
Parcel* reply, uint32_t flags);
void incStrongHandle(int32_t handle);
void decStrongHandle(int32_t handle);
void incWeakHandle(int32_t handle);
void decWeakHandle(int32_t handle);
status_t attemptIncStrongHandle(int32_t handle);
static void expungeHandle(int32_t handle, IBinder* binder);
status_t requestDeathNotification( int32_t handle,
BpBinder* proxy);
status_t clearDeathNotification( int32_t handle,
BpBinder* proxy);
static void shutdown();
// Call this to disable switching threads to background scheduling when
// receiving incoming IPC calls. This is specifically here for the
// Android system process, since it expects to have background apps calling
// in to it but doesn't want to acquire locks in its services while in
// the background.
static void disableBackgroundScheduling(bool disable);
// Call blocks until the number of executing binder threads is less than
// the maximum number of binder threads threads allowed for this process.
void blockUntilThreadAvailable();
private:
IPCThreadState();
~IPCThreadState();
status_t sendReply(const Parcel& reply, uint32_t flags);
status_t waitForResponse(Parcel *reply,
status_t *acquireResult=NULL);
status_t talkWithDriver(bool doReceive=true);
status_t writeTransactionData(int32_t cmd,
uint32_t binderFlags,
int32_t handle,
uint32_t code,
const Parcel& data,
status_t* statusBuffer);
status_t getAndExecuteCommand();
status_t executeCommand(int32_t command);
void processPendingDerefs();
void clearCaller();
static void threadDestructor(void *st);
static void freeBuffer(Parcel* parcel,
const uint8_t* data, size_t dataSize,
const binder_size_t* objects, size_t objectsSize,
void* cookie);
const sp<ProcessState> mProcess;
Vector<BBinder*> mPendingStrongDerefs;
Vector<RefBase::weakref_type*> mPendingWeakDerefs;
Parcel mIn;
Parcel mOut;
status_t mLastError;
pid_t mCallingPid;
uid_t mCallingUid;
int32_t mStrictModePolicy;
int32_t mLastTransactionBinderFlags;
};
在类 IPCThreadState 中,成员函数用于实现数据处理。在 transact 请求中将请求的数据经过 Binder 设备发送给 Service,Service 处理完请求后,又将结果原路返回给客户端。函数 transact() 在文件 frameworks/native/libs/binder/IPCThreadState.cpp 中定义,具体实现代码如下。
status_t IPCThreadState::transact(int32_t handle,
uint32_t code, const Parcel& data,
Parcel* reply, uint32_t flags)
{
status_t err = data.errorCheck();
flags |= TF_ACCEPT_FDS;
IF_LOG_TRANSACTIONS() {
TextOutput::Bundle _b(alog);
alog << "BC_TRANSACTION thr " << (void*)pthread_self() << " / hand "
<< handle << " / code " << TypeCode(code) << ": "
<< indent << data << dedent << endl;
}
if (err == NO_ERROR) {
LOG_ONEWAY(">>>> SEND from pid %d uid %d %s", getpid(), getuid(),
(flags & TF_ONE_WAY) == 0 ? "READ REPLY" : "ONE WAY");
err = writeTransactionData(BC_TRANSACTION, flags, handle, code, data, NULL);
}
if (err != NO_ERROR) {
if (reply) reply->setError(err);
return (mLastError = err);
}
if ((flags & TF_ONE_WAY) == 0) {
#if 0
if (code == 4) { // relayout
ALOGI(">>>>>> CALLING transaction 4");
} else {
ALOGI(">>>>>> CALLING transaction %d", code);
}
#endif
if (reply) {
err = waitForResponse(reply);
} else {
Parcel fakeReply;
err = waitForResponse(&fakeReply);
}
#if 0
if (code == 4) { // relayout
ALOGI("<<<<<< RETURNING transaction 4");
} else {
ALOGI("<<<<<< RETURNING transaction %d", code);
}
#endif
IF_LOG_TRANSACTIONS() {
TextOutput::Bundle _b(alog);
alog << "BR_REPLY thr " << (void*)pthread_self() << " / hand "
<< handle << ": ";
if (reply) alog << indent << *reply << dedent << endl;
else alog << "(none requested)" << endl;
}
} else {
err = waitForResponse(NULL, NULL);
}
return err;
}
1.5 IPermissionController
1.6 IServiceManager
1.7 Binder库中的其它部分
3 初始化 Java 层 Binder 框架
虽然 Java 层 Binder 系统是 Native 层 Binder 系统的一个镜像,但这个镜像终归还需借助 Native 层Binder 系统来开展工作,即它和 Native 层 Binder 有着千丝万缕的关系,故一定要在 Java 层 Binder 正式工作之前建立这种关系。本节讲解Java 层 Binder 框架的初始化过程。
3.1 搭建交互关系
在Android系统中,函数 register_android_os_Binder() (专门负责搭建 Java Binder 和 Native Binder 的交互关系)。此函数在文件 frameworks/base/core/jni/android_util_Binder.cpp 中实现。
int register_android_os_Binder(JNIEnv* env)
{
//初始化Java Binder类和Native层的关系
if (int_register_android_os_Binder(env) < 0)
return -1;
//初始化Java BinderInternel类和Native层的关系
if (int_register_android_os_BinderInternal(env) < 0)
return -1;
//初始化Java BinderProxy类和Native层的关系
if (int_register_android_os_BinderProxy(env) < 0)
return -1;
jclass clazz = FindClassOrDie(env, "android/util/Log");
gLogOffsets.mClass = MakeGlobalRefOrDie(env, clazz);
gLogOffsets.mLogE = GetStaticMethodIDOrDie(env, clazz, "e",
"(Ljava/lang/String;Ljava/lang/String;Ljava/lang/Throwable;)I");
clazz = FindClassOrDie(env, "android/os/ParcelFileDescriptor");
gParcelFileDescriptorOffsets.mClass = MakeGlobalRefOrDie(env, clazz);
gParcelFileDescriptorOffsets.mConstructor = GetMethodIDOrDie(env, clazz, "<init>",
"(Ljava/io/FileDescriptor;)V");
clazz = FindClassOrDie(env, "android/os/StrictMode");
gStrictModeCallbackOffsets.mClass = MakeGlobalRefOrDie(env, clazz);
gStrictModeCallbackOffsets.mCallback = GetStaticMethodIDOrDie(env, clazz,
"onBinderStrictModePolicyChange", "(I)V");
return 0;
}
根据上面的代码可知,函数 register_android_os_Binder() 完成了 Java 层 Binder 架构中最重要的3个类的初始化工作。下面将详细分析 Binder 类的初始化进程。
3.2 实现 Binder 类的初始化
函数 int_register_android_os_Binder() 实现了 Binder 类的初始化工作,此函数在文件 android_util_Binder.cpp 中实现,具体实现代码如下所示。
static int int_register_android_os_Binder(JNIEnv* env)
{
//kBinderPathName为 Java 层中 Binder 类的全路径名,android/os/Binder
jclass clazz = FindClassOrDie(env, kBinderPathName);
/*
gBinderOffsets 是一个静态类对象,专门保存Binder类的一些在JNI 层中使用的信息,
如:成员函数execTransact()的 methodID,Binder 类中成员mObject的fieldID
*/
gBinderOffsets.mClass = MakeGlobalRefOrDie(env, clazz);
gBinderOffsets.mExecTransact = GetMethodIDOrDie(env, clazz, "execTransact", "(IJJI)Z");
gBinderOffsets.mObject = GetFieldIDOrDie(env, clazz, "mObject", "J");
//注册Binder类中Native函数的实现
return RegisterMethodsOrDie(
env, kBinderPathName,
gBinderMethods, NELEM(gBinderMethods));
}
从上面的代码可知,gBinderOffsets 对象保存了和 Binder 类相关的某些在JNI层中使用的信息。下一个初始化的类是 BinderInternal,其代码位于 int_register_android_os_BinderInternal() 函数中。此函数在文件 android_util_Binder.cpp 中实现,具体实现代码如下。
static int int_register_android_os_BinderInternal(JNIEnv* env)
{
jclass clazz = FindClassOrDie(env, kBinderInternalPathName);
gBinderInternalOffsets.mClass = MakeGlobalRefOrDie(env, clazz);
gBinderInternalOffsets.mForceGc = GetStaticMethodIDOrDie(env, clazz, "forceBinderGc", "()V");
return RegisterMethodsOrDie(
env, kBinderInternalPathName,
gBinderInternalMethods, NELEM(gBinderInternalMethods));
}
由此可见,int_register_android_os_BinderInternal() 的功能和 int_register_android_os_Binder() 的功能类似,主要包括以下两个方面:
- 获取一些有用的 methodID 和 fieldID。这表明JNI层一定会向上调用 Java 层的函数。
- 注册相关类中native函数的实现。
3.3 实现 BinderProxy 类的初始化
函数 int_register_android_os_BinderProxy() 完成了 BinderProxy 类的初始化工作,此函数在文件android_util_Binder.cpp 中实现,具体实现代码如下。
static int int_register_android_os_BinderProxy(JNIEnv* env)
{
jclass clazz = FindClassOrDie(env, "java/lang/Error");
//gErrorOffsets用来和Error类交互
gErrorOffsets.mClass = MakeGlobalRefOrDie(env, clazz);
clazz = FindClassOrDie(env, kBinderProxyPathName);
//gBinderProxyOffsets用来和BinderProxy打交道
gBinderProxyOffsets.mClass = MakeGlobalRefOrDie(env, clazz);
gBinderProxyOffsets.mConstructor = GetMethodIDOrDie(env, clazz, "<init>", "()V");
gBinderProxyOffsets.mSendDeathNotice = GetStaticMethodIDOrDie(env, clazz, "sendDeathNotice",
"(Landroid/os/IBinder$DeathRecipient;)V");
//获取BinderProxy的一些信息
gBinderProxyOffsets.mObject = GetFieldIDOrDie(env, clazz, "mObject", "J");
gBinderProxyOffsets.mSelf = GetFieldIDOrDie(env, clazz, "mSelf",
"Ljava/lang/ref/WeakReference;");
gBinderProxyOffsets.mOrgue = GetFieldIDOrDie(env, clazz, "mOrgue", "J");
clazz = FindClassOrDie(env, "java/lang/Class");
//gClassOffsets用来和Class类交互
gClassOffsets.mGetName = GetMethodIDOrDie(env, clazz, "getName", "()Ljava/lang/String;");
// 注册BinderProxy native 函数的实现
return RegisterMethodsOrDie(
env, kBinderProxyPathName,
gBinderProxyMethods, NELEM(gBinderProxyMethods));
}
根据上面的代码可知,int_register_android_os_BinderProxy() 函数除了初始化 BinderProxy 类外,还获取了 Error 类的一些信息。到此为止,Java Binder 几个重要成员的初始化已完成,同时在代码中定义了几个全局静态对象,分别是gBinderOffsets、gBinderInternalOffsets 和 gBinderProxyOffsets。
4 实体对象 binder_node
在Android 系统中,bindcr node 用来描述一个 Binder 实体对象。每个Service 组件在 Binder 动程序中都对应有一个 Binder 实体对象,用来描述它在内核中的状态。Android 系统的 Binder 通信框架如图 5-2 所示。
4.1 定义实体对象
Binder 实体对象binder_node的定义在内核代码 binder.c 中。
struct binder_node {
int debug_id; //调试id
struct binder_work work; //描述一个待处理的工作项
union {
struct rb_node rb_node; //挂载到宿主进程binder_proc的成员变量nodes红黑树的节点
struct hlist_node dead_node; //当宿主进程死亡,该Binder实体对象将挂载到全局binder_dead_nodes 链表中
};
struct binder_proc *proc; //指向该Binder线程的宿主进程
struct hlist_head refs; //保存所有引用该Binder实体对象的Binder引用对象
int internal_strong_refs; //Binder实体对象的强引用计数
int local_weak_refs; //Binder实体对象的弱引用计数
int local_strong_refs;
binder_uintptr_t ptr;
binder_uintptr_t cookie;
unsigned has_strong_ref:1;
unsigned pending_strong_ref:1;
unsigned has_weak_ref:1;
unsigned pending_weak_ref:1;
unsigned has_async_transaction:1; //标示该Binder实体对象是否正在处理一个异步事务
unsigned accept_fds:1; //设置该Binder实体对象是否可以接收包含有文件描述符的IPC数据
unsigned min_priority:8; //Binder实体对象要求处理线程应具备的最小线程优先级
struct list_head async_todo; //异步事务队列
};
通过上述代码可知,在Binder 驱动中,用户空间中的每一个 Binder 本地对象都对应有一个 Binder 实体对象。各个成员的具体说明如下所示:
- proc : 指向 Binder 实体对象的宿主进程,宿主进程使用红黑树来维护其内部的所有 Binder 实体对象。
- rbnode : 用来挂载到宿主进程 proc 的 Binder 实体对象红黑树中的节点。
- dead_node : 如果该 Binder 实体对象的宿主进程已经死亡,该 Binder 实体就通过成员变量 dead_node 保存到全局链表 binder_dead_nodes。
- refs : 一个Binder 实体对象可以被多个 client 引用,成员变量 refs 用来保存所有引用该 Binder
实体的 Binder 引用对象。 - internal_strong_refs 和 local_strong_refs : 都是用来描述 Binder 实体对象的强引用计数。
- local_weak_refs : 用来描述 Binder 实体对象的弱引用计数。
- ptr 和 cookie : 分别指向用户空间地址,cookie 指向 BBinder 的地址,ptr 指向 BBinder 对象的引用计数地址。
- has_async_transaction : 描述一个 Binder 实体对象是否正在处理一个异步事务,当 Binder 驱动指定某个线程来处理某一事务时,首先将该事务保存到指定线程的 todo 队列中,表示要由该线程来处理该事务。如果是异步事务,Binder 驱动程序就会将它保存在目标 Binder 实体对象的一个异步事务队列 async_todo 中。
- min_priority : 表示一个 Binder 实体对象在处理来自 client 进程请求时,要求处理线程的最小线程优先级。
4.2 增加引用计数
在 Binder 驱动程序中,使用函数 binder_inc_node() 来增加一个 Binder 实体对象的引用计数。函数binder_inc_node() 在文件内核代码 binder.c 中定义,具体实现代码如下。
/**
各个参数的具体说明如下所示:
node : 表示要增加引用计数的 Binder 实体对象。
strong : 表示要增加强引用计数还是要增加弱引用计数。
internal : 用于区分增加的是内部引用计数还是外部引用计数。
target_list : 用于指向一个目标进程或目标线程的 todo 队列,当不是null值时表示增加了Binder实体对象的引用计数后,需要对应增加它所引用的Binder本地对象的引用计数。
*/
static int binder_inc_node(struct binder_node *node, int strong, int internal,
struct list_head *target_list)
{
if (strong) {
if (internal) {
if (target_list == NULL &&
node->internal_strong_refs == 0 &&
!(node == binder_context_mgr_node &&
node->has_strong_ref)) {
pr_err("invalid inc strong node for %d\n",
node->debug_id);
return -EINVAL;
}
node->internal_strong_refs++;
} else
node->local_strong_refs++;
if (!node->has_strong_ref && target_list) {
list_del_init(&node->work.entry);
list_add_tail(&node->work.entry, target_list);
}
} else {
if (!internal)
node->local_weak_refs++;
if (!node->has_weak_ref && list_empty(&node->work.entry)) {
if (target_list == NULL) {
pr_err("invalid inc weak node for %d\n",
node->debug_id);
return -EINVAL;
}
list_add_tail(&node->work.entry, target_list);
}
}
return 0;
}
4.3 减少引用计数
与函数 binder_inc_node() 相反,在 Binder 驱动程序中,使用函数 binder_dec_node() 来减少一个 Binder 实体对象的引用计数。函数 binder_dec_node() 会减少 internal_strong_refs、local_strong_refs 或 local_weak_refs 的使用计数并删除节点的 work.entry 链表。
static int binder_dec_node(struct binder_node *node, int strong, int internal)
{
if (strong) {
if (internal)
node->internal_strong_refs--;
else
node->local_strong_refs--;
if (node->local_strong_refs || node->internal_strong_refs)
return 0;
} else {
if (!internal)
node->local_weak_refs--;
if (node->local_weak_refs || !hlist_empty(&node->refs))
return 0;
}
if (node->proc && (node->has_strong_ref || node->has_weak_ref)) {
if (list_empty(&node->work.entry)) {
list_add_tail(&node->work.entry, &node->proc->todo);
wake_up_interruptible(&node->proc->wait);
}
} else {
if (hlist_empty(&node->refs) && !node->local_strong_refs &&
!node->local_weak_refs) {
list_del_init(&node->work.entry);
if (node->proc) {
rb_erase(&node->rb_node, &node->proc->nodes);
binder_debug(BINDER_DEBUG_INTERNAL_REFS,
"refless node %d deleted\n",
node->debug_id);
} else {
hlist_del(&node->dead_node);
binder_debug(BINDER_DEBUG_INTERNAL_REFS,
"dead node %d deleted\n",
node->debug_id);
}
kfree(node);
binder_stats_deleted(BINDER_STAT_NODE);
}
}
return 0;
}
5 本地对象BBinder
因为 Binder 的功能就是在本地执行其他进程的功能,所以对于 Binder 机制来说,不但是 Android 系统中的一个完美的IPC机制,其实也是 Android 的一种远程过程调用(RPC)机制。当进程通过 Binder 获取将要调用的进程服务时,不但可以是一个本地对象,也可以是一个远程服务的引用。也就是说,Binder 不但可以与本地进程通信,还可以与远程进程通信。此处的本地进程就是本节所讲解的本地对象,而远程进程就是远程服务的一个引用。
5.1 引用了运行的本地对象
在Android 系统中,Binder 驱动程序通过函数 binder_thread_read() 引用了运行在 Server 进程中的Binder 本地对象,此函数在内核代码 binder.c 中定义。当 service_manager 运行时此函数会一直等待,直到有请求到达为止。
static int binder_thread_read(struct binder_proc *proc,
struct binder_thread *thread,
binder_uintptr_t binder_buffer, size_t size,
binder_size_t *consumed, int non_block)
{
void __user *buffer = (void __user *)(uintptr_t)binder_buffer;
void __user *ptr = buffer + *consumed;
void __user *end = buffer + size;
int ret = 0;
int wait_for_proc_work;
if (*consumed == 0) {
if (put_user_preempt_disabled(BR_NOOP, (uint32_t __user *)ptr))
return -EFAULT;
ptr += sizeof(uint32_t);
}
retry:
wait_for_proc_work = thread->transaction_stack == NULL &&
list_empty(&thread->todo);
if (thread->return_error != BR_OK && ptr < end) {
if (thread->return_error2 != BR_OK) {
if (put_user_preempt_disabled(thread->return_error2, (uint32_t __user *)ptr))
return -EFAULT;
ptr += sizeof(uint32_t);
binder_stat_br(proc, thread, thread->return_error2);
if (ptr == end)
goto done;
thread->return_error2 = BR_OK;
}
if (put_user_preempt_disabled(thread->return_error, (uint32_t __user *)ptr))
return -EFAULT;
ptr += sizeof(uint32_t);
binder_stat_br(proc, thread, thread->return_error);
thread->return_error = BR_OK;
goto done;
}
thread->looper |= BINDER_LOOPER_STATE_WAITING;
if (wait_for_proc_work)
proc->ready_threads++;
binder_unlock(__func__);
trace_binder_wait_for_work(wait_for_proc_work,
!!thread->transaction_stack,
!list_empty(&thread->todo));
if (wait_for_proc_work) {
if (!(thread->looper & (BINDER_LOOPER_STATE_REGISTERED |
BINDER_LOOPER_STATE_ENTERED))) {
binder_user_error("%d:%d ERROR: Thread waiting for process work before calling BC_REGISTER_LOOPER or BC_ENTER_LOOPER (state %x)\n",
proc->pid, thread->pid, thread->looper);
wait_event_interruptible(binder_user_error_wait,
binder_stop_on_user_error < 2);
}
binder_set_nice(proc->default_priority);
if (non_block) {
if (!binder_has_proc_work(proc, thread))
ret = -EAGAIN;
} else
ret = wait_event_freezable_exclusive(proc->wait, binder_has_proc_work(proc, thread));
} else {
if (non_block) {
if (!binder_has_thread_work(thread))
ret = -EAGAIN;
} else
ret = wait_event_freezable(thread->wait, binder_has_thread_work(thread));
}
binder_lock(__func__);
if (wait_for_proc_work)
proc->ready_threads--;
thread->looper &= ~BINDER_LOOPER_STATE_WAITING;
if (ret)
return ret;
while (1) {
uint32_t cmd;
//将用户传进来的transact 参数复制到本地变量 struct binder_transaction_data tr 中
struct binder_transaction_data tr;
struct binder_work *w;
struct binder_transaction *t = NULL;
//由于thread->todo非空,执行下列语句
if (!list_empty(&thread->todo))
w = list_first_entry(&thread->todo, struct binder_work, entry);
else if (!list_empty(&proc->todo) && wait_for_proc_work)
//ServiceManager 被唤醒之后,就进入while 循环开始处理事务了
//此处 wait_for_proc_work 等于1,并且 proc-todo 不为空,所以从 proc-todo 列表中得到第一个工作项
w = list_first_entry(&proc->todo, struct binder_work, entry);
else {
if (ptr - buffer == 4 && !(thread->looper & BINDER_LOOPER_STATE_NEED_RETURN)) /* no data added */
goto retry;
break;
}
if (end - ptr < sizeof(tr) + 4)
break;
switch (w->type) {
//函数调用binder_transaction进一步处理
case BINDER_WORK_TRANSACTION: {
//因为这个工作项的类型为BINDER_WORK_TRANSACTION,所以通过下面语句得到事务项
t = container_of(w, struct binder_transaction, work);
} break;
//因为w->type 为BINDER_WORK_TRANSACTION_COMPLETE
//这是在上面的 binder_transaction()函数中设置的,于是执行下面的代码
case BINDER_WORK_TRANSACTION_COMPLETE: {
cmd = BR_TRANSACTION_COMPLETE;
if (put_user_preempt_disabled(cmd, (uint32_t __user *)ptr))
return -EFAULT;
ptr += sizeof(uint32_t);
binder_stat_br(proc, thread, cmd);
binder_debug(BINDER_DEBUG_TRANSACTION_COMPLETE,
"%d:%d BR_TRANSACTION_COMPLETE\n",
proc->pid, thread->pid);
//将w从thread->todo删除
list_del(&w->entry);
kfree(w);
binder_stats_deleted(BINDER_STAT_TRANSACTION_COMPLETE);
} break;
case BINDER_WORK_NODE: {
struct binder_node *node = container_of(w, struct binder_node, work);
uint32_t cmd = BR_NOOP;
const char *cmd_name;
int strong = node->internal_strong_refs || node->local_strong_refs;
int weak = !hlist_empty(&node->refs) || node->local_weak_refs || strong;
if (weak && !node->has_weak_ref) {
cmd = BR_INCREFS;
cmd_name = "BR_INCREFS";
node->has_weak_ref = 1;
node->pending_weak_ref = 1;
node->local_weak_refs++;
} else if (strong && !node->has_strong_ref) {
cmd = BR_ACQUIRE;
cmd_name = "BR_ACQUIRE";
node->has_strong_ref = 1;
node->pending_strong_ref = 1;
node->local_strong_refs++;
} else if (!strong && node->has_strong_ref) {
cmd = BR_RELEASE;
cmd_name = "BR_RELEASE";
node->has_strong_ref = 0;
} else if (!weak && node->has_weak_ref) {
cmd = BR_DECREFS;
cmd_name = "BR_DECREFS";
node->has_weak_ref = 0;
}
if (cmd != BR_NOOP) {
if (put_user_preempt_disabled(cmd, (uint32_t __user *)ptr))
return -EFAULT;
ptr += sizeof(uint32_t);
if (put_user_preempt_disabled(node->ptr,
(binder_uintptr_t __user *)ptr))
return -EFAULT;
ptr += sizeof(binder_uintptr_t);
if (put_user_preempt_disabled(node->cookie,
(binder_uintptr_t __user *)ptr))
return -EFAULT;
ptr += sizeof(binder_uintptr_t);
binder_stat_br(proc, thread, cmd);
binder_debug(BINDER_DEBUG_USER_REFS,
"%d:%d %s %d u%016llx c%016llx\n",
proc->pid, thread->pid, cmd_name,
node->debug_id,
(u64)node->ptr, (u64)node->cookie);
} else {
list_del_init(&w->entry);
if (!weak && !strong) {
binder_debug(BINDER_DEBUG_INTERNAL_REFS,
"%d:%d node %d u%016llx c%016llx deleted\n",
proc->pid, thread->pid, node->debug_id,
(u64)node->ptr, (u64)node->cookie);
rb_erase(&node->rb_node, &proc->nodes);
kfree(node);
binder_stats_deleted(BINDER_STAT_NODE);
} else {
binder_debug(BINDER_DEBUG_INTERNAL_REFS,
"%d:%d node %d u%016llx c%016llx state unchanged\n",
proc->pid, thread->pid, node->debug_id,
(u64)node->ptr, (u64)node->cookie);
}
}
} break;
case BINDER_WORK_DEAD_BINDER:
case BINDER_WORK_DEAD_BINDER_AND_CLEAR:
case BINDER_WORK_CLEAR_DEATH_NOTIFICATION: {
struct binder_ref_death *death;
uint32_t cmd;
death = container_of(w, struct binder_ref_death, work);
if (w->type == BINDER_WORK_CLEAR_DEATH_NOTIFICATION)
cmd = BR_CLEAR_DEATH_NOTIFICATION_DONE;
else
cmd = BR_DEAD_BINDER;
if (put_user_preempt_disabled(cmd, (uint32_t __user *)ptr))
return -EFAULT;
ptr += sizeof(uint32_t);
if (put_user_preempt_disabled(death->cookie,
(binder_uintptr_t __user *)ptr))
return -EFAULT;
ptr += sizeof(binder_uintptr_t);
binder_stat_br(proc, thread, cmd);
binder_debug(BINDER_DEBUG_DEATH_NOTIFICATION,
"%d:%d %s %016llx\n",
proc->pid, thread->pid,
cmd == BR_DEAD_BINDER ?
"BR_DEAD_BINDER" :
"BR_CLEAR_DEATH_NOTIFICATION_DONE",
(u64)death->cookie);
if (w->type == BINDER_WORK_CLEAR_DEATH_NOTIFICATION) {
list_del(&w->entry);
kfree(death);
binder_stats_deleted(BINDER_STAT_DEATH);
} else
list_move(&w->entry, &proc->delivered_death);
if (cmd == BR_DEAD_BINDER)
goto done; /* DEAD_BINDER notifications can cause transactions */
} break;
}
if (!t)
continue;
BUG_ON(t->buffer == NULL);
//把事务项t中的数据复制到本地局部变量struct binder_transaction_data tr 中
if (t->buffer->target_node) {
struct binder_node *target_node = t->buffer->target_node;
tr.target.ptr = target_node->ptr;
tr.cookie = target_node->cookie;
t->saved_priority = task_nice(current);
if (t->priority < target_node->min_priority &&
!(t->flags & TF_ONE_WAY))
binder_set_nice(t->priority);
else if (!(t->flags & TF_ONE_WAY) ||
t->saved_priority > target_node->min_priority)
binder_set_nice(target_node->min_priority);
cmd = BR_TRANSACTION;
} else {
tr.target.ptr = 0;
tr.cookie = 0;
cmd = BR_REPLY;
}
tr.code = t->code;
tr.flags = t->flags;
tr.sender_euid = from_kuid(current_user_ns(), t->sender_euid);
if (t->from) {
struct task_struct *sender = t->from->proc->tsk;
tr.sender_pid = task_tgid_nr_ns(sender,
task_active_pid_ns(current));
} else {
tr.sender_pid = 0;
}
tr.data_size = t->buffer->data_size;
tr.offsets_size = t->buffer->offsets_size;
/*
t->buffer->data 所指向的地址是内核空间的,如果要把数据返回给 Service Manager 进程的用户空间
而Service Manager 进程的用户空间是不能访问内核空间的数据的,所以需要进一步处理
在具体处理时,Binder 机制使用类似浅拷贝的方法,通过在用户空间分配一个虚拟地址
然后让这个用户空间虚拟地址与 t->buffer->data 这个内核空间虚拟地址指向同一个物理地址
在此只需将t->buffer->data 加上一个偏移值 proc->user_buffer_offset
就可以得到t->buffer->data 对应的用户空间虚拟地址了
在调整了tr.data.ptr.buffer 值后,需要一起调整tr.data.ptr.offsets 的值
*/
tr.data.ptr.buffer = (binder_uintptr_t)(
(uintptr_t)t->buffer->data +
proc->user_buffer_offset);
tr.data.ptr.offsets = tr.data.ptr.buffer +
ALIGN(t->buffer->data_size,
sizeof(void *));
//把tr的内容复制到用户传进来的缓冲区,指针ptr 指向这个用户缓冲区的地址
if (put_user_preempt_disabled(cmd, (uint32_t __user *)ptr))
return -EFAULT;
ptr += sizeof(uint32_t);
if (copy_to_user_preempt_disabled(ptr, &tr, sizeof(tr)))
return -EFAULT;
ptr += sizeof(tr);
//上述代码只是对 tr.data.ptr.bufferr 和 tr.data.ptr.ffsets 的内容进行了浅拷贝工作
trace_binder_transaction_received(t);
binder_stat_br(proc, thread, cmd);
binder_debug(BINDER_DEBUG_TRANSACTION,
"%d:%d %s %d %d:%d, cmd %d size %zd-%zd ptr %016llx-%016llx\n",
proc->pid, thread->pid,
(cmd == BR_TRANSACTION) ? "BR_TRANSACTION" :
"BR_REPLY",
t->debug_id, t->from ? t->from->proc->pid : 0,
t->from ? t->from->pid : 0, cmd,
t->buffer->data_size, t->buffer->offsets_size,
(u64)tr.data.ptr.buffer, (u64)tr.data.ptr.offsets);
//从todo列表中删除,因为已经处理了这个事务
list_del(&t->work.entry);
t->buffer->allow_user_free = 1;
//如果cmd== BR_TRANSACTION && !(t->fags &TF_ONE_WAY)为true
//说明虽然在驱动程序中已经处理完了这个事务,但是仍然要在Service Manager 完成之后等待回复确认
if (cmd == BR_TRANSACTION && !(t->flags & TF_ONE_WAY)) {
//把当前事务t放在thread->transaction_stack 队列的头部
t->to_parent = thread->transaction_stack;
t->to_thread = thread;
thread->transaction_stack = t;
} else { //如果为false 则不需要等待回复了,而是直接删除事务t
t->buffer->transaction = NULL;
kfree(t);
binder_stats_deleted(BINDER_STAT_TRANSACTION);
}
break;
}
done:
*consumed = ptr - buffer;
if (proc->requested_threads + proc->ready_threads == 0 &&
proc->requested_threads_started < proc->max_threads &&
(thread->looper & (BINDER_LOOPER_STATE_REGISTERED |
BINDER_LOOPER_STATE_ENTERED)) /* the user-space code fails to */
/*spawn a new thread if we leave this out */) {
proc->requested_threads++;
binder_debug(BINDER_DEBUG_THREADS,
"%d:%d BR_SPAWN_LOOPER\n",
proc->pid, thread->pid);
if (put_user_preempt_disabled(BR_SPAWN_LOOPER, (uint32_t __user *)buffer))
return -EFAULT;
binder_stat_br(proc, thread, BR_SPAWN_LOOPER);
}
return 0;
}
由此可见,Binder 驱动程序是通过如下 4 个协议来引用运行在 Server 进程中的 Binder 本地对象的:
- BR_INCREFS
- BR_ACQUIRE
- BR_DECREFS
- BR_RELEASE
5.2 处理接口协议
在文件 frameworks/native/libs/binder/IPCThreadState.cpp 中,通过使用类成员函数executeCommand() 来处理上节中的4个接口协议。
status_t IPCThreadState::executeCommand(int32_t cmd)
{
BBinder* obj;
RefBase::weakref_type* refs;
status_t result = NO_ERROR;
switch ((uint32_t)cmd) {
case BR_ERROR:
result = mIn.readInt32();
break;
case BR_OK:
break;
case BR_ACQUIRE:
refs = (RefBase::weakref_type*)mIn.readPointer();
obj = (BBinder*)mIn.readPointer();
ALOG_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.writePointer((uintptr_t)refs);
mOut.writePointer((uintptr_t)obj);
break;
case BR_RELEASE:
refs = (RefBase::weakref_type*)mIn.readPointer();
obj = (BBinder*)mIn.readPointer();
ALOG_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.readPointer();
obj = (BBinder*)mIn.readPointer();
refs->incWeak(mProcess.get());
mOut.writeInt32(BC_INCREFS_DONE);
mOut.writePointer((uintptr_t)refs);
mOut.writePointer((uintptr_t)obj);
break;
case BR_DECREFS:
refs = (RefBase::weakref_type*)mIn.readPointer();
obj = (BBinder*)mIn.readPointer();
// NOTE: This assertion is not valid, because the object may no
// longer exist (thus the (BBinder*)cast above resulting in a different
// memory address).
//ALOG_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.readPointer();
obj = (BBinder*)mIn.readPointer();
{
const bool success = refs->attemptIncStrong(mProcess.get());
ALOG_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));
ALOG_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 binder_size_t*>(tr.data.ptr.offsets),
tr.offsets_size/sizeof(binder_size_t), freeBuffer, this);
const pid_t origPid = mCallingPid;
const uid_t origUid = mCallingUid;
const int32_t origStrictModePolicy = mStrictModePolicy;
const int32_t origTransactionBinderFlags = mLastTransactionBinderFlags;
mCallingPid = tr.sender_pid;
mCallingUid = tr.sender_euid;
mLastTransactionBinderFlags = tr.flags;
int curPrio = getpriority(PRIO_PROCESS, mMyThreadId);
if (gDisableBackgroundScheduling) {
if (curPrio > ANDROID_PRIORITY_NORMAL) {
// We have inherited a reduced priority from the caller, but do not
// want to run in that state in this process. The driver set our
// priority already (though not our scheduling class), so bounce
// it back to the default before invoking the transaction.
setpriority(PRIO_PROCESS, mMyThreadId, ANDROID_PRIORITY_NORMAL);
}
} else {
if (curPrio >= ANDROID_PRIORITY_BACKGROUND) {
// We want to use the inherited priority from the caller.
// Ensure this thread is in the background scheduling class,
// since the driver won't modify scheduling classes for us.
// The scheduling group is reset to default by the caller
// once this method returns after the transaction is complete.
set_sched_policy(mMyThreadId, SP_BACKGROUND);
}
}
//ALOGI(">>>> TRANSACT from pid %d uid %d\n", mCallingPid, mCallingUid);
Parcel reply;
status_t error;
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) {
// We only have a weak reference on the target object, so we must first try to
// safely acquire a strong reference before doing anything else with it.
if (reinterpret_cast<RefBase::weakref_type*>(
tr.target.ptr)->attemptIncStrong(this)) {
error = reinterpret_cast<BBinder*>(tr.cookie)->transact(tr.code, buffer,
&reply, tr.flags);
reinterpret_cast<BBinder*>(tr.cookie)->decStrong(this);
} else {
error = UNKNOWN_TRANSACTION;
}
} else {
error = the_context_object->transact(tr.code, buffer, &reply, tr.flags);
}
//ALOGI("<<<< 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);
if (error < NO_ERROR) reply.setError(error);
sendReply(reply, 0);
} else {
LOG_ONEWAY("NOT sending reply to %d!", mCallingPid);
}
mCallingPid = origPid;
mCallingUid = origUid;
mStrictModePolicy = origStrictModePolicy;
mLastTransactionBinderFlags = origTransactionBinderFlags;
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.readPointer();
proxy->sendObituary();
mOut.writeInt32(BC_DEAD_BINDER_DONE);
mOut.writePointer((uintptr_t)proxy);
} break;
case BR_CLEAR_DEATH_NOTIFICATION_DONE:
{
BpBinder *proxy = (BpBinder*)mIn.readPointer();
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;
}
通过上述代码可知,在函数 executeCommand() 中会调用 BBinder::transact() 来处理 Client 端的请求。当需要多个线程提供服务时,驱动会请求创建新线程。具体创建某线程的过程,可以通过上述函数处理 BR_SPAWN_LOOPER 协议的过程获得。
6 引用对象 binder_ref
struct binder_ref {
/* Lookups needed: */
/* node + proc => ref (transaction) */
/* desc + proc => ref (transaction, inc/dec ref) */
/* node => refs + procs (proc exit) */
int debug_id; //调试id
struct rb_node rb_node_desc; //挂载到宿主对象binder_proc的红黑树refs_by_desc中的节点
struct rb_node rb_node_node; //挂载到宿主对象binder_proc的红黑树refs_by_node中的节点
struct hlist_node node_entry; //挂载到Binder实体对象的refs链表中的节点
struct binder_proc *proc; //Binder引用对象的宿主进程binder_proc
struct binder_node *node; //Binder引用对象所引用的Binder实体对象
uint32_t desc; //Binder引用对象的句柄值
int strong; //强引用计数
int weak; //弱引用计数
struct binder_ref_death *death; //注册死亡接收通知
};
在 Binder 机制中,binder_ref 用来描述一个 Binder 引用对象,每一个 client 在 Binder 驱动中都有个 binder 引用对象。各个成员变量的具体说明如下所示。
- 成员变量 node : 保存了该 Binder 引用对象所引用的 Binder 实体对象,Binder 实体对象使用链表保存了所有引用该实体对象的 Binder 引用对象。
- node_entry : 是该 Binder 引用对象所引用的实体对象的成员变量 refs 链表中的节点。
- desc : 是一个句柄值,用来描述一个 Binder 引用对象。
- node : 当 Client 进程通过句柄值来访问某个 Service 时,Binder 驱动程序可以通过该句柄值找到对应的 Binder引用对象,然后根据该 Binder 引用对象的成员变量 node 找到对应的 Binder 实体对象,最后通过该 Binder 实体对象找到要访问的 Service。
- proc : 执行该 Binder 引用对象的宿主进程。
- rb_node_desc 和 rb_node_node : 是 binder_proc 中红黑树 refs_by_desc 和 refs_by_node 的节点。
Binder 驱动程序存在如下4个重要的协议,用于增加和减少 Binder 引用对象的强引用计数和弱引用计数:
- BR_INCREFS
- BR_ACQUIRE
- BR_DECREFS
- BR_RELEASE
上述计数处理功能通过函数 binder_thread_write() 实现,此函数在内核驱动 binder.c 中定义。协议BR_INCREFS 和 BR_ACOUIRE 用于增加一个 Binder 引用对象的强引用计数和弱引用计数,此功能是通过调用函数 binder_inc_ref() 实现的,具体代码如下所示。
static int binder_inc_ref(struct binder_ref *ref, int strong,
struct list_head *target_list)
{
int ret;
if (strong) {
if (ref->strong == 0) {
ret = binder_inc_node(ref->node, 1, 1, target_list);
if (ret)
return ret;
}
ref->strong++;
} else {
if (ref->weak == 0) {
ret = binder_inc_node(ref->node, 0, 1, target_list);
if (ret)
return ret;
}
ref->weak++;
}
return 0;
}
而协议 BR_RELEASE 和 BR_DECREFS 用于减少一个 Binder 引用对象的强引用计数和弱引用计数,此功能是通过调用函数 binder_dec_ref() 实现的,具体代码如下:
static int binder_dec_ref(struct binder_ref **ptr_to_ref, int strong)
{
struct binder_ref *ref = *ptr_to_ref;
if (strong) {
if (ref->strong == 0) {
binder_user_error("%d invalid dec strong, ref %d desc %d s %d w %d\n",
ref->proc->pid, ref->debug_id,
ref->desc, ref->strong, ref->weak);
return -EINVAL;
}
ref->strong--;
if (ref->strong == 0) {
int ret;
ret = binder_dec_node(ref->node, strong, 1);
if (ret)
return ret;
}
} else {
if (ref->weak == 0) {
binder_user_error("%d invalid dec weak, ref %d desc %d s %d w %d\n",
ref->proc->pid, ref->debug_id,
ref->desc, ref->strong, ref->weak);
return -EINVAL;
}
ref->weak--;
}
if (ref->strong == 0 && ref->weak == 0) {
binder_delete_ref(ref);
*ptr_to_ref = NULL;
}
return 0;
}
再看函数 binder_delete_ref(),功能是销毁binder ref对象。
static void binder_delete_ref(struct binder_ref *ref)
{
binder_debug(BINDER_DEBUG_INTERNAL_REFS,
"%d delete ref %d desc %d for node %d\n",
ref->proc->pid, ref->debug_id, ref->desc,
ref->node->debug_id);
rb_erase(&ref->rb_node_desc, &ref->proc->refs_by_desc);
rb_erase(&ref->rb_node_node, &ref->proc->refs_by_node);
if (ref->strong)
binder_dec_node(ref->node, 1, 1);
hlist_del(&ref->node_entry);
binder_dec_node(ref->node, 0, 1);
if (ref->death) {
binder_debug(BINDER_DEBUG_DEAD_BINDER,
"%d delete ref %d desc %d has death notification\n",
ref->proc->pid, ref->debug_id, ref->desc);
list_del(&ref->death->work.entry);
kfree(ref->death);
binder_stats_deleted(BINDER_STAT_DEATH);
}
kfree(ref);
binder_stats_deleted(BINDER_STAT_REF);
}
7 代理对象 BpBinder
在Android 系统中,代理对象 BpBinder 是远程对象在当前进程的代理,它实现了 IBinder 接口。对于初学者来说,BBinder 与 BpBinder 这两者容易混淆。**其实这两者很好区分,对于Service 来说继承了BBinder(BnInterface),因为 BBinder 有 onTransact() 消息处理函数。而对于与 Service 通信的 Client 来说,需要继承 BpBinder(BpInterface),因为 BpBinder 有消息传递函数 transact() **。
7.1 创建 Binder 代理对象
以 cameraService 的 client 为例,文件 Camera.cpp 中的函数 getCameraService() 能够获取远程CameraService 的IBinder 对象,然后通过如下代码进行了重构,得到了 BpCameraService 对象。
mCameraService = interface_cast<ICameraService>(binder);
而BpCameraService 继承了 BpInterface,并传入了BBinder。
cameraService:
defaultServiceManager()->addService(
String16("media.camera"), new CameraService());
在IPC传递的过程中,IBinder 指针不可缺少。这个指针对一个进程来说就像是 socket 的 ID 一样是唯一的。无论这个 IBinder 是 BBinder 还是 BpBinder,它们都是在重构 BpBinder 或者 BBinder 时把 IBinder 作为参数传入的。在Android系统中,创建 Binder 代理对象的方法在文件 frameworks/native/libs/binder/BpBinder.cpp 中定义,具体代码如下所示。
BpBinder::BpBinder(int32_t handle)
: mHandle(handle)
, mAlive(1)
, mObitsSent(0)
, mObituaries(NULL)
{
ALOGV("Creating BpBinder %p handle %d\n", this, mHandle);
//设置Binder代理对象的生命周期受到弱引用的计数影响
extendObjectLifetime(OBJECT_LIFETIME_WEAK);
//调用当前线程内部的IPCThreadState的成员函数incWeakHandle()增加相应的Binder引用对象的弱引用计数
IPCThreadState::self()->incWeakHandle(handle);
}
在文件frameworks/native/libs/binder/IPCThreadState.cpp 中,定义成员函数incWeakHandle() 的代码。
void IPCThreadState::incWeakHandle(int32_t handle)
{
LOG_REMOTEREFS("IPCThreadState::incWeakHandle(%d)\n", handle);
mOut.writeInt32(BC_INCREFS);
mOut.writeInt32(handle);
}
7.2 销毁 Binder 代理对象
当销毁一个Binder代理对象时,线程会调用内部的IPCThreadState对象的成员函数decWeakHandle0来减少相应的 Binder 引用对象的弱引用计数。函数decWeakHandle0的具体实现代码如下所示。
void IPCThreadState::decWeakHandle(int32_t handle)
{
LOG_REMOTEREFS("IPCThreadState::decWeakHandle(%d)\n", handle);
mOut.writeInt32(BC_DECREFS);
mOut.writeInt32(handle);
}
在Binder 代理对象中,其 transact0函数的实现代码如下所示。
/*
各个参数的具体说明如下所示:
code:表示请求的ID号。
data:表示请求的参数。
reply:表示返回的结果。
flags:表示一些额外的标识,如FLAG_ONEWAY,通常为0
*/
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() 函数只是简单调用了 IPCThreadState::self() 的 transact,IPCThreadState::transact 中的代码如下。
status_t IPCThreadState::transact(int32_t handle,
uint32_t code, const Parcel& data,
Parcel* reply, uint32_t flags)
{
status_t err = data.errorCheck();
flags |= TF_ACCEPT_FDS;
IF_LOG_TRANSACTIONS() {
TextOutput::Bundle _b(alog);
alog << "BC_TRANSACTION thr " << (void*)pthread_self() << " / hand "
<< handle << " / code " << TypeCode(code) << ": "
<< indent << data << dedent << endl;
}
if (err == NO_ERROR) {
LOG_ONEWAY(">>>> SEND from pid %d uid %d %s", getpid(), getuid(),
(flags & TF_ONE_WAY) == 0 ? "READ REPLY" : "ONE WAY");
err = writeTransactionData(BC_TRANSACTION, flags, handle, code, data, NULL);
}
if (err != NO_ERROR) {
if (reply) reply->setError(err);
return (mLastError = err);
}
if ((flags & TF_ONE_WAY) == 0) {
#if 0
if (code == 4) { // relayout
ALOGI(">>>>>> CALLING transaction 4");
} else {
ALOGI(">>>>>> CALLING transaction %d", code);
}
#endif
if (reply) {
err = waitForResponse(reply);
} else {
Parcel fakeReply;
err = waitForResponse(&fakeReply);
}
#if 0
if (code == 4) { // relayout
ALOGI("<<<<<< RETURNING transaction 4");
} else {
ALOGI("<<<<<< RETURNING transaction %d", code);
}
#endif
IF_LOG_TRANSACTIONS() {
TextOutput::Bundle _b(alog);
alog << "BR_REPLY thr " << (void*)pthread_self() << " / hand "
<< handle << ": ";
if (reply) alog << indent << *reply << dedent << endl;
else alog << "(none requested)" << endl;
}
} else {
err = waitForResponse(NULL, NULL);
}
return err;
}
status_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult)
{
uint32_t cmd;
int32_t err;
while (1) {
if ((err=talkWithDriver()) < NO_ERROR) break;
err = mIn.errorCheck();
if (err < NO_ERROR) break;
if (mIn.dataAvail() == 0) continue;
cmd = (uint32_t)mIn.readInt32();
IF_LOG_COMMANDS() {
alog << "Processing waitForResponse Command: "
<< getReturnString(cmd) << endl;
}
switch (cmd) {
case BR_TRANSACTION_COMPLETE:
if (!reply && !acquireResult) goto finish;
break;
case BR_DEAD_REPLY:
err = DEAD_OBJECT;
goto finish;
case BR_FAILED_REPLY:
err = FAILED_TRANSACTION;
goto finish;
case BR_ACQUIRE_RESULT:
{
ALOG_ASSERT(acquireResult != NULL, "Unexpected brACQUIRE_RESULT");
const int32_t result = mIn.readInt32();
if (!acquireResult) continue;
*acquireResult = result ? NO_ERROR : INVALID_OPERATION;
}
goto finish;
case BR_REPLY:
{
binder_transaction_data tr;
err = mIn.read(&tr, sizeof(tr));
ALOG_ASSERT(err == NO_ERROR, "Not enough command data for brREPLY");
if (err != NO_ERROR) goto finish;
if (reply) {
if ((tr.flags & TF_STATUS_CODE) == 0) {
reply->ipcSetDataReference(
reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer),
tr.data_size,
reinterpret_cast<const binder_size_t*>(tr.data.ptr.offsets),
tr.offsets_size/sizeof(binder_size_t),
freeBuffer, this);
} else {
err = *reinterpret_cast<const status_t*>(tr.data.ptr.buffer);
freeBuffer(NULL,
reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer),
tr.data_size,
reinterpret_cast<const binder_size_t*>(tr.data.ptr.offsets),
tr.offsets_size/sizeof(binder_size_t), this);
}
} else {
freeBuffer(NULL,
reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer),
tr.data_size,
reinterpret_cast<const binder_size_t*>(tr.data.ptr.offsets),
tr.offsets_size/sizeof(binder_size_t), this);
continue;
}
}
goto finish;
default:
err = executeCommand(cmd);
if (err != NO_ERROR) goto finish;
break;
}
}
finish:
if (err != NO_ERROR) {
if (acquireResult) *acquireResult = err;
if (reply) reply->setError(err);
mLastError = err;
}
return err;
}
在上述代码中,通过内核模块 transact 将请求发送给服务端。当服务端处理完请求之后,会沿着原路返回结果给调用者。在此可以看出请求是同步操作,它会等待直到结果返回为止。这样在 BpBinder 之上进行简单包装之后,就可以得到与服务对象相同的接口,调用者无须关心调用的对象是远程的还是本地的。