Android Framework:Binder(6)-Java层Service的注册及跨进程调用
来源:互联网 发布:广发期货模拟软件 编辑:程序博客网 时间:2024/05/22 16:57
Android Framework:Binder(6)-Java层Service的注册及跨进程调用
一、Java层Binder概述
Java层中的binder和Native层的Binder在命名上尽量保持了一致,且Java层的Binder依托于Native层的Binder,其实就是对底层的Binder的真正实现的一个封装,最终还是通过JNI技术调用到C/C++代码的实现。。
本文我们从PKMS服务的初始化注册和PKMS的服务调用来学习Java层Binder的知识。
废话不说先上图:
1. Java Binder及PKMS框架:
2. Java Binder跨进程调用服务的整体框架
这图是学完整个Java层Binder机制之后总结出来的,先放这里引导一下:
1. 从该图中我们发现Java层的Binder框架的确是依靠Native层的Binder框架的,通过JNI层使得两者联系在一起。Native Service中Client端会有一个BpBinder的引用,Service端会有一个BBinder的引用来实现通信;而Java层Service在Client端会有个BinderProxy的引用,在Service端会有个JavaBBinder对象的引用来实现通信。当然Java层的Binder机制是基于native层的,native层的binder机制是基于Binder驱动的。
2. 同Native层Service调用一样,Client端调用远程Service时需要向ServiceManager进程请求Service的代理对象,Service代理对象XXSeviceProxy是通过BinderProxy对象new出来的,而BinderProxy对象是由ServiceManager根据查询到的Service的Bp端的Binder代理BpBinder(handle)构造出来的,供java层Client端中的XXServiceProxy使用。Java层的BinderProxy与native层的BpBinder对应。
3. Java Service进行注册服务时将Java service的name和通过JNI层封装后service的JavaBBinder对象注册至service_manager中。
4. JavaService响应请求时,在Native层的IPCThreadState中调用BBinder的transact进而调用到JavaService的JavaBBinder的onTransact()函数,通过JNI层调用到Binder子类的IXXServiceInterface.stub中的onTransact()方法,在xx.stub类中的onTransact()方法中调用到指定的xx.stub的具体实现函数即XXService中的具体实现方法,从而完成Java Service的响应。
二、Java层Binder框架初始化
Android启动初期,系统会提前一个专门负责搭建Java Binder和Native Binder交互关系的函数,该函数是register_android_os_Binder,代码如下:
//frameworks/base/core/jni/android_util_Binder.cppint register_android_os_Binder(JNIEnv* env) { // 初始化Java Binder类和Native层的关系 if (int_register_android_os_Binder(env) < 0) return -1; // 初始化Java BinderInternal类和Native层的关系 if (int_register_android_os_BinderInternal(env) < 0) return -1; // 初始化Java BinderProxy类和Native层的关系 if (int_register_android_os_BinderProxy(env) < 0) return -1; ...... return 0; }
1.Java层Binder框架JNI层的初始化
1.1 Binder类JNI层初始化
//java层的Binder类的全路径名const char* const kBinderPathName = "android/os/Binder";static int int_register_android_os_Binder(JNIEnv* env){ //找到java层的Binder类,保存至clazz变量中 jclass clazz = FindClassOrDie(env, kBinderPathName); gBinderOffsets.mClass = MakeGlobalRefOrDie(env, clazz); //将Binder类中的execTransact方法保存至gBinderOffsets的mExectransact变量中 gBinderOffsets.mExecTransact = GetMethodIDOrDie(env, clazz, "execTransact", "(IJJI)Z"); //将Binder的mObject变量保存到gBinderOffsets的mObject中 gBinderOffsets.mObject = GetFieldIDOrDie(env, clazz, "mObject", "J"); //注册Java Binder类的native函数实现 return RegisterMethodsOrDie( env, kBinderPathName, gBinderMethods, NELEM(gBinderMethods));}
我们看到gBinderOffsets对象保存了Binder类相关的信息,这些信息将在JNI层中使用到,下面两个方法类似;
1.2 BinderInternal类JNI层初始化
const char* const kBinderInternalPathName = "com/android/internal/os/BinderInternal";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));}
1.3 BinderProxy类JNI层初始化
const char* const kBinderProxyPathName = "android/os/BinderProxy";static int int_register_android_os_BinderProxy(JNIEnv* env){ jclass clazz = FindClassOrDie(env, "java/lang/Error"); gErrorOffsets.mClass = MakeGlobalRefOrDie(env, clazz); clazz = FindClassOrDie(env, kBinderProxyPathName); gBinderProxyOffsets.mClass = MakeGlobalRefOrDie(env, clazz); gBinderProxyOffsets.mConstructor = GetMethodIDOrDie(env, clazz, "<init>", "()V"); gBinderProxyOffsets.mSendDeathNotice = GetStaticMethodIDOrDie(env, clazz, "sendDeathNotice", "(Landroid/os/IBinder$DeathRecipient;)V"); 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.mGetName = GetMethodIDOrDie(env, clazz, "getName", "()Ljava/lang/String;"); return RegisterMethodsOrDie(env, kBinderProxyPathName, gBinderProxyMethods, NELEM(gBinderProxyMethods));}
至此,初始了JavaBinder重要成员变量,gBinderOffsets,gBinderInternalOffsets,gBinderProxyOffsets,分别保存了对应的Java对象类的方法和变量等信息,这些信息将会在JNI层native和java对象类型转换时使用到,先保存下来能节约一定的时间。
2. Java Binder中重要Native方法映射
2.1 Java层Binder类中的native方法:
static const JNINativeMethod gBinderMethods[] = { /* name, signature, funcPtr */ { "getCallingPid", "()I", (void*)android_os_Binder_getCallingPid }, { "getCallingUid", "()I", (void*)android_os_Binder_getCallingUid }, { "clearCallingIdentity", "()J", (void*)android_os_Binder_clearCallingIdentity }, { "restoreCallingIdentity", "(J)V", (void*)android_os_Binder_restoreCallingIdentity }, { "setThreadStrictModePolicy", "(I)V", (void*)android_os_Binder_setThreadStrictModePolicy }, { "getThreadStrictModePolicy", "()I", (void*)android_os_Binder_getThreadStrictModePolicy }, { "flushPendingCommands", "()V", (void*)android_os_Binder_flushPendingCommands }, { "init", "()V", (void*)android_os_Binder_init }, { "destroy", "()V", (void*)android_os_Binder_destroy }, { "blockUntilThreadAvailable", "()V", (void*)android_os_Binder_blockUntilThreadAvailable }};
2.2 Java层BinderInternal类中的native方法:
static const JNINativeMethod gBinderInternalMethods[] = { /* name, signature, funcPtr */ { "getContextObject", "()Landroid/os/IBinder;", (void*)android_os_BinderInternal_getContextObject }, { "joinThreadPool", "()V", (void*)android_os_BinderInternal_joinThreadPool }, { "disableBackgroundScheduling", "(Z)V", (void*)android_os_BinderInternal_disableBackgroundScheduling }, { "setMaxThreads", "(I)V", (void*)android_os_BinderInternal_setMaxThreads }, { "handleGc", "()V", (void*)android_os_BinderInternal_handleGc }};
2.3 Java层BinderProxy类中的native方法:
static const JNINativeMethod gBinderProxyMethods[] = { /* name, signature, funcPtr */ {"pingBinder", "()Z", (void*)android_os_BinderProxy_pingBinder}, {"isBinderAlive", "()Z", (void*)android_os_BinderProxy_isBinderAlive}, {"getInterfaceDescriptor", "()Ljava/lang/String;", (void*)android_os_BinderProxy_getInterfaceDescriptor}, {"transactNative", "(ILandroid/os/Parcel;Landroid/os/Parcel;I)Z", (void*)android_os_BinderProxy_transact}, {"linkToDeath", "(Landroid/os/IBinder$DeathRecipient;I)V", (void*)android_os_BinderProxy_linkToDeath}, {"unlinkToDeath", "(Landroid/os/IBinder$DeathRecipient;I)Z", (void*)android_os_BinderProxy_unlinkToDeath}, {"destroy", "()V", (void*)android_os_BinderProxy_destroy},};
保存一下方便日后查看。
三、PKMS初始化注册服务
我们以PKMS初始化作为分析Binder java层的入口。
在SystemServer启动PMKS的时候会在PackageManagerService的main函数中new出一个PKMS的实例m,并将PKMS的名称和实例注册至ServiceManager:
//frameworks\base\services\core\java\com\android\server\pm\PackageManagerService.javapublic static PackageManagerService main(Context context, Installer installer, boolean factoryTest, boolean onlyCore) { PackageManagerService m = new PackageManagerService(context, installer, factoryTest, onlyCore); ServiceManager.addService("package", m); }
从这个地方我们继续跟下去:
//frameworks\base\core\java\android\os\ServiceManager.java public static void addService(String name, IBinder service) { try { getIServiceManager().addService(name, service, false); } catch (RemoteException e) { Log.e(TAG, "error in addService", e); } }
1. 获取ServiceManager的代理对象:
getIServiceManager通过ServiceManagerNative类获取到ServiceManager的代理对象:
private static IServiceManager getIServiceManager() { if (sServiceManager != null) { return sServiceManager; } // Find the service manager sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject()); return sServiceManager; }
1.1 获取Service的Binder代理BinderProxy
看下BinderInternal.getContextObject是如何活的SM的Binder代理的:
//frameworks\base\core\java\com\android\internal\os\BinderInternal.javapublic static final native IBinder getContextObject();
看到getContextObject是个native方法,我们找到它native的实现:
//frameworks/base/core/jni/android_util_Binder.cppstatic jobject android_os_BinderInternal_getContextObject(JNIEnv* env, jobject clazz){ sp<IBinder> b = ProcessState::self()->getContextObject(NULL);//1,获得native的BpBinder(0)对象 return javaObjectForIBinder(env, b);//2,利用BpBinder对象构造出java层使用的对应的BinderProxy对象}
1.1.1 获取SM的Bp端的BpBinder(0)
首先获取native service_manager的Bp端代理BpBinder(0),在 Android Framework:Binder(4)-Native Service的注册中的第二段的第2小结得知这里最终获得的是Native的BpBinder(0).
1.1.2 javaObjectForIBinder方法构造出BinderProxy对象
然后将Native层的BpBinder(0)通过javaObjectForIBinder()方法包装成java层使用的BinderProxy对象:
//frameworks/base/core/jni/android_util_Binder.cppjobject javaObjectForIBinder(JNIEnv* env, const sp<IBinder>& val){ if (val == NULL) return NULL; //创建一个新的BinderProxy对象 object = env->NewObject(gBinderProxyOffsets.mClass, gBinderProxyOffsets.mConstructor); if (object != NULL) { // The proxy holds a reference to the native object. //代理持有一份native对象的的应用,这里的native对象即指的是BpBinder(0), //将BpBinder对象保存到BinderProxy的mObject成员变量中 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)); //native对象需要持有对应java对象BinderProxy的一份弱引用。 val->attachObject(&gBinderProxyOffsets, refObject, jnienv_to_javavm(env), proxy_cleanup); ... } //返回这个BinderProxy对象 return object;}
javaObjectForIBinder的作用是,新建一个Java层的BinderProxy对象,将Native层的BpBinder保存到BinderProxy.mObject,并将BinderProxy的弱引用通过attachObject保存到Native层的BpBinder(0)(成员mObjects中),这样Java层的BinderProxy与Native层的BpBinder就可以相互引用了。
通过上的分析可知,BinderInternal.getContextObject()的目的就是得到ServiceManager进程对应的BpBinder,即BpBinder(0),这里需要利用该BpBinder构造出java层使用的BinderProxy对象。
1.2 ISM asInterface方法利用BinderProxy构造服务代理对象SMProxy:
//frameworks\base\core\java\android\os\ServiceManagerNative.javastatic final String descriptor = "android.os.IServiceManager";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); }
看到IServiceManager asInterface的方法中将返回一个ServiceManagerProxy的ServiceManager的代理对象,即类似于ServiceManagerProxy(BinderProxy(BpBinder(0)))【当然这种写法不准确,仅仅表示结构关系,下面类似的情况也是相同原因】。
1.3.分析ServiceManagerProxy
我们来看下ServiceManagerProxy,ServiceManagerProxy实现了IServiceManager中的方法,提供了SM的方法接口:
//frameworks/base/core/java/android/os/ServiceManagerNative.java::ServiceManagerProxyclass ServiceManagerProxy implements IServiceManager { public ServiceManagerProxy(IBinder remote) { //这里看到在ServiceManagerProxy的构造函数时就将remote赋值给了ServiceManagerProxy的成员变量mRemote //而这里的remote值即是上一步中包装给java层用的BpBinder(0) mRemote = remote; } public IBinder asBinder() { return mRemote; } public IBinder checkService(String name) {mRemote.transact(CHECK_SERVICE_TRANSACTION, data, reply, 0);} public void addService(String name, IBinder service,){mRemote.transact(ADD_SERVICE_TRANSACTION, data, reply, 0);} public String[] listServices() { boolean res = mRemote.transact(LIST_SERVICES_TRANSACTION, data, reply, 0);} private IBinder mRemote;}
从上面的分析得知getIServiceManager()方法得到的是ServiceManager的代理实例,ServiceManagerProxy(BinderProxy(BpBinder(0)));当调用SM代理的接口方法时会调用成员变量mRemote的transact()方法,由上面的分析我们知道这里的mRemote变量即是由BpBinder(0)构造来的BinderProxy对象;
至此,我们在Client端,PKMS的进程中获得了SM进程的代理对象ServiceManagerProxy,这个SM的代理对象与Native层的service_manager进程息息相关,通过BinderProxy与BpBinder(0)之间的关系传递着联系。
2. 跨进程调用ServiceManager的addService方法:
获得Servicemanager代理对象ServiceManagerProxy(BinderProxy(BpBinder(0))),所以调用addService方法即调用到ServiceManagerProxy中的addService方法:
//frameworks/base/core/java/android/os/ServiceManagerNative.java::ServiceManagerProxy 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);//发送不同的执行code reply.recycle(); data.recycle(); }
2.1 数据Binder的封装 data.writeStrongBinder(service):
这里我们看到java层的Binder子类即Service通过writeStrongBinder()方法写到Parcel载体对象data中,看下writeStrongBinder()是做什么的:
//frameworks/base/core/java/android/os/Parcel.javapublic final void writeStrongBinder(IBinder val) { nativeWriteStrongBinder(mNativePtr, val); }
这是个Native方法实现的,找到该方法native实现的地方:
//frameworks/base/core/jni/android_os_Parcel.cppstatic 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)); }}
看到writeStrongBinder中调用Native Parcel类中writeStrongBinder方法,参数是通过ibinderForJavaObject()函数生成的对象,首先看看这个ibinderForJavaObject()函数做了什么:
2.1.1 iBinderForJavaObject():
sp<IBinder> ibinderForJavaObject(JNIEnv* env, jobject obj){ if (obj == NULL) return NULL; //查看这个java对象是否是Binder.java子类,PKMS继承自IPackageManager.Stub,在生成的IPackageManager.java文件中 //可以看到子类Stub类是继承自android.os.binder的,因此这里PKMS应该是Binder子类 if (env->IsInstanceOf(obj, gBinderOffsets.mClass)) { //如果是则先获得JavaBBinderHolder对象,然后调用他的get函数,get函数返回一个JavaBBinder对象 JavaBBinderHolder* jbh = (JavaBBinderHolder*) env->GetLongField(obj, gBinderOffsets.mObject); return jbh != NULL ? jbh->get(env, obj) : NULL; } //如果这个java对象是BinderProxy类,则返回Native层的BpBinder对象 if (env->IsInstanceOf(obj, gBinderProxyOffsets.mClass)) { return (IBinder*) env->GetLongField(obj, gBinderProxyOffsets.mObject); } return NULL;}
从上面的分析至从事obj正是PKMS的实例对象,而PKMS继承自IPackageManager.stub类,IPackageManager.stub继承自android.os.Binder类,因此这里的obj这个java对象是Binder的子类,所以经过ibinderForJavaObject()函数,通过JavaBBinderHolder对象的get方法获得并返回一个JavaBBinder对象。
2.1.2 JavaBBinder,Binder,BinderProxy
PKMS继承自IPackageManager.stub,IPackageManager.stub继承自Binder,在注册PKMS之前,需要new一个PKMS实例,因此这时会调用到爷爷类的Binder的构造函数Binder();
//frameworks/base/core/java/android/os/Binder.javapublic Binder() { init(); ...}private native final void init();
init是一个native实现的方法,我们找到它实现的地方:
//frameworks/base/core/jni/android_util_Binder.cppstatic void android_os_Binder_init(JNIEnv* env, jobject obj){ JavaBBinderHolder* jbh = new JavaBBinderHolder(); ... jbh->incStrong((void*)android_os_Binder_init); env->SetLongField(obj, gBinderOffsets.mObject, (jlong)jbh);}
我们看到Binder初始化时new了一个JavaBBinderHolder对象,然后把这个JavaBBinderHolder对象保存在了Binder类中的mObject对象中。
再看JavaBBinderHolder的定义:
class JavaBBinderHolder : public RefBase{public: sp<JavaBBinder> get(JNIEnv* env, jobject obj) { sp<JavaBBinder> b = mBinder.promote(); if (b == NULL) { b = new JavaBBinder(env, obj);mBinder = b; } return b; }private: wp<JavaBBinder> mBinder;};
我们看到JavaBBinderHolder 中持有一个JavaBBinder类型的成员变量mBinder。
而JavaBBinder定义:
class JavaBBinder : public BBinder{ virtual status_t onTransact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0) { JNIEnv* env = javavm_to_jnienv(mVM); jboolean res = env->CallBooleanMethod(mObject, gBinderOffsets.mExecTransact, code, reinterpret_cast<jlong>(&data), reinterpret_cast<jlong>(reply), flags); }private: JavaVM* const mVM; jobject const mObject;};
看到JavaBBinder中有个成员变量mObject指向一个Java层的Binder对象。
三者的关系:
从上面1.1.2小节中我们知道BinderProxy中的mObject指向native层中对应的BpBinder对象,同时该BpBinder对象也持有者BinderProxy的一份弱引用,两者相互引用:
2.1.3 Native层的writeStrongBinder:
//frameworks/native/libs/binder/Parcel.cppstatus_t Parcel::writeStrongBinder(const sp<IBinder>& val){ return flatten_binder(ProcessState::self(), val, this);}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) { BpBinder *proxy = binder->remoteBinder(); const int32_t handle = proxy ? proxy->handle() : 0; obj.type = BINDER_TYPE_HANDLE; obj.handle = handle; } else { obj.type = BINDER_TYPE_BINDER; obj.binder = reinterpret_cast<uintptr_t>(local->getWeakRefs()); obj.cookie = reinterpret_cast<uintptr_t>(local); } } ... return finish_flatten_binder(binder, obj, out);}
可以看到Native层的writeStrongBinder最终将得到的JavaBBinder对象封装成一个flat_binder_object对象用于写到Parcel数据体中传给Binder驱动,flat_binder_object的数据结构我们在前几篇中见到很多,多为对binder与进程之间对传递的binder对象的封装。
从这里看来,ServiceManagerProxy的addService方法中,data.writeStrongBinder(service);这一步加入的并不是PKMS本身,而是与PKMS对象对应的JavaBBinder对象,将这个JavaBBinder这个对象传递到binder驱动中,最终加入到service_manager中的也是这个JavaBBinder。
2.2 执行BinderProxy的transact方法:
接着执行mRemote.transact(ADD_SERVICE_TRANSACTION, data, reply, 0)方法,由上面的分析我们得知mRemote实际上是BinderProxy(BpBinder(0)),因此下面会调用到BinderProxy中的transact方法:
我们接着看下BinderProxy中的transact()方法:
//frameworks/base/core/java/android/os/Binder.java$BinderProxy 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); } public native boolean transactNative(int code, Parcel data, Parcel reply, int flags) throws RemoteException; ...}
BinderProxy的transact()方法调用到native方法transactNative(),我们看到transactNative()中的四个参数和native层的BpBinder的transact方法中的参数正好一一对应。
我们看下transactNative的实现地方:
static jboolean android_os_BinderProxy_transact(JNIEnv* env, jobject obj, jint code, jobject dataObj, jobject replyObj, jint flags) // throws RemoteException{ //将java对象转化为native对象 Parcel* data = parcelForJavaObject(env, dataObj); Parcel* reply = parcelForJavaObject(env, replyObj); //得到native层的BpBinder, IBinder* target = (IBinder*) env->GetLongField(obj, gBinderProxyOffsets.mObject); ... //通过BpBinder利用IPCThreadState,将请求写入binder驱动,继而传给service_manager进程 status_t err = target->transact(code, *data, reply, flags); ...}
同过上面分析我们知道BinderProxy的mObject保存的是对应的BpBinder的引用,因此这里的target是构造BinderProxy对象时所用到的BpBinder对象,即BpBinder(0)。
2.3 Native层BpBinder向BinderDriver传输请求
这里就比较熟悉了,最终调用到native层的BpBinder去与binder驱动进行通信,最终由service_manager进程向Binder驱动中去取指令与数据进行处理。这里我们知道发给service_manager进程的指令是ADD_SERVICE_TRANSACTION,
数据是ServiceName及Service对象对应的JavaBBinder。
Native层的binder机制在前几篇文章中已经叙述的足够详细,请参考Android Framework:Binder(4)-Native Service的注册中的第二节的第3小节,这里不再赘述。
PKMS服务注册小结:
ServiceManager是公开的管理类,ServiceManager中定义了公开的接口方法,而这些接口方法中通过ServiceManagerNative类调用ServiceManager代理对象ServiceManagerProxy中的方法来实现,
而ServiceManagerProxy中持有一个由service_manager的Bp端代理BpBinder(0)构造出来的BinderProxy对象,在执行ServiceManagerProxy中对应的方法时会执行到BinderProxy的transact方法,通过传入
BinderProxy的transact()中的操作指令不同来实现不同的方法。
至此,我们跟踪了PKMS初始化向service_manager注册自己的过程。
上图总结下:
四、跨进程调用PKMS服务
这里以PackageInstaller使用PackageManager卸载应用为例进行学习;
/packages/apps/PackageInstaller/src/com/android/packageinstaller/wear/WearPackageInstallerService.javaprivate void uninstallPackage(Bundle argsBundle) { final PackageManager pm = getPackageManager(); pm.deletePackage(packageName, new PackageDeleteObserver(lock, startId), PackageManager.DELETE_ALL_USERS); }
1.获取PKMS服务的代理:
通过前面的学习我们知道要调用Service方法需要先获得Service的代理,所以这里先看如何得到PKMS的代理:
public static IPackageManager getPackageManager() { if (sPackageManager != null) { return sPackageManager; } IBinder b = ServiceManager.getService("package"); sPackageManager = IPackageManager.Stub.asInterface(b); return sPackageManager; }
1.1 获取SM服务代理,向SM请求获取PKMS的服务代理:
要得到PKMS的代理需要借助ServiceManager的getService()方法,参数为PKMS注册时注册的名字”package”,而ServiceManager的getService()方法大部分步骤和第三节分析的addService步骤是一致的:
1. 获取ServiceManager的代理对象ServiceManagerProxy(BinderProxy(BpBinder(0))),
2. 调用ServiceManagerProxy的getService方法,
3. 调用BinderProxy的transact()方法,传入的操作指令code是GET_SERVICE_TRANSACTION,
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; }
从上面的分析知mRemote实际是BinderProxy(BpBinder(0)),执行BinderProxy的transact()方法,然后调用到其native的实现方法,android_os_BinderProxy_transact(),在这个native方法中先获取该BinderProxy中mObject中保存的BpBinder对象,再调用该BpBinder的transact()方法实现与binder驱动通信,进而与service_manager进程通信得到写在指针reply地址中的返回数据。
在native层的binder介绍中我们知道reply指针指向的地址中是service_manager返回的包含PKMS handle值的flat_binder_object类型对象;
1.2 readStongBinder获取Java层PKMS的代理Binder对象:
看下面这一步:
Binder binder = reply.readStrongBinder();
调用了Parcel.java中的readStrongBinder()方法:
public final IBinder readStrongBinder() { return nativeReadStrongBinder(mNativePtr); }
nativeReadStrongBinder方法是个Native方法,找到它native实现的地方:
//frameworks/base/core/jni/android_os_Parcel.cppstatic 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;}
又是两步操作,第一步是Native的Parcel的readStrongBinder()方法,第二步又是这个javaObejctForIBinder()方法。
1.2.1 Native Parcell的readStrongBinder
先看这一步,parcel->readStrongBinder():
status_t Parcel::readStrongBinder(sp<IBinder>* val) const{ // return unflatten_binder(ProcessState::self(), *this, val);}
unflatten_binder()中主要将binder驱动传过来的包含PMS的handle值的flat_binder_object对象还原成BpBinder(handle)对象写至val指针指向的地址上。
status_t unflatten_binder(const sp<ProcessState>& proc, const Parcel& in, sp<IBinder>* out){ const flat_binder_object* flat = in.readObject(false); if (flat) { switch (flat->type) { case BINDER_TYPE_BINDER: *out = reinterpret_cast<IBinder*>(flat->cookie); return finish_unflatten_binder(NULL, *flat, in); case BINDER_TYPE_HANDLE: *out = proc->getStrongProxyForHandle(flat->handle); return finish_unflatten_binder( static_cast<BpBinder*>(out->get()), *flat, in); } } return BAD_TYPE;}
之前在第二节的第2.1.3小节中分析过Native Parcel类的writeStrongBinder方法,是将JavaBBinder对象打扁成flat_binder_object类型的对象,以这样的类型向binder驱动传递binder对象;这里的readStrongBinder方法正好和它相反,是将Binder驱动传递过来的flat_binder_object对象(service_manager查询到PKMS的handle值然后构造封装成flat_binder_object对象通过binder驱动返回请求的cilent端)unflatten还原成一个对应的BpBinder(handle)对象,这个BpBinder对象就是PKMS 在native层Bp端的代理BpBinder。
1.2.2 JNI层中的javaObjectForIBinder方法:
而在上面第二节的1.1小节中我们分析了javaObjectForIBinder函数的作用:javaObjectForIBinder(env,BpBinder(handle))会将第二个参数BpBinder(handle)转化成一个BinderProxy对象返回给Java层。
这样Client端就得到了PMSjava层的代理Binder对象BinderProxy(BpBinder(handle)).
1.3 xx.stub.asInterface获取PKMS服务的proxy(BinderProxy)
sPackageManager = IPackageManager.Stub.asInterface(b);
我们在Android Framework源码中没有搜到IPackageManager.Stub.asInterface的定义的地方,原因是这个定义的地方是Android跟据IPackageManager.aidl文件在编译时生成的在out目录下我们搜到了IPackageManager.java。
简要摘录点IPackageManager.java的code,整理下结构方便查看:
//out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/core/java/android/content/pm/IPackageManager.javapublic interface IPackageManager extends android.os.IInterface { public static abstract class Stub extends android.os.Binder implements android.content.pm.IPackageManager { private static final java.lang.String DESCRIPTOR = "android.content.pm.IPackageManager"; public Stub() { this.attachInterface(this, DESCRIPTOR); } public static android.content.pm.IPackageManager asInterface(android.os.IBinder obj) { if ((obj == null)) { return null; } android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR); if (((iin != null) && (iin instanceof android.content.pm.IPackageManager))) { return ((android.content.pm.IPackageManager) iin); } return new android.content.pm.IPackageManager.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: {...} case TRANSACTION_checkPackageStartable: {...} case TRANSACTION_isPackageAvailable: {...} .... } ... } ... private static class Proxy implements android.content.pm.IPackageManager { 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 checkPackageStartable(java.lang.String packageName, int userId) throws android.os.RemoteException { ... mRemote.transact(Stub.TRANSACTION_checkPackageStartable, _data, _reply, 0); } @Override public boolean isPackageAvailable(java.lang.String packageName, int userId) throws android.os.RemoteException { ... mRemote.transact(Stub.TRANSACTION_isPackageAvailable, _data, _reply, 0); ... } } } ...}
查看上面的code之后看到IPackageManager.Stub.asInterface(b)之后得到一个android.content.pm.IPackageManager.Stub.Proxy(obj)的对象(下面简写为PKMProxy实在是太长了好吓人)赋值给sPackageManager。这个对象即是PackageManagerService的代理对象,obj是传入的Binderproxy(BpBinder(handle))的PMS的代理Binder对象。
这里和上面得到ServiceManager的代理对象类似,ServiceManager得到的是ServiceManagerProxy(BinderProxy(BpBinder(0)))。
至此,我们及得到了PKMS服务的代理类对象PKMProxy,下面就可以使用PKMSProxy类对象进行PKMS的方法调用了。
2. 使用PKMProxy类对象调用PKMS方法
2.1 PKMS家族主要结构
- android.content.pm.IPackageManager.Stub.Proxy是在IPackageManager.java中IPackageManager内部类Stub中的内部类,我们看PMS的proxy中实现了IPackageManager的接口,而PKMProxy具体是通过mRemote的transact方法实现。而这个mRemote就是我们new PKMProxy(obj)时传入的BinderProxy(BpBidner(handle))对象。
- BinderProxy由对应的BpBinder构造而来,且BinderProxy与BpBinder相互引用,BinderProxy的transact()方法会通过JNI层调用到对应的成员变量mObject中的BpBinder的transact()方法;
- 通过JNI层的支持,native层的JavaBBinder对象对java层的Binder持有引用,在Binder初始化时即通过JavaBBinderHolder持有了Java Binder的引用,Java Binder的引用保存在JavaBBinder的成员变量mObject中,因此PKMS响应时是由JavaBBinder这个BBinder的子类通过JNI层通知上层Java Binder继而实现java层服务的响应请求。
2.2 使用PKMS服务代理调用服务方法
同Servicemanager中分析的,执行BinderProxy对象的transact()方法通过JNI层的传递调用到native层中对应的BpBinder(handle)的transact()方法,接下来就是通过BpBinder中的IPCThreadState与Binder驱动进行交互了。
3 PKMS服务响应Client端请求
我们知道PackageManagerService是跑在SystemServer进程里的,Zygote的第一个子进程就是SystemServer,在启动SystemServer进程后期会去为SystemServer起一个Binder线程用于SystemServer与Binder驱动进程通信。
///frameworks/base/cmds/app_process/app_main.cppvirtual void onZygoteInit() { sp<ProcessState> proc = ProcessState::self(); proc->startThreadPool(); // 启动一个线程,用于Binder通信。 }
从之前的BinderNative学习中知道proc->startThreadPool()即是启动了一个线程用于Binder通信了,具体可以看Android Framework:Binder(4)-Native Service的注册中的第二节的第4小节 “4.Service线程池管理,处理请求”相关的分析。
也就是说同样的SystemServer进程中也是有个Binder线程在不断向Binder驱动查看是否有请求数据。
3.1 PKMS进程读取Binder驱动请求数据调用JavaBBinder的onTransact()方法
当有个systemServer的请求时会调用systemserver进程的IPCThreadState的joinThreadPool里调用getAndExecuteCommand()函数去处理请求,最终会调用到BBinder的transact()处理请求,transact会调用虚函数onTransact(),而此时JavaBBinder继承自BBinder,所以会调用JavaBBinder::onTransact()方法:
//frameworks/base/core/jni/android_util_Binder.cpp::JavaBBinder virtual status_t onTransact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0) { JNIEnv* env = javavm_to_jnienv(mVM); ... //通过JNI调用了java类的方法 jboolean res = env->CallBooleanMethod(mObject, gBinderOffsets.mExecTransact, code, reinterpret_cast<jlong>(&data), reinterpret_cast<jlong>(reply), flags); return res != JNI_FALSE ? NO_ERROR : UNKNOWN_TRANSACTION; }
3.2 JavaBBinder通过JNI层调用到Java Binder的execTransact方法:
前面我们知道了,Java实现的Service中,Service对象,JavaBBinderHolder,JavaBBinder存在相互引用关系,JavaBBinder的成员mObject引用了Java中的Service的Binder对象,比如此处的PMS,而且在int_register_android_os_Binder中通过
gBinderOffsets.mExecTransact = env->GetMethodID(clazz, "execTransact", "(IIII)Z");
将Service的execTransact方法(其实是Binder的方法)保存在了gBinderOffsets.mExecTransact中,所在以JavaBBinder::onTransact中会调用Binder.execTransact。
public class Binder implements IBinder { // 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); boolean res; try { res = onTransact(code, data, reply, flags); } catch{...} }}
3.3 Java Binder调用子类stub类中的onTransact()方法:
在Binder.execTransact中调用了onTransact,执行子类即IPackageManager.stub类的onTransact()方法
//out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/core/java/android/content/pm/IPackageManager.javapublic static abstract class Stub extends android.os.Binder implements android.content.pm.IPackageManager { ... @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:{return;} ... case TRANSACTION_deletePackage:{ data.enforceInterface(DESCRIPTOR); java.lang.String _arg0; _arg0 = data.readString(); android.content.pm.IPackageDeleteObserver2 _arg1; _arg1 = android.content.pm.IPackageDeleteObserver2.Stub.asInterface(data.readStrongBinder()); int _arg2; _arg2 = data.readInt(); int _arg3; _arg3 = data.readInt(); this.deletePackage(_arg0, _arg1, _arg2, _arg3);//调到这里 reply.writeNoException(); return true; } ... } ... } ...}
3.4 stub类onTransact()方法调用子类Service类的接口方法完成服务调用:
在IPackageManager.stub的onTransact方法中中根据code值执行相应的方法这里即调用 this.deletePackage()方法,最终则调用PackageManagerService类(继承自Stub)中相应的deletePackage()接口方法,执行该接口方法的功能。
至此,完成了Client端跨进程调用PKMS的deletePackage服务方法。
五、Java层Binder机制总结
- Java层Binder机制依赖于Native层的Binder框架,是对Native层的binder进行了java层的封装,通过JNI层进行联系。
- java层的binder机制的跨进程调用主要可以通过以下这张图高度概括:
- Client端通过获取Service端的服务代理XXServiceProxy来和Binder驱动进行通信;
- Service端有一个Binder线程监听着Binder驱动,监听到有发向自己的请求即通过native层的BBinder子类JavaBBinder经由JNI层通知到Java层的Binder子类IXXService.stub,从而通知到stub的子类Service的实现方法;
- Client端Service的服务代理XXServiceProxy持有一个BinderProxy类型的成员变量mRemote,该变量通过JNI层技术与native层的BpBinder对象相互持有引用,而BpBinder中的IPCThreadState与Binder驱动进行交流,通过这样的联系达到Java层Client端与Binder驱动交流的目的
- JavaBBinder对象通过JavaBBinderHolder与Java层的Binder类相互引用联系,而JavaBBinder的父类BBinder与BpBinder是一一对应的,这样Client端Binder代理对象经过Binder驱动与Server端Binder对象也建立了对应的
关系.
- Java层的Service其实就是个Binder,Service是Binder的子类的子类 ,Client端获取的是Binder的代理。
- 引用邓凡平的书中的经典的话,从通信的角度看,Binder的架构不论采用Native语言还是Java语言,都是Client要把请求传递到Binder驱动,Server端从Binder驱动中获取数据,通信的目的是向binder发送请求和接收回复。
- 本文只讲述了系统核心服务PKMS的注册及跨进程调用,当然跨进程调用的服务不止这些,日后继续分析普通service的跨进程调用,aidl的使用,以及应用层service的注册及调用细节。
参考博客:
Android FrameWork——Binder机制详解(1)
http://blog.csdn.net/stonecao/article/details/6657438
Android情景分析之深入解析system_server
http://blog.csdn.net/hu3167343/article/details/38375167
Binder in java
http://www.cnblogs.com/angeldevil/p/3328748.html
Android7.0 Binder通信(4) Java层中的Binder
http://blog.csdn.net/gaugamela/article/details/52577381
Binder机制4—Framework层
http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/0319/2622.html
《深入理解Android卷2》第2章 深入理解Java Binder 邓凡平
- Android Framework:Binder(6)-Java层Service的注册及跨进程调用
- Android Framework:Binder(5)-Native Service的跨进程调用
- 基于 Binder 的跨进程通信以及 Service(二):Java 层
- Java 层Binder的使用(Android framework)
- Android Framework:Binder(4)-Native Service的注册
- 【Android】跨进程调用service
- android 跨进程Service调用
- 基于 Binder 的跨进程通信以及 Service(一):Native 层
- Android Binder分析四:Java service的注册
- android 跨进程通信的代表Binder
- android跨进程调用Service(AIDL服务)
- 初学Android,跨进程调用Service(六十)
- Android AIDL跨进程调用Service
- Android:跨进程调用Services(AIDL Service)
- Android 跨进程调用service学(一)
- android 跨进程调用service学习(二)
- Android Binder分析五:Java service的获取和调用
- Android的Service与BroadcastReceiver之二 跨进程调用Service(AIDL Service)
- Firefox兼容OCX控件的方法
- 盘点2017年上半年移动互联网安全事件
- C#按钮控件数组绑定按钮时间和键盘操作事件
- nodejs搭建web服务器
- 1277: 连续和
- Android Framework:Binder(6)-Java层Service的注册及跨进程调用
- React-router表单跳转两种方法
- JZOJ1312.【USACO题库】5.1.1 Fencing the Cows圈奶牛
- C与C++的常错小细节
- the resource is not on the build path of a java project错误
- 在jsp页面中格式化时间
- 子窗口调用父窗口方法
- CSDN会用用我的账号搞事情?
- OkHttp3实现Cookies持续化管理