java层Binder——BinderProxy类
BinderProxy类实际上是java层Binder机制中客户端Proxy的mRemote成员变量。在Proxy中,客户端调用服务端IPC业务接口时,首先便会通过proxy中的业务接口去调用mRemote.transact,mRemote自然就是Proxy的成员变量,是一个IBinder类,这个IBinder只是一个Binder功能接口,它实际上就是由BinderProxy向上转型得来的。
一、实例化
在java层代码中很难找到这个类实例化的地方,那是因为这个类一般都是被放到native层去进行实例化的。这里举一个简单的例子,当我在IMyAidlInterface中增加一个接口,该接口需要传递一个Binder。这样,在IMyAidlInterface服务端接收到客户端传过来的Bidner时,自然会自己实例化一个Proxy,我们由此可以看看它是怎样实例化的。
interface IMyAidlInterface {
void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
double aDouble, String aString);
void BinderTest(IMyAidlInterface inetrface);
}
经过编译后,可以看到Stub中关于BinderTest的接口实现如下:
@Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException
{
……
case TRANSACTION_BinderTest:
{
data.enforceInterface(descriptor);
com.example.bindertest.IMyAidlInterface _arg0;
_arg0 = com.example.bindertest.IMyAidlInterface.Stub.asInterface(data.readStrongBinder());
this.BinderTest(_arg0);
reply.writeNoException();
return true;
}
……
}
是的,在从客户端获取到一个Binder后,他会通过data.readStrongBinder()方法获取到一个Binder客户端。进入到Parcel后,会发现该接口实际只是一个native方法的封装。
public final IBinder readStrongBinder() {
return nativeReadStrongBinder(mNativePtr);
}
由此可以看出,java层中对Binder客户端的实例化,实际上是在native层实现的。在进入native层看代码。
static jobject android_os_Parcel_readStrongBinder(JNIEnv* env, jclass clazz, jlong nativePtr)
{
Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
if (parcel != NULL) {
return javaObjectForIBinder(env, parcel->readStrongBinder());
}
return NULL;
}
nativeReadStrongBinder方法对应到native层,便是android_os_Parcel_readStrongBinder方法。这个函数中,最终会嗲用javaObjectForIBinder方法来获取一个java层的Binder客户端。
jobject javaObjectForIBinder(JNIEnv* env, const sp<IBinder>& val)
{
// N.B. This function is called from a @FastNative JNI method, so don't take locks around
// calls to Java code or block the calling thread for a long time for any reason.
if (val == NULL) return NULL;
if (val->checkSubclass(&gBinderOffsets)) {
// It's a JavaBBinder created by ibinderForJavaObject. Already has Java object.
jobject object = static_cast<JavaBBinder*>(val.get())->object();
LOGDEATH("objectForBinder %p: it's our own %p!\n", val.get(), object);
return object;
}
BinderProxyNativeData* nativeData = new BinderProxyNativeData();
nativeData->mOrgue = new DeathRecipientList;
nativeData->mObject = val;
jobject object = env->CallStaticObjectMethod(gBinderProxyOffsets.mClass,
gBinderProxyOffsets.mGetInstance, (jlong) nativeData, (jlong) val.get());
if (env->ExceptionCheck()) {
// In the exception case, getInstance still took ownership of nativeData.
return NULL;
}
BinderProxyNativeData* actualNativeData = getBPNativeData(env, object);
if (actualNativeData == nativeData) {
// Created a new Proxy
uint32_t numProxies = gNumProxies.fetch_add(1, std::memory_order_relaxed);
uint32_t numLastWarned = gProxiesWarned.load(std::memory_order_relaxed);
if (numProxies >= numLastWarned + PROXY_WARN_INTERVAL) {
// Multiple threads can get here, make sure only one of them gets to
// update the warn counter.
if (gProxiesWarned.compare_exchange_strong(numLastWarned,
numLastWarned + PROXY_WARN_INTERVAL, std::memory_order_relaxed)) {
ALOGW("Unexpectedly many live BinderProxies: %d\n", numProxies);
}
}
} else {
delete nativeData;
}
return object;
}
在这个方法中,实例化java层Binder客户端的关键语句便是:
jobject object = env->CallStaticObjectMethod(gBinderProxyOffsets.mClass,
gBinderProxyOffsets.mGetInstance, (jlong) nativeData, (jlong) val.get());
而gBinderProxyOffsets结构体中,mClass和mGetInstance的赋值是在jni注册过程时完成的,代码如下:
const char* const kBinderProxyPathName = "android/os/BinderProxy";
static int int_register_android_os_BinderProxy(JNIEnv* env)
{
gErrorOffsets.mError = MakeGlobalRefOrDie(env, FindClassOrDie(env, "java/lang/Error"));
gErrorOffsets.mOutOfMemory =
MakeGlobalRefOrDie(env, FindClassOrDie(env, "java/lang/OutOfMemoryError"));
gErrorOffsets.mStackOverflow =
MakeGlobalRefOrDie(env, FindClassOrDie(env, "java/lang/StackOverflowError"));
jclass clazz = FindClassOrDie(env, kBinderProxyPathName);
gBinderProxyOffsets.mClass = MakeGlobalRefOrDie(env, clazz);
gBinderProxyOffsets.mGetInstance = GetStaticMethodIDOrDie(env, clazz, "getInstance",
"(JJ)Landroid/os/BinderProxy;");
gBinderProxyOffsets.mSendDeathNotice =
GetStaticMethodIDOrDie(env, clazz, "sendDeathNotice",
"(Landroid/os/IBinder$DeathRecipient;Landroid/os/IBinder;)V");
gBinderProxyOffsets.mNativeData = GetFieldIDOrDie(env, clazz, "mNativeData", "J");
clazz = FindClassOrDie(env, "java/lang/Class");
gClassOffsets.mGetName = GetMethodIDOrDie(env, clazz, "getName", "()Ljava/lang/String;");
return RegisterMethodsOrDie(
env, kBinderProxyPathName,
gBinderProxyMethods, NELEM(gBinderProxyMethods));
}
现在已经很明显了,java层的Binder客户端实际上就是BinderProxy。
二、构造和初始化
private static BinderProxy getInstance(long nativeData, long iBinder) {
BinderProxy result;
synchronized (sProxyMap) {
try {
result = sProxyMap.get(iBinder);
if (result != null) {
return result;
}
result = new BinderProxy(nativeData);
} catch (Throwable e) {
// We're throwing an exception (probably OOME); don't drop nativeData.
NativeAllocationRegistry.applyFreeFunction(NoImagePreloadHolder.sNativeFinalizer,
nativeData);
throw e;
}
NoImagePreloadHolder.sRegistry.registerNativeAllocation(result, nativeData);
// The registry now owns nativeData, even if registration threw an exception.
sProxyMap.set(iBinder, result);
}
return result;
}
private BinderProxy(long nativeData) {
mNativeData = nativeData;
}
BinderProxy的构造函数很简单,首先它时private函数,需要通过getInstance方法来完成实例化,但getInstance也是一个private方法,且在自身类中没有调用该方法的地方。这当然是因为它本身只提供给native层调用,调用过程上面有分析。此外在BinderProxy的构造函数中,还传入了一个nativeData,它是native层的一个BinderProxyNativeData对象指针,在native层需要用到该指针。
三、transact
BinderProxy的关键函数自然就是transact,java层的Binder客户端就是通过该函数进行Binder通信的。而该函数本质上也是调用的native层接口。函数中的关键语句如下:
public boolean transact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
……
try {
return transactNative(code, data, reply, flags);
} finally {
AppOpsManager.resumeNotedAppOpsCollection(prevCollection);
if (transactListener != null) {
transactListener.onTransactEnded(session);
}
if (tracingEnabled) {
Trace.traceEnd(Trace.TRACE_TAG_ALWAYS);
}
}
……
}
BinderProxy通过调用native层的transactNative方法来进行Binder通信。该方法对应到native的方法名是android_os_BinderProxy_transact。
static jboolean android_os_BinderProxy_transact(JNIEnv* env, jobject obj,
jint code, jobject dataObj, jobject replyObj, jint flags) // throws RemoteException
{
if (dataObj == NULL) {
jniThrowNullPointerException(env, NULL);
return JNI_FALSE;
}
Parcel* data = parcelForJavaObject(env, dataObj);
if (data == NULL) {
return JNI_FALSE;
}
Parcel* reply = parcelForJavaObject(env, replyObj);
if (reply == NULL && replyObj != NULL) {
return JNI_FALSE;
}
IBinder* target = getBPNativeData(env, obj)->mObject.get(); //获取C++层Bp端Binder(就是C++层的客户端Binder)
if (target == NULL) {
jniThrowException(env, "java/lang/IllegalStateException", "Binder has been finalized!");
return JNI_FALSE;
}
ALOGV("Java code calling transact on %p in Java object %p with code %" PRId32 "\n",
target, obj, code);
bool time_binder_calls;
int64_t start_millis;
if (kEnableBinderSample) {
// Only log the binder call duration for things on the Java-level main thread.
// But if we don't
time_binder_calls = should_time_binder_calls();
if (time_binder_calls) {
start_millis = uptimeMillis();
}
}
//printf("Transact from Java code to %p sending: ", target); data->print();
status_t err = target->transact(code, *data, reply, flags); //通过Bp端Binder进行Binder通信
//if (reply) printf("Transact from Java code to %p received: ", target); reply->print();
if (kEnableBinderSample) {
if (time_binder_calls) {
conditionally_log_binder_call(start_millis, target, code);
}
}
if (err == NO_ERROR) {
return JNI_TRUE;
} else if (err == UNKNOWN_TRANSACTION) {
return JNI_FALSE;
}
signalExceptionForError(env, obj, err, true /*canThrowRemoteException*/, data->dataSize());
return JNI_FALSE;
}