每天一篇系列:
强化知识体系,查漏补缺。
欢迎指正,共同学习!
目标:注册一个自定义的服务,实现跨进程通信。
JAVA方法:
先定义一个AIDL接口:
package com.test.lib;
interface IMyService {
void setValue(int val);
int getValue();
}
继承接口Stub:
package com.test.myservice;
import android.os.RemoteException;
import com.test.lib.IMyService;
public class MyService extends IMyService.Stub {
private int value;
@Override
public void setValue(int val) throws RemoteException {
this.value = val;
}
@Override
public int getValue() throws RemoteException {
return value;
}
}
通过ServiceManager注册服务:
package com.test.myservice;
import android.app.Application;
import android.os.ServiceManager;
public class MyServiceApplication extends Application{
@Override
public void onCreate() {
super.onCreate();
ServiceManager.addService("MYSERVICE", new MyService());
}
}
服务注册后,就可以通过以下方式获得这个自定义的Service:
IMyService myservice = IMyService.Stub.asInterface(ServiceManager.getService("MYSERVICE"));
那么为什么可以这样做到跨进程通信呢?
首先分析服务的注册:
public static void addService(String name, IBinder service) {
try {
getIServiceManager().addService(name, service, false);
} catch (RemoteException e) {
Log.e(TAG, "error in addService", e);
}
}
private static IServiceManager getIServiceManager() {
if (sServiceManager != null) {
return sServiceManager;
}
// Find the service manager
sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());
return sServiceManager;
}
从这里看的话,有两个知识点需要分析。
ServiceManagerNative.asInterface:
static public IServiceManager asInterface(IBinder obj)
{
if (obj == null) {
return null;
}
IServiceManager in =
(IServiceManager)obj.queryLocalInterface(descriptor);
if (in != null) {
return in;
}
return new ServiceManagerProxy(obj);
}
另外一个知识点BinderInternal.getContextObject():
public static final native IBinder getContextObject();
getContextObject是一个native方法,在android_util_Binder.cpp中创建了Java层Binder和Native层Bindler的通信,在JNI层需要先注册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;
jclass clazz;
clazz = env->FindClass("android/util/Log");
LOG_FATAL_IF(clazz == NULL, "Unable to find class android.util.Log");
gLogOffsets.mClass = (jclass) env->NewGlobalRef(clazz);
gLogOffsets.mLogE = env->GetStaticMethodID(
clazz, "e", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/Throwable;)I");
assert(gLogOffsets.mLogE);
clazz = env->FindClass("android/os/ParcelFileDescriptor");
LOG_FATAL_IF(clazz == NULL, "Unable to find class android.os.ParcelFileDescriptor");
gParcelFileDescriptorOffsets.mClass = (jclass) env->NewGlobalRef(clazz);
gParcelFileDescriptorOffsets.mConstructor
= env->GetMethodID(clazz, "", "(Ljava/io/FileDescriptor;)V");
clazz = env->FindClass("android/os/StrictMode");
LOG_FATAL_IF(clazz == NULL, "Unable to find class android.os.StrictMode");
gStrictModeCallbackOffsets.mClass = (jclass) env->NewGlobalRef(clazz);
gStrictModeCallbackOffsets.mCallback = env->GetStaticMethodID(
clazz, "onBinderStrictModePolicyChange", "(I)V");
LOG_FATAL_IF(gStrictModeCallbackOffsets.mCallback == NULL,
"Unable to find strict mode callback.");
return 0;
}
const char* const kBinderPathName = "android/os/Binder";
static int int_register_android_os_Binder(JNIEnv* env)
{
jclass clazz;
clazz = env->FindClass(kBinderPathName);
LOG_FATAL_IF(clazz == NULL, "Unable to find class android.os.Binder");
gBinderOffsets.mClass = (jclass) env->NewGlobalRef(clazz);
gBinderOffsets.mExecTransact
= env->GetMethodID(clazz, "execTransact", "(IJJI)Z");
assert(gBinderOffsets.mExecTransact);
gBinderOffsets.mObject
= env->GetFieldID(clazz, "mObject", "J");
assert(gBinderOffsets.mObject);
return AndroidRuntime::registerNativeMethods(
env, kBinderPathName,
gBinderMethods, NELEM(gBinderMethods));
}
static void android_os_Binder_init(JNIEnv* env, jobject obj)
{
JavaBBinderHolder* jbh = new JavaBBinderHolder();
if (jbh == NULL) {
jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
return;
}
ALOGV("Java Binder %p: acquiring first ref on holder %p", obj, jbh);
jbh->incStrong((void*)android_os_Binder_init);
env->SetLongField(obj, gBinderOffsets.mObject, (jlong)jbh);
}
static int int_register_android_os_BinderProxy(JNIEnv* env)
{
jclass clazz;
clazz = env->FindClass("java/lang/Error");
LOG_FATAL_IF(clazz == NULL, "Unable to find class java.lang.Error");
gErrorOffsets.mClass = (jclass) env->NewGlobalRef(clazz);
clazz = env->FindClass(kBinderProxyPathName);
LOG_FATAL_IF(clazz == NULL, "Unable to find class android.os.BinderProxy");
gBinderProxyOffsets.mClass = (jclass) env->NewGlobalRef(clazz);
gBinderProxyOffsets.mConstructor
= env->GetMethodID(clazz, "", "()V");
assert(gBinderProxyOffsets.mConstructor);
gBinderProxyOffsets.mSendDeathNotice
= env->GetStaticMethodID(clazz, "sendDeathNotice", "(Landroid/os/IBinder$DeathRecipient;)V");
assert(gBinderProxyOffsets.mSendDeathNotice);
gBinderProxyOffsets.mObject
= env->GetFieldID(clazz, "mObject", "J");
assert(gBinderProxyOffsets.mObject);
gBinderProxyOffsets.mSelf
= env->GetFieldID(clazz, "mSelf", "Ljava/lang/ref/WeakReference;");
assert(gBinderProxyOffsets.mSelf);
gBinderProxyOffsets.mOrgue
= env->GetFieldID(clazz, "mOrgue", "J");
assert(gBinderProxyOffsets.mOrgue);
clazz = env->FindClass("java/lang/Class");
LOG_FATAL_IF(clazz == NULL, "Unable to find java.lang.Class");
gClassOffsets.mGetName = env->GetMethodID(clazz, "getName", "()Ljava/lang/String;");
assert(gClassOffsets.mGetName);
return AndroidRuntime::registerNativeMethods(
env, kBinderProxyPathName,
gBinderProxyMethods, NELEM(gBinderProxyMethods));
}
来看BinderInternal:
static jobject android_os_BinderInternal_getContextObject(JNIEnv* env, jobject clazz)
{
sp b = ProcessState::self()->getContextObject(NULL);
return javaObjectForIBinder(env, b);
}
ProcessState::self()->getContextObject(NULL);返回的是service_manager创建的BpBinder(0)。javaObjectForIBinder如下:
jobject javaObjectForIBinder(JNIEnv* env, const sp& val)
{
//安全检查,BpBinder(0)创建一次后就不会为NULL
if (val == NULL) return NULL;
//注意gBinderOffsets,在通过反射JAVA类,如果是Java的Binder类,则val.get()的是JavaBBinder?
if (val->checkSubclass(&gBinderOffsets)) {
jobject object = static_cast(val.get())->object();
LOGDEATH("objectForBinder %p: it's our own %p!\n", val.get(), object);
return object;
}
AutoMutex _l(mProxyLock);
//注意gBinderProxyOffsets,如果之前已经创建过BinderProxy并且把BinderProxy保存到val的Object中,就先删掉
jobject object = (jobject)val->findObject(&gBinderProxyOffsets);
if (object != NULL) {
jobject res = jniGetReferent(env, object);
if (res != NULL) {
ALOGV("objectForBinder %p: found existing %p!\n", val.get(), res);
return res;
}
LOGDEATH("Proxy object %p of IBinder %p no longer in working set!!!", object, val.get());
android_atomic_dec(&gNumProxyRefs);
val->detachObject(&gBinderProxyOffsets);
env->DeleteGlobalRef(object);
}
//注意gBinderProxyOffsets初始化,创建一个新的BinderProxy对象。并将它注册到Native BpBinder对象的ObjectManager中
object = env->NewObject(gBinderProxyOffsets.mClass, gBinderProxyOffsets.mConstructor);
if (object != NULL) {
LOGDEATH("objectForBinder %p: created new proxy %p !\n", val.get(), object);
// The proxy holds a reference to the native object.
//把Native层的BpProxy的指针保存到BinderProxy对象的成员字段mObject中。于是BinderProxy对象的Native方法可以通过mObject获取BpProxy对象的指针。这个操作是将BinderProxy与BpProxy联系起来的纽带
env->SetLongField(object, gBinderProxyOffsets.mObject, (jlong)val.get());
val->incStrong((void*)javaObjectForIBinder);
// The native object needs to hold a weak reference back to the
// proxy, so we can retrieve the same proxy if it is still active.
jobject refObject = env->NewGlobalRef(
env->GetObjectField(object, gBinderProxyOffsets.mSelf));
// 将这个新创建的BinderProxy对象注册(attach)到BpBinder的ObjectManager中,同时注册一个回收函数proxy_cleanup。当BinderProxy对象撤销(detach)的时候,该函数会被调用,以释放一些资源。
val->attachObject(&gBinderProxyOffsets, refObject,
jnienv_to_javavm(env), proxy_cleanup);
// Also remember the death recipients registered on this proxy
sp drl = new DeathRecipientList;
drl->incStrong((void*)javaObjectForIBinder);
env->SetLongField(object, gBinderProxyOffsets.mOrgue, reinterpret_cast(drl.get()));
// Note that a new object reference has been created.
android_atomic_inc(&gNumProxyRefs);
incRefsCreated(env);
}
//这里的object就是创建出来的BinderProxy
return object;
}
创建了一个BinderProxy对象,通过JNI,把BinderProxy对象和一个Native的BpProxy(在这里是BpBinder(0))对象挂钩,而该BpProxy对象的通信目标就是ServiceManager。
再来分析IServiceManager的asInterface:
sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());
public abstract class ServiceManagerNative extends Binder implements IServiceManager
{
static public IServiceManager asInterface(IBinder obj)
{
if (obj == null) {
return null;
}
//这里的obj实际上就是native层通过JNI创建的BinderProxy,因此这里返回为null
IServiceManager in =
(IServiceManager)obj.queryLocalInterface(descriptor);
if (in != null) {
return in;
}
return new ServiceManagerProxy(obj);
}
...
class ServiceManagerProxy implements IServiceManager {
public ServiceManagerProxy(IBinder remote) {
mRemote = remote;
}
public IBinder asBinder() {
return mRemote;
}
...
public void addService(String name, IBinder service, boolean allowIsolated)
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);
mRemote.transact(ADD_SERVICE_TRANSACTION, data, reply, 0);
reply.recycle();
data.recycle();
}
...
传递给ServiceManagerProxy的参数正是BinderInternal.getContextObject()创建的BinderProxy,也就是说mRemote的调用就是BinderProxy的调用。
[特别留意:在addService方法中data.writeStrongBinder(service)后面会使用到]
继续分析transact:
final class BinderProxy implements IBinder {
...
public boolean transact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
Binder.checkParcel(this, code, data, "Unreasonably large binder buffer");
return transactNative(code, data, reply, flags);
}
public native boolean transactNative(int code, Parcel data, Parcel reply,
int flags) throws RemoteException;
...
static void checkParcel(IBinder obj, int code, Parcel parcel, String msg) {
if (CHECK_PARCEL_SIZE && parcel.dataSize() >= 800*1024) {
// Trying to send > 800k, this is way too much
StringBuilder sb = new StringBuilder();
sb.append(msg);
sb.append(": on ");
sb.append(obj);
sb.append(" calling ");
sb.append(code);
sb.append(" size ");
sb.append(parcel.dataSize());
sb.append(" (data: ");
parcel.setDataPosition(0);
sb.append(parcel.readInt());
sb.append(", ");
sb.append(parcel.readInt());
sb.append(", ");
sb.append(parcel.readInt());
sb.append(")");
Slog.wtfStack(TAG, sb.toString());
}
}
可以看到Binder在的CHECK_PARCEL_SIZE开关打开的情况下,可以校验Binder传输最大字节数是800K。transactNative是JNI方法:
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;
}
// java的参数转换为c层的参数类型
Parcel* data = parcelForJavaObject(env, dataObj);
if (data == NULL) {
return JNI_FALSE;
}
Parcel* reply = parcelForJavaObject(env, replyObj);
if (reply == NULL && replyObj != NULL) {
return JNI_FALSE;
}
// 从obj(在BinderInternal.getContextObject()创建的BinderProxy)中获取BpProxy,因为之前已经把BpBinder(0)保存在gBinderProxyOffsets.mObject中
IBinder* target = (IBinder*)
env->GetLongField(obj, gBinderProxyOffsets.mObject);
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);
#if ENABLE_BINDER_SAMPLE
// Only log the binder call duration for things on the Java-level main thread.
// But if we don't
const bool time_binder_calls = should_time_binder_calls();
int64_t start_millis;
if (time_binder_calls) {
start_millis = uptimeMillis();
}
#endif
//printf("Transact from Java code to %p sending: ", target); data->print();
// 从mObject中获取的BpProxy即BpBinder(0),调用transact ,那么就会在service_manager处理。
status_t err = target->transact(code, *data, reply, flags);
//if (reply) printf("Transact from Java code to %p received: ", target); reply->print();
#if ENABLE_BINDER_SAMPLE
if (time_binder_calls) {
conditionally_log_binder_call(start_millis, target, code);
}
#endif
if (err == NO_ERROR) {
return JNI_TRUE;
} else if (err == UNKNOWN_TRANSACTION) {
return JNI_FALSE;
}
signalExceptionForError(env, obj, err, true /*canThrowRemoteException*/);
return JNI_FALSE;
}
这样就把Java层Service的注册交给了Native层的service_manager。
服务的注册:
ServiceManager.addService("MYSERVICE", new MyService());
addService时data.writeStrongBinder(service)这个参数需要是IBinder,而MyService继承了Binder,Binder又继承于IBinder:
public class MyService extends IMyService.Stub {
...
}
AIDL文件编译后如下:
/*
* This file is auto-generated. DO NOT MODIFY.
* Original file: F:\\Eclipse_ThinkAndroid\\ApitestDemo\\src\\com\\test\\lib\\IMyService.aidl
*/
package com.test.lib;
public interface IMyService extends android.os.IInterface {
/** Local-side IPC implementation stub class. */
public static abstract class Stub extends android.os.Binder implements
com.test.lib.IMyService {
private static final java.lang.String DESCRIPTOR = "com.test.lib.IMyService";
/** Construct the stub at attach it to the interface. */
public Stub() {
this.attachInterface(this, DESCRIPTOR);
}
/**
* Cast an IBinder object into an com.test.lib.IMyService interface,
* generating a proxy if needed.
*/
public static com.test.lib.IMyService asInterface(android.os.IBinder obj) {
if ((obj == null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin != null) && (iin instanceof com.test.lib.IMyService))) {
return ((com.test.lib.IMyService) iin);
}
return new com.test.lib.IMyService.Stub.Proxy(obj);
}
@Override
public android.os.IBinder asBinder() {
return this;
}
@Override
public boolean onTransact(int code, android.os.Parcel data,
android.os.Parcel reply, int flags)
throws android.os.RemoteException {
switch (code) {
case INTERFACE_TRANSACTION: {
reply.writeString(DESCRIPTOR);
return true;
}
case TRANSACTION_setValue: {
data.enforceInterface(DESCRIPTOR);
int _arg0;
_arg0 = data.readInt();
this.setValue(_arg0);
reply.writeNoException();
return true;
}
case TRANSACTION_getValue: {
data.enforceInterface(DESCRIPTOR);
int _result = this.getValue();
reply.writeNoException();
reply.writeInt(_result);
return true;
}
}
return super.onTransact(code, data, reply, flags);
}
private static class Proxy implements com.test.lib.IMyService {
private android.os.IBinder mRemote;
Proxy(android.os.IBinder remote) {
mRemote = remote;
}
@Override
public android.os.IBinder asBinder() {
return mRemote;
}
public java.lang.String getInterfaceDescriptor() {
return DESCRIPTOR;
}
@Override
public void setValue(int val) throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeInt(val);
mRemote.transact(Stub.TRANSACTION_setValue, _data, _reply,
0);
_reply.readException();
} finally {
_reply.recycle();
_data.recycle();
}
}
@Override
public int getValue() throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
int _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
mRemote.transact(Stub.TRANSACTION_getValue, _data, _reply,
0);
_reply.readException();
_result = _reply.readInt();
} finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
}
static final int TRANSACTION_setValue = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
static final int TRANSACTION_getValue = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
}
public void setValue(int val) throws android.os.RemoteException;
public int getValue() throws android.os.RemoteException;
}
public void attachInterface(IInterface owner, String descriptor) {
mOwner = owner;
mDescriptor = descriptor;
}
可以看到IMyService继承了IInterface,IMyService.Stub继承了Binder并且实现了IMyService接口。Proxy是Stub抽象类的代理,Proxy实际实现了IMyService接口的处理,作用是从service_manager获取IMyService的BpProxy。new MyService()可以认为等同于new Stub()。所以在addService时data.writeStrongBinder(service)传入的参数就是这个Stub。
经过上面的分析,Java层通过的服务注册还是要借助C层service_manager [ProcessState::self()->getContextObject(NULL);] 的Binder机制。BpBinder(0)如何注册服务这里不分析了。
服务注册后,需要在客户端使用:
IMyService myservice = IMyService.Stub.asInterface(ServiceManager.getService("MYSERVICE"));
首先看看ServiceManager.getService:
public static IBinder getService(String name) {
try {
//看cache中是否有,比如同一段时间内连续调用AIDL接口,这里就能提交效率
IBinder service = sCache.get(name);
if (service != null) {
return service;
} else {
return getIServiceManager().getService(name);
}
} catch (RemoteException e) {
Log.e(TAG, "error in getService", e);
}
return null;
}
和addService流程一样,通过JNI调用后获得BinderProxy:
public static IBinder getService(String name) {
try {
IBinder service = sCache.get(name);
if (service != null) {
return service;
} else {
return getIServiceManager().getService(name);
}
} catch (RemoteException e) {
Log.e(TAG, "error in getService", e);
}
return null;
}
public IBinder getService(String name) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IServiceManager.descriptor);
data.writeString(name);
mRemote.transact(GET_SERVICE_TRANSACTION, data, reply, 0);
IBinder binder = reply.readStrongBinder();
reply.recycle();
data.recycle();
return binder;
}
和addService的writeStrongBinder对应,getService中对应的是IBinder binder = reply.readStrongBinder();这里有一个问题需要思考,addSevice时是给native service_manager注册的一个Stub,那么getSevice应该是什么?可以先大胆的假设getService就是add时的Stub。
writeStrongBinder和readStrongBinder调用的都是native层方法:
public final class Parcel {
...
public final void writeStrongBinder(IBinder val) {
nativeWriteStrongBinder(mNativePtr, val);
}
private static native void nativeWriteStrongBinder(long nativePtr, IBinder val);
private static native IBinder nativeReadStrongBinder(long nativePtr);
...
}
对应的JNI实现:
static void android_os_Parcel_writeStrongBinder(JNIEnv* env, jclass clazz, jlong nativePtr, jobject object)
{
Parcel* parcel = reinterpret_cast(nativePtr);
if (parcel != NULL) {
const status_t err = parcel->writeStrongBinder(ibinderForJavaObject(env, object));
if (err != NO_ERROR) {
signalExceptionForError(env, clazz, err);
}
}
}
static jobject android_os_Parcel_readStrongBinder(JNIEnv* env, jclass clazz, jlong nativePtr)
{
Parcel* parcel = reinterpret_cast(nativePtr);
if (parcel != NULL) {
return javaObjectForIBinder(env, parcel->readStrongBinder());
}
return NULL;
}
ibinderForJavaObject和javaObjectForIBinder这是相对的方法。介绍ibinderForJavaObject之前先看以下方法:
public Binder() {
init();
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());
}
}
}
新建一个Binder的时候都会被调用。
static void android_os_Binder_init(JNIEnv* env, jobject obj)
{
JavaBBinderHolder* jbh = new JavaBBinderHolder();
if (jbh == NULL) {
jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
return;
}
ALOGV("Java Binder %p: acquiring first ref on holder %p", obj, jbh);
//自增作为句柄,并且把JavaBBinderHolder写入到Binder对象的mObject,之后会需要使用
jbh->incStrong((void*)android_os_Binder_init);
env->SetLongField(obj, gBinderOffsets.mObject, (jlong)jbh);
}
JavaBBinderHolder是什么:
class JavaBBinderHolder : public RefBase
{
public:
sp get(JNIEnv* env, jobject obj)
{
AutoMutex _l(mLock);
sp 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 getExisting()
{
AutoMutex _l(mLock);
return mBinder.promote();
}
private:
Mutex mLock;
wp mBinder;
}
了解了以上几点后,再来看ibinderForJavaObject:
sp ibinderForJavaObject(JNIEnv* env, jobject obj)
{
if (obj == NULL) return NULL;
//gBinderOffsets.mClass对应的是android/os/Binder,例如在Java层添加自定义的Service时就继承的android/os/Binder,因此会在此处理
if (env->IsInstanceOf(obj, gBinderOffsets.mClass)) {
JavaBBinderHolder* jbh = (JavaBBinderHolder*)
//这里是获取JAVA层Binder对象的句柄?这个值是在android_os_Binder_init时写入的
env->GetLongField(obj, gBinderOffsets.mObject);
return jbh != NULL ? jbh->get(env, obj) : NULL;
}
//gBinderProxyOffsets.mClass对应的是android/os/BinderProxy
if (env->IsInstanceOf(obj, gBinderProxyOffsets.mClass)) {
return (IBinder*)
//这里返回的就是从BinderProxy中获取的BpBinder(0)
env->GetLongField(obj, gBinderProxyOffsets.mObject);
}
ALOGW("ibinderForJavaObject: %p is not a Binder object", obj);
return NULL;
}
在Java层添加自定义的Service时继承的android/os/Binder,因此会默认创建出一个句柄JavaBBinderHolder,此时在addService时,会调用JavaBBinderHolder的get函数,返回一个创建出来的JavaBBinder:
class JavaBBinder : public BBinder
{
public:
JavaBBinder(JNIEnv* env, jobject object)
: mVM(jnienv_to_javavm(env)), mObject(env->NewGlobalRef(object))
{
ALOGV("Creating JavaBBinder %p\n", this);
android_atomic_inc(&gNumLocalRefs);
incRefsCreated(env);
}
...
此时Java层的Stub已经保存在JavaBBinder的mObject中。 也就是在这个流程里addService的时候ibinderForJavaObject返回的是一个JavaBBinder的指针。写入到service_manager的就是一个JavaBBinder,JavaBBinder持有了Java层创建的Binder对象。
status_t Parcel::writeStrongBinder(const sp& val)
{
return flatten_binder(ProcessState::self(), val, this);
}
status_t flatten_binder(const sp& /*proc*/,
const sp& binder, Parcel* out)
{
flat_binder_object obj;
obj.flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;
if (binder != NULL) {
IBinder *local = binder->localBinder();
if (!local) {
BpBinder *proxy = binder->remoteBinder();
if (proxy == NULL) {
ALOGE("null proxy");
}
const int32_t handle = proxy ? proxy->handle() : 0;
obj.type = BINDER_TYPE_HANDLE;
obj.binder = 0; /* Don't pass uninitialized stack data to a remote process */
obj.handle = handle;
obj.cookie = 0;
} else {
obj.type = BINDER_TYPE_BINDER;
obj.binder = reinterpret_cast(local->getWeakRefs());
obj.cookie = reinterpret_cast(local);
}
} else {
obj.type = BINDER_TYPE_BINDER;
obj.binder = 0;
obj.cookie = 0;
}
return finish_flatten_binder(binder, obj, out);
}
从Parcel::writeStrongBinder中可以看到,binder是localBinder时,保存的是binder的指针引用,而binder是remoteBinder时,保存的是binder的句柄。
JavaBBinder是继承BBinder的,我们看BBinder的localBinder:
BBinder* BBinder::localBinder()
{
return this;
}
那么很明显的,我们能知道在native中我们保存的是JavaBBinder的指针引用。
在来看看对应的javaObjectForIBinder方法:
jobject javaObjectForIBinder(JNIEnv* env, const sp& val)
{
if (val == NULL) return NULL;
if (val->checkSubclass(&gBinderOffsets)) {
// One of our own!
jobject object = static_cast(val.get())->object();
LOGDEATH("objectForBinder %p: it's our own %p!\n", val.get(), object);
return object;
}
...
}
首先我们需要清楚javaObjectForIBinder参数中的val具体是什么?
他是parcel->readStrongBinder()读取出来的,应该也是JavaBBinder:
sp Parcel::readStrongBinder() const
{
sp val;
unflatten_binder(ProcessState::self(), *this, &val);
return val;
}
status_t unflatten_binder(const sp& proc,
const Parcel& in, sp* out)
{
const flat_binder_object* flat = in.readObject(false);
if (flat) {
switch (flat->type) {
case BINDER_TYPE_BINDER:
*out = reinterpret_cast(flat->cookie);
return finish_unflatten_binder(NULL, *flat, in);
case BINDER_TYPE_HANDLE:
*out = proc->getStrongProxyForHandle(flat->handle);
return finish_unflatten_binder(
static_cast(out->get()), *flat, in);
}
}
return BAD_TYPE;
}
在Write时保存的是BINDER_TYPE_BINDER,Read的时候当然也是这个类型,那么返回的就是reinterpret_cast
至此也就是说javaObjectForIBinder传入的val是JavaBBinder,那么我们再来分析getService时,IBinder binder = reply.readStrongBinder();到底返回了一个什么:
val->checkSubclass(&gBinderOffsets)
因为val返回的是JavaBBinder:
class JavaBBinder : public BBinder
{
...
bool checkSubclass(const void* subclassID) const
{
return subclassID == &gBinderOffsets;
}
jobject object() const
{
return mObject;
}
...
}
那么返回的正好也就是:
jobject object = static_cast(val.get())->object();
JavaBBinder在创建的时候把Java层的Stub保存到mObject过,所以这里不就是在addService的时候new MyService()的对象嘛。那么客户端就可以通过getService获取这个引用,可以看到这个mOwner就是add时的Stub,客户端在使用是通过asInterface创建一个Proxy,Proxy实现了IMyService的接口且持有mRemote(Stub),最终都会通过Proxy中的mRemote去调用。
技巧:没发现嘛?使用writeStrongBinder和readStrongBinder是可以达到双端通信的,具体内容需要思考。
@Override
public void setValue(int val) throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeInt(val);
mRemote.transact(Stub.TRANSACTION_setValue, _data, _reply,
0);
_reply.readException();
} finally {
_reply.recycle();
_data.recycle();
}
}
mRemote不就是分析就是创建时的JavaBBinder嘛,JavaBBinder继承BBinder,但是没有重写transact,所以在JNI调用的时候会调用BBinder的transact:
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;
}
进而调用到onTransact方法,而JavaBBinder重写了onTransact:
virtual status_t onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0)
{
JNIEnv* env = javavm_to_jnienv(mVM);
ALOGV("onTransact() on %p calling object %p in env %p vm %p\n", this, mObject, env, mVM);
IPCThreadState* thread_state = IPCThreadState::self();
const int32_t strict_policy_before = thread_state->getStrictModePolicy();
//printf("Transact from %p to Java code sending: ", this);
//data.print();
//printf("\n");
//会去调用mObject的mExecTransact,而这个mObject就是之前绑定的JAVA的Binder对象,
jboolean res = env->CallBooleanMethod(mObject, gBinderOffsets.mExecTransact,
code, reinterpret_cast(&data), reinterpret_cast(reply), flags);
jthrowable excep = env->ExceptionOccurred();
if (excep) {
report_exception(env, excep,
"*** Uncaught remote exception! "
"(Exceptions are not yet supported across processes.)");
res = JNI_FALSE;
/* clean up JNI local ref -- we don't return to Java code */
env->DeleteLocalRef(excep);
}
// Check if the strict mode state changed while processing the
// call. The Binder state will be restored by the underlying
// Binder system in IPCThreadState, however we need to take care
// of the parallel Java state as well.
if (thread_state->getStrictModePolicy() != strict_policy_before) {
set_dalvik_blockguard_policy(env, strict_policy_before);
}
jthrowable excep2 = env->ExceptionOccurred();
if (excep2) {
report_exception(env, excep2,
"*** Uncaught exception in onBinderStrictModePolicyChange");
/* clean up JNI local ref -- we don't return to Java code */
env->DeleteLocalRef(excep2);
}
// Need to always call through the native implementation of
// SYSPROPS_TRANSACTION.
if (code == SYSPROPS_TRANSACTION) {
BBinder::onTransact(code, data, reply, flags);
}
//aout << "onTransact to Java code; result=" << res << endl
// << "Transact from " << this << " to Java code returning "
// << reply << ": " << *reply << endl;
return res != JNI_FALSE ? NO_ERROR : UNKNOWN_TRANSACTION;
}
会去调用mObject的mExecTransact,而这个mObject就是之前绑定的JAVA的Binder对象,因此会调用到Java层的Binder方法execTransact:
// Entry point from android_util_Binder.cpp's onTransact
private boolean execTransact(int code, long dataObj, long replyObj,
int flags) {
Parcel data = Parcel.obtain(dataObj);
Parcel reply = Parcel.obtain(replyObj);
// theoretically, we should call transact, which will call onTransact,
// but all that does is rewind it, and we just got these from an IPC,
// so we'll just call it directly.
boolean res;
// Log any exceptions as warnings, don't silently suppress them.
// If the call was FLAG_ONEWAY then these exceptions disappear into the ether.
try {
res = onTransact(code, data, reply, flags);
} catch (RemoteException e) {
if ((flags & FLAG_ONEWAY) != 0) {
Log.w(TAG, "Binder call failed.", e);
} else {
reply.setDataPosition(0);
reply.writeException(e);
}
res = true;
} catch (RuntimeException e) {
if ((flags & FLAG_ONEWAY) != 0) {
Log.w(TAG, "Caught a RuntimeException from the binder stub implementation.", e);
} else {
reply.setDataPosition(0);
reply.writeException(e);
}
res = true;
} catch (OutOfMemoryError e) {
// Unconditionally log this, since this is generally unrecoverable.
Log.e(TAG, "Caught an OutOfMemoryError from the binder stub implementation.", e);
RuntimeException re = new RuntimeException("Out of memory", e);
reply.setDataPosition(0);
reply.writeException(re);
res = true;
}
checkParcel(this, code, reply, "Unreasonably large binder reply buffer");
reply.recycle();
data.recycle();
...
}
}
其中又调用了onTransact方法,onTransact是在Binder子类中实现的,子类就可以重写该方法,实现方法处理了。而AIDL是自动生成了onTransact的实现:
@Override
public boolean onTransact(int code, android.os.Parcel data,
android.os.Parcel reply, int flags)
throws android.os.RemoteException {
switch (code) {
case INTERFACE_TRANSACTION: {
reply.writeString(DESCRIPTOR);
return true;
}
case TRANSACTION_setValue: {
data.enforceInterface(DESCRIPTOR);
int _arg0;
_arg0 = data.readInt();
this.setValue(_arg0);
reply.writeNoException();
return true;
}
case TRANSACTION_getValue: {
data.enforceInterface(DESCRIPTOR);
int _result = this.getValue();
reply.writeNoException();
reply.writeInt(_result);
return true;
}
}
return super.onTransact(code, data, reply, flags);
}
可以看到onTransact方法里分别对setValue和getValue作了处理,并从服务端MyService返回处理结果,这也是为什么MyService要重写setValue,getValue接口。
Binder模块我还会持续更新文章,Native层的我现在还没有整理完整,后续更新。