在通过Service调用,了解Java与Binder驱动的通信机制(上)我们说到了Service
客户端调用ServiceManager
的getService
,本篇我们将看看Service
服务端的相关方法是如何被调用的,这里为了表述方便,可以先说明,在Service
服务端最终会调用BBinder
的onTransact
方法,如果是java环境的话会调用继承BBinder
的JavaBBinder
的onTransact
方法,这一点将在下文中作出解释。在Android 进程中binder主线程启动流程中我们可以知道binder线程最后调用了 IPCThreadState::self()->joinThreadPool( true)
:
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 {
processPendingDerefs();
// now get the next command to be processed, waiting if necessary
result = getAndExecuteCommand();
if (result < NO_ERROR && result != TIMED_OUT && result != -ECONNREFUSED && result != -EBADF) {
ALOGE("getAndExecuteCommand(fd=%d) returned unexpected error %d, aborting",
mProcess->mDriverFD, result);
abort();
}
// 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=%d\n",
(void*)pthread_self(), getpid(), result);
mOut.writeInt32(BC_EXIT_LOOPER);
talkWithDriver(false);
}
该函数会通过getAndExecuteCommand()
读取驱动发送过来的命令并执行:
status_t IPCThreadState::getAndExecuteCommand()
{
status_t result;
int32_t cmd;
result = talkWithDriver();
if (result >= NO_ERROR) {
size_t IN = mIn.dataAvail();
if (IN < sizeof(int32_t)) return result;
cmd = mIn.readInt32();
....
}
....
result = executeCommand(cmd);
....
}
return result;
}
talkWithDriver
会与驱动进行通信,并获取数据写入mIn
中,然后读取cmd
,调用executeCommand
:
status_t IPCThreadState::executeCommand(int32_t cmd)
{
....
switch ((uint32_t)cmd) {
case BR_TRANSACTION:
{
binder_transaction_data tr;
result = mIn.read(&tr, sizeof(tr));
if (tr.target.ptr) {
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);
}
if ((tr.flags & TF_ONE_WAY) == 0) {
sendReply(reply, 0);
}
....
}
break;
....
return result;
}
这里注意error = reinterpret_cast<BBinder*>(tr.cookie)->transact(tr.code, buffer,&reply, tr.flags)
,他根据驱动传过来的tr.cookie
调用了BBinder
的transact
方法,BBinder
方法在\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 != nullptr) {
reply->setDataPosition(0);
}
return err;
}
也就调用到了BBinder
的onTransact
方法,所以在C层如果要写自己的BBinder
服务,直接继承BBinder
然后重写onTransact
方法即可。回到上面,tr.cookie
到底是什么呢?他又为何会出现在这里呢?仔细想想,这肯定和addService
有关,在addService
的时候我们将引用传入到驱动层,之后驱动层发现客户端要引用该服务,就将tr.cookie
返回给我们,让我们可以去调用,实际情况也大致如此。首先来看ServiceManager
的addService
:
@UnsupportedAppUsage
public static void addService(String name, IBinder service, boolean allowIsolated,
int dumpPriority) {
try {
getIServiceManager().addService(name, service, allowIsolated, dumpPriority);
} catch (RemoteException e) {
Log.e(TAG, "error in addService", e);
}
}
这里的getIServiceManager()
在上篇中已经分析过了,就是ServiceManagerProxy
,其在\frameworks\base\core\java\android\os\ServiceManagerNative.java
中:
public void addService(String name, IBinder service, boolean allowIsolated, int dumpPriority)
throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IServiceManager.descriptor);
data.writeString(name);
data.writeStrongBinder(service);
data.writeInt(allowIsolated ? 1 : 0);
data.writeInt(dumpPriority);
mRemote.transact(ADD_SERVICE_TRANSACTION, data, reply, 0);
reply.recycle();
data.recycle();
}
这里首先看data.writeStrongBinder(service)
public final void writeStrongBinder(IBinder val) {
nativeWriteStrongBinder(mNativePtr, val);
}
nativeWriteStrongBinder
是本地方法,对应方法在\frameworks\base\core\jni\android_os_Parcel.cpp
:
static void android_os_Parcel_writeStrongBinder(JNIEnv* env, jclass clazz, jlong nativePtr, jobject object)
{
Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
if (parcel != NULL) {
const status_t err = parcel->writeStrongBinder(ibinderForJavaObject(env, object));
if (err != NO_ERROR) {
signalExceptionForError(env, clazz, err);
}
}
}
首先来看ibinderForJavaObject
:
sp<IBinder> ibinderForJavaObject(JNIEnv* env, jobject obj)
{
if (obj == NULL) return NULL;
// Instance of Binder?
if (env->IsInstanceOf(obj, gBinderOffsets.mClass)) {
JavaBBinderHolder* jbh = (JavaBBinderHolder*)
env->GetLongField(obj, gBinderOffsets.mObject);
return jbh->get(env, obj);
}
// Instance of BinderProxy?
if (env->IsInstanceOf(obj, gBinderProxyOffsets.mClass)) {
return getBPNativeData(env, obj)->mObject;
}
ALOGW("ibinderForJavaObject: %p is not a Binder object", obj);
return NULL;
}
在了解这个函数之前,我们需要知道,在Android系统中,在Java初创时期,系统会提前注册一些JNI函数,其中有一个函数专门负责搭建Java Binder和Native Binder交互关系,该函数是register_android_os_Binder,代码如下:
int register_android_os_Binder(JNIEnv* env)
{
if (int_register_android_os_Binder(env) < 0)
return -1;
if (int_register_android_os_BinderInternal(env) < 0)
return -1;
if (int_register_android_os_BinderProxy(env) < 0)
return -1;
....
return 0;
}
其中int_register_android_os_Binder
如下:
const char* const kBinderPathName = "android/os/Binder";
static int int_register_android_os_Binder(JNIEnv* env)
{
jclass clazz = FindClassOrDie(env, kBinderPathName);
gBinderOffsets.mClass = MakeGlobalRefOrDie(env, clazz);
gBinderOffsets.mExecTransact = GetMethodIDOrDie(env, clazz, "execTransact", "(IJJI)Z");
gBinderOffsets.mGetInterfaceDescriptor = GetMethodIDOrDie(env, clazz, "getInterfaceDescriptor",
"()Ljava/lang/String;");
gBinderOffsets.mObject = GetFieldIDOrDie(env, clazz, "mObject", "J");
return RegisterMethodsOrDie(
env, kBinderPathName,
gBinderMethods, NELEM(gBinderMethods));
}
这方法里面对gBinderOffsets
相关的方法和属性进行了设置,大家可以看到mClass
类名其实是android/os/Binder
,而我们的在addService
时,传入的Service对象就继承android.os.Binder
对象,同时注意这里还对execTransact和mObject进行了声明。回到ibinderForJavaObject
,就知道了,我们调用的是:
// Instance of Binder?
if (env->IsInstanceOf(obj, gBinderOffsets.mClass)) {
JavaBBinderHolder* jbh = (JavaBBinderHolder*)
env->GetLongField(obj, gBinderOffsets.mObject);
return jbh->get(env, obj);
}
这里会发现从传入的Service对象中的mObject
对象获取了native层面的JavaBBinderHolder
,为什么可以获取java层mObject,以及他什么时候变成了JavaBBinderHolder
指针,这个稍后解答。之后在ibinderForJavaObject
调用了JavaBBinderHolder
的get
方法,就可以获取一个native层面new
出来的JavaBBinder
对象,其继承Binder
,并持有java层传入的Service对象:
class JavaBBinderHolder
{
public:
sp<JavaBBinder> get(JNIEnv* env, jobject obj)
{
AutoMutex _l(mLock);
sp<JavaBBinder> b = mBinder.promote();
if (b == NULL) {
b = new JavaBBinder(env, obj);
mBinder = b;
ALOGV("Creating JavaBinder %p (refs %p) for Object %p, weakCount=%" PRId32 "\n",
b.get(), b->getWeakRefs(), obj, b->getWeakRefs()->getWeakCount());
}
return b;
}
sp<JavaBBinder> getExisting()
{
AutoMutex _l(mLock);
return mBinder.promote();
}
private:
Mutex mLock;
wp<JavaBBinder> mBinder;
};
回到android_os_Parcel_writeStrongBinder
函数,调用完ibinderForJavaObject
函数之后,就要调用parcel->writeStrongBinder
对应方法在\frameworks\native\libs\binder\Parcel.cpp
中:
status_t Parcel::writeStrongBinder(const sp<IBinder>& val)
{
return flatten_binder(ProcessState::self(), val, this);
}
status_t flatten_binder(const sp<ProcessState>& /*proc*/,
const wp<IBinder>& binder, Parcel* out)
{
flat_binder_object obj;
obj.flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;
if (binder != nullptr) {
sp<IBinder> real = binder.promote();
if (real != nullptr) {
IBinder *local = real->localBinder();
if (!local) {
BpBinder *proxy = real->remoteBinder();
if (proxy == nullptr) {
ALOGE("null proxy");
}
const int32_t handle = proxy ? proxy->handle() : 0;
obj.hdr.type = BINDER_TYPE_WEAK_HANDLE;
obj.binder = 0; /* Don't pass uninitialized stack data to a remote process */
obj.handle = handle;
obj.cookie = 0;
} else {
obj.hdr.type = BINDER_TYPE_WEAK_BINDER;
obj.binder = reinterpret_cast<uintptr_t>(binder.get_refs());
obj.cookie = reinterpret_cast<uintptr_t>(binder.unsafe_get());
}
return finish_flatten_binder(real, obj, out);
}
// XXX How to deal? In order to flatten the given binder,
// we need to probe it for information, which requires a primary
// reference... but we don't have one.
//
// The OpenBinder implementation uses a dynamic_cast<> here,
// but we can't do that with the different reference counting
// implementation we are using.
ALOGE("Unable to unflatten Binder weak reference!");
obj.hdr.type = BINDER_TYPE_BINDER;
obj.binder = 0;
obj.cookie = 0;
return finish_flatten_binder(nullptr, obj, out);
} else {
obj.hdr.type = BINDER_TYPE_BINDER;
obj.binder = 0;
obj.cookie = 0;
return finish_flatten_binder(nullptr, obj, out);
}
}
这里binder.promote()
返回的还是binder
,而real->remoteBinder()
对于BBinder
(因为上面分析过了,传入的是一个JavaBBinder
继承BBinder
)而言:
BHwBinder* BHwBinder::localBinder()
{
return this;
}
返回的也是自己,所以local
就是我们传入的BBinder
,所以下面的判断走的就是else
:
obj.hdr.type = BINDER_TYPE_WEAK_BINDER;
obj.binder = reinterpret_cast<uintptr_t>(binder.get_refs());
obj.cookie = reinterpret_cast<uintptr_t>(binder.unsafe_get());
注意这里的obj.cookie
设置为了我们JavaBBinder
的引用,也就回答了上面的问题,我们确实把进程中的JavaBBinder
引用写到了驱动中去。之后执行命令的时候就会调用JavaBBinder
的onTransact
方法,又调用到java层的onTransact
方法。java层的onTransact
方法就是AIDL生成文件中的方法啦。
最后回答关于JavaBBinderHolder
的问题,他上面时候被设置到了java层Service对象中的mObject中去的。这个首先要看Binder的构造函数:
public Binder() {
this(null);
}
public Binder(@Nullable String descriptor) {
mObject = getNativeBBinderHolder();
NoImagePreloadHolder.sRegistry.registerNativeAllocation(this, mObject);
if (FIND_POTENTIAL_LEAKS) {
final Class<? extends Binder> klass = getClass();
if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
(klass.getModifiers() & Modifier.STATIC) == 0) {
Log.w(TAG, "The following Binder class should be static or leaks might occur: " +
klass.getCanonicalName());
}
}
mDescriptor = descriptor;
}
注意看getNativeBBinderHolder()
,相信这应该已经很明显了,该函数对应的本地方法在\frameworks\base\core\jni\android_util_Binder.cpp
为:
static jlong android_os_Binder_getNativeBBinderHolder(JNIEnv* env, jobject clazz)
{
JavaBBinderHolder* jbh = new JavaBBinderHolder();
return (jlong) jbh;
}
java层的Service又是继承binder
的,所以父类的构造函数肯定会被调用到。