Android跨进程通信IPC之17——Binder之Frame
1 注册服务
注册服务在ServiceManager里面
//frameworks/base/core/java/android/os/ServiceManager.java 70行
public static void addService(String name, IBinder service, boolean allowIsolated) {
try {
//getIServiceManager()是获取ServiceManagerProxy对象
// addService() 是执行注册服务操作
getIServiceManager().addService(name, service, allowIsolated);
} catch (RemoteException e) {
Log.e(TAG, "error in addService", e);
}
}
2 getIServiceManager()方法
//frameworks/base/core/java/android/os/ServiceManager.java 70行
private static IServiceManager getIServiceManager() {
if (sServiceManager != null) {
return sServiceManager;
}
// Find the service manager
sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());
return sServiceManager;
}
2.1 BinderInternal.getContextObject()方法
//frameworks/base/core/java/com/android/internal/os/BinderInternal.java 88行
/**
* Return the global "context object" of the system. This is usually
* an implementation of IServiceManager, which you can use to find
* other services.
*/
public static final native IBinder getContextObject();
可见BinderInternal.getContextObject()最终会调用JNI通过C层来实现,那我们就继续跟踪
2.1.1 android_os_BinderInternal_getContextObject)函数
// frameworks/base/core/jni/android_util_Binder.cpp 899行
static jobject android_os_BinderInternal_getContextObject(JNIEnv* env, jobject clazz)
{
sp<IBinder> b = ProcessState::self()->getContextObject(NULL);
return javaObjectForIBinder(env, b);
}
- 看到上面的代码 大家有没有熟悉的感觉,前面讲过了:对于ProcessState::self() -> getContextObject()
- 对于ProcessState::self()->getContextObject()可以理解为new BpBinder(0)
2.1.2 javaObjectForIBinder()函数
// frameworks/base/core/jni/android_util_Binder.cpp 547行
jobject javaObjectForIBinder(JNIEnv* env, const sp<IBinder>& val)
{
if (val == NULL) return NULL;
//返回false
if (val->checkSubclass(&gBinderOffsets)) {
jobject object = static_cast<JavaBBinder*>(val.get())->object();
return object;
}
AutoMutex _l(mProxyLock);
jobject object = (jobject)val->findObject(&gBinderProxyOffsets);
//第一次 object为null
if (object != NULL) {
//查找是否已经存在需要使用的BinderProxy对应,如果有,则返回引用。
jobject res = jniGetReferent(env, object);
if (res != NULL) {
return res;
}
android_atomic_dec(&gNumProxyRefs);
val->detachObject(&gBinderProxyOffsets);
env->DeleteGlobalRef(object);
}
//创建BinderProxy对象
object = env->NewObject(gBinderProxyOffsets.mClass, gBinderProxyOffsets.mConstructor);
if (object != NULL) {
// BinderProxy.mObject成员变量记录BpBinder对象
env->SetLongField(object, gBinderProxyOffsets.mObject, (jlong)val.get());
val->incStrong((void*)javaObjectForIBinder);
jobject refObject = env->NewGlobalRef(
env->GetObjectField(object, gBinderProxyOffsets.mSelf));
//将BinderProxy对象信息附加到BpBinder的成员变量mObjects中
val->attachObject(&gBinderProxyOffsets, refObject,
jnienv_to_javavm(env), proxy_cleanup);
sp<DeathRecipientList> drl = new DeathRecipientList;
drl->incStrong((void*)javaObjectForIBinder);
// BinderProxy.mOrgue成员变量记录死亡通知对象
env->SetLongField(object, gBinderProxyOffsets.mOrgue, reinterpret_cast<jlong>(drl.get()));
android_atomic_inc(&gNumProxyRefs);
incRefsCreated(env);
}
return object;
}
上面的大致流程如下:
- 1、第二个入参val在有些时候指向BpBinder,有些时候指向JavaBBinder
- 2、至于是BpBinder还是JavaBBinder是通过if (val->checkSubclass(&gBinderOffsets)) 这个函数来区分的,如果是JavaBBinder,则为true,则就会通过成员函数object(),返回一个Java对象,这个对象就是Java层的Binder对象。由于我们这里是BpBinder,所以是 返回false
- 3、如果是BpBinder,会先判断是不是第一次
- 如果是第一次,下面的object为null。
jobject object = (jobject)val->findObject(&gBinderProxyOffsets);
- 如果不是第一次,就会先查找是否已经存在需要使用的BinderProxy对象,如果找到就会返回引用
- 4、如果没有找到可用的引用,就new一个BinderProxy对象
- 所以主要是根据BpBinder(C++) 生成BinderProxy(Java对象),主要工作是创建BinderProxy对象,并把BpBinder对象地址保存到BinderProxy.mObject成员变量。
- 到此,可知ServiceManagerNative.asInterface(BinderInternal.getContextObject()) 等价于
ServiceManagerNative.asInterface(new BinderProxy())
2.2 ServiceManagerNative.asInterface()方法
//frameworks/base/core/java/android/os/ServiceManagerNative.java 33行
/**
* Cast a Binder object into a service manager interface, generating
* a proxy if needed.
* 将Binder对象转换service manager interface,如果需要,生成一个代理。
*/
static public IServiceManager asInterface(IBinder obj)
{
//obj为 BpBinder
// 如果 obj为null 则直接返回
if (obj == null) {
return null;
}
// 由于是BpBinder,所以BpBinder的queryLocalInterface(descriptor) 默认返回null
IServiceManager in =
(IServiceManager)obj.queryLocalInterface(descriptor);
if (in != null) {
return in;
}
return new ServiceManagerProxy(obj);
}
我们看下这个obj.queryLocalInterface(descriptor)方法,其实他是调用的IBinder的native方法如下
public interface IBinder {
.....
/**
* Attempt to retrieve a local implementation of an interface
* for this Binder object. If null is returned, you will need
* to instantiate a proxy class to marshall calls through
* the transact() method.
*/
public IInterface queryLocalInterface(String descriptor);
.....
}
- 通过注释我们知道,queryLocalInterface是查询本地的对象
- 本地对象,这里的本地对象是指,如果进行IPC调用,如果是两个进程是同一个进程,即对象是本地对象;如果两个进程是两个不同的进程,则返回的远端的代理类。
- 所以在BBinder的子类BnInterface中,重载了这个方法,返回this,而在BpInterface并没有重载这个方法。又因为queryLocalInterface 默认返回的是null,所以obj.queryLocalInterface=null。
- 所以最后结论是 return new ServiceManagerProxy(obj);
2.2.1 ServiceManagerProxy
PS:ServiceManagerProxy是ServiceManagerNative类的内部类
//frameworks/base/core/java/android/os/ServiceManagerNative.java 109行
class ServiceManagerProxy implements IServiceManager {
public ServiceManagerProxy(IBinder remote) {
mRemote = remote;
}
}
- mRemote为BinderProxy对象,该BinderProxy对象对应于BpBinder(0),其作为binder代理端,指向native的层的Service Manager。
所以说:
- ServiceManager.getIServiceManager最终等价于new ServiceManagerProxy(new BinderProxy())。所以
getIServiceManager().addService()
等价于
ServiceManagerNative.addService();
- framework层的ServiceManager的调用实际的工作确实交给了ServiceManagerProxy的成员变量BinderProxy;
- 而BinderProxy通过JNI的方式,最终会调用BpBinder对象;可见上层binder结构的核心功能依赖native架构的服务来完成的。
3 addService()方法详解
上面已经知道了
getIServiceManager().addService(name, service, allowIsolated);
等价于
ServiceManagerProxy..addService(name, service, allowIsolated);
所以让我们来看下ServiceManagerProxy的addService()方法
3.1 ServiceManagerProxy的addService()
//frameworks/base/core/java/android/os/ServiceManagerNative.java 142行
public void addService(String name, IBinder service, boolean allowIsolated)
throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
//是个常量是 “android.os.IServiceManager"
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();
}
里面代码都比较容易理解,这里重点说下data.writeStrongBinder(service); 和 mRemote.transact(ADD_SERVICE_TRANSACTION, data, reply, 0);
3.2 Parcel.writeStrongBinder()
//frameworks/base/core/java/android/os/Parcel.java 583行
/**
* Write an object into the parcel at the current dataPosition(),
* growing dataCapacity() if needed.
*/
public final void writeStrongBinder(IBinder val) {
nativeWriteStrongBinder(mNativePtr, val);
}
注释:在当前的dataPosition()的位置上写入一个对象,如果空间不足,则增加空间
3.2.1 nativeWriteStrongBinder()方法
/frameworks/base/core/java/android/os/Parcel.java 265行
private static native void nativeWriteStrongBinder(long nativePtr, IBinder val);
3.2.2 android_os_Parcel_writeStrongBinder()函数
//frameworks/base/core/jni/android_os_Parcel.cpp 298行
static void android_os_Parcel_writeStrongBinder(JNIEnv* env, jclass clazz, jlong nativePtr, jobject object)
{
//将java层Parcel转换为native层Parcel
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);
}
}
}
这里主要涉及的两个重要的函数
- writeStrongBinder()函数
- ibinderForJavaObject()函数
3.2.3 ibinderForJavaObject()函数
// frameworks/base/core/jni/android_util_Binder.cpp 603行
sp<IBinder> ibinderForJavaObject(JNIEnv* env, jobject obj)
{
if (obj == NULL) return NULL;
//Java层的Binder对象
//mClass指向Java层中的Binder class
if (env->IsInstanceOf(obj, gBinderOffsets.mClass)) {
JavaBBinderHolder* jbh = (JavaBBinderHolder*)
env->GetLongField(obj, gBinderOffsets.mObject);
//get()返回一个JavaBBinder,继承自BBinder
return jbh != NULL ? jbh->get(env, obj) : NULL;
}
//Java层的BinderProxy对象
// mClass 指向Java层的BinderProxy class
if (env->IsInstanceOf(obj, gBinderProxyOffsets.mClass)) {
//返回一个 BpBinder,mObject 是它的地址值
return (IBinder*)env->GetLongField(obj, gBinderProxyOffsets.mObject);
}
return NULL;
}
根据Binder(Java)生成JavaBBinderHolder(C++)对象,主要工作是创建JavaBBinderHolder对象,并把JavaBBinder对象保存在到Binder.mObject成员变量。
- 这个函数,本质就是根据传进来的Java对象找到对应的C++对象,这里的obj可能会指向两种对象:Binder对象和BinderProxy对象。
- 如果传进来的是Binder对象,则会把gBinderOffsets.mObject转化为JavaBBinderHolder,并从中获得一个JavaBBinder对象(JavaBBinder继承自BBinder)。
- 如果是BinderProxy对象,会返回一个BpBinder,这个BpBinder的地址值保存在gBinderProxyOffsets.mObject中
在上面的代码里面调用了get()函数,如下图
JavaBBinderHolder* jbh = (JavaBBinderHolder*)
env->GetLongField(obj, gBinderOffsets.mObject);
//get()返回一个JavaBBinder,继承自BBinder
return jbh != NULL ? jbh->get(env, obj) : NULL;
那我们就来研究下JavaBBinderHolder.get()函数
3.2.4 JavaBBinderHolder.get()函数
// frameworks/base/core/jni/android_util_Binder.cpp 316行
sp<JavaBBinder> get(JNIEnv* env, jobject obj)
{
AutoMutex _l(mLock);
sp<JavaBBinder> b = mBinder.promote();
if (b == NULL) {
//首次进来,创建JavaBBinder对象
b = new JavaBBinder(env, obj);
mBinder = b;
}
return b;
}
JavaBBinderHolder有一个成员变量mBinder,保存当前创建的JavaBBinder对象,这是一个wp类型的,可能会被垃圾回收器给回收的,所以每次使用前都需要先判断是否存在。
那我们再来看看下JavaBBinder的初始化
3.2.5 JavaBBinder的初始化
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);
}
创建JavaBBinder,该对象继承于BBinder对象。
3.2.6 总结
所以说 data.writeStrongBinder(Service)最终等价于parcel->writeStringBinder(new JavaBBinder(env, obj));
3.2.7 writeStrongBinder() 函数
// frameworks/native/libs/binder/Parcel.cpp 872行
status_t Parcel::writeStrongBinder(const sp<IBinder>& val)
{
return flatten_binder(ProcessState::self(), val, this);
}
我们看到writeStrongBinder()函数 实际上是调用的flatten_binder()函数
3.2.8 writeStrongBinder() 函数
//frameworks/native/libs/binder/Parcel.cpp 205行
status_t flatten_binder(const sp<ProcessState>& /*proc*/,
const sp<IBinder>& binder, Parcel* out)
{
flat_binder_object obj;
obj.flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;
if (binder != NULL) {
IBinder *local = binder->localBinder();
if (!local) {
//如果不是本地Binder
BpBinder *proxy = binder->remoteBinder();
const int32_t handle = proxy ? proxy->handle() : 0;
//远程Binder
obj.type = BINDER_TYPE_HANDLE;
obj.binder = 0;
obj.handle = handle;
obj.cookie = 0;
} else {
//如果是本地Binder
obj.type = BINDER_TYPE_BINDER;
obj.binder = reinterpret_cast<uintptr_t>(local->getWeakRefs());
obj.cookie = reinterpret_cast<uintptr_t>(local);
}
} else {
//本地Binder
obj.type = BINDER_TYPE_BINDER;
obj.binder = 0;
obj.cookie = 0;
}
return finish_flatten_binder(binder, obj, out);
}
将Binder对象扁平化,转换成flat_binder_object对象
- 对于Binder实体,则cookie记录Binder实体指针
- 对于Binder代理,则用handle记录Binder代理的句柄
关于localBinder,在Binder.cpp里面
BBinder* BBinder::localBinder()
{
return this;
}
BBinder* IBinder::localBinder()
{
return NULL;
在最后面调用了finish_flatten_binder()函数,那我们再研究下finish_flatten_binder()函数
3.2.9 finish_flatten_binder() 函数
//frameworks/native/libs/binder/Parcel.cpp 199行
inline static status_t finish_flatten_binder(
const sp<IBinder>& , const flat_binder_object& flat, Parcel* out)
{
return out->writeObject(flat, false);
}
这个大家看明白了吧,就是写入一个object。
3.3 IBinder.transact()
ServiceManagerProxy的addService()中的mRemote.transact(ADD_SERVICE_TRANSACTION, data, reply, 0);里面的mRemote的类型是BinderProxy的,所以调用是BinderProxy的transact()方法,那我们就进去看看
3.2.3.1 BinderProxy.transact()
温馨提示:BinderProxy类是Binder类的内部类
他其实是重写的IBinder的里面的transact()方法,那让我们看下IBinder里面
// frameworks/base/core/java/android/os/IBinder.java 223行
/**
* Perform a generic operation with the object.
*
* @param code The action to perform. This should
* be a number between {@link #FIRST_CALL_TRANSACTION} and
* {@link #LAST_CALL_TRANSACTION}.
* @param data Marshalled data to send to the target. Must not be null.
* If you are not sending any data, you must create an empty Parcel
* that is given here.
* @param reply Marshalled data to be received from the target. May be
* null if you are not interested in the return value.
* @param flags Additional operation flags. Either 0 for a normal
* RPC, or {@link #FLAG_ONEWAY} for a one-way RPC.
*/
public boolean transact(int code, Parcel data, Parcel reply, int flags)
throws RemoteException;
主要是这个注释
- 用对象执行一个操作
- 参数code 为操作码,是介于FIRST_CALL_TRANSACTION和LAST_CALL_TRANSACTION之间
- 参数data 是要发往目标的数据,一定不能null,如果你没有数据要发送,你也要创建一个Parcel,哪怕是空的。
- 参数reply 是从目标发过来的数据,如果你对这个数据没兴趣,这个数据是可以为null的。
- 参数flags 一个操作标志位,要么是0代表普通的RPC,要么是FLAG_ONEWAY代表单一方向的RPC即不管返回值
这时候我们再回来看
/frameworks/base/core/java/android/os/Binder.java 501行
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");
if (Binder.isTracingEnabled()) { Binder.getTransactionTracker().addTrace(); }
return transactNative(code, data, reply, flags);
}
}
3.3.2 Binder.checkParcel()
/frameworks/base/core/java/android/os/Binder.java 415行
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());
}
}
- 这段代码很简单,主要是检查Parcel大小是否大于800K
- 执行完Binder.checkParcel后,直接调用了transactNative()方法,那我们就来看看transactNative()方法
3.3.3 transactNative()方法
// frameworks/base/core/java/android/os/Binder.java 507行
public native boolean transactNative(int code, Parcel data, Parcel reply,
int flags) throws RemoteException;
我们看到他是一个native函数,后面肯定经过JNI调用到了native层,根据包名,它对应的方法应该是"android_os_BinderProxy_transact"函数,那我们继续跟踪
3.3.4 android_os_BinderProxy_transact()函数
// frameworks/base/core/jni/android_util_Binder.cpp 1083行
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 Parcel转化为native Parcel
Parcel * data = parcelForJavaObject(env, dataObj);
if (data == NULL) {
return JNI_FALSE;
}
Parcel * reply = parcelForJavaObject(env, replyObj);
if (reply == NULL && replyObj != NULL) {
return JNI_FALSE;
}
// gBinderProxyOffsets.mObject中保存的是new BpBinder(0)对象
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);
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();
// 此处便是BpBinder:: transact(),经过native层,进入Binder驱动。
status_t err = target -> transact(code, * data, reply, flags);
//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;
}
通过上面的代码我们知道,Java层BinderProxy.transact()最终交由Native层的BpBinder::transact()完成。这部分之前代码讲解过了,我这里就不详细说明了。不过注意,该方法可能会抛出RemoteException。