Android Framework:Binder(6)-Java層Service的註冊及跨進程調用

Android Framework:Binder(6)-Java層Service的註冊及跨進程調用
1、Java層Binder概述java

Java Binder及PKMS框架


   Java層中的binder和Native層的Binder在命名上儘可能保持了一致,且Java層的Binder依託於Native層的Binder,其實就是對底層的Binder的真正實現的一個封裝,最終仍是經過JNI技術調用到C/C++代碼的實現。。
  本文咱們從PKMS服務的初始化註冊和PKMS的服務調用來學習Java層Binder的知識。
  廢話不說先上圖:android

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的響應。cookie

2、Java層Binder框架初始化
  Android啓動初期,系統會提早一個專門負責搭建Java Binder和Native Binder交互關係的函數,該函數是register_android_os_Binder,代碼以下:數據結構

//frameworks/base/core/jni/android_util_Binder.cpp
int 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));
}app

咱們看到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));
}ide

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},
};

  保存一下方便往後查看。

3、PKMS初始化註冊服務
  咱們以PKMS初始化做爲分析Binder java層的入口。
  在SystemServer啓動PMKS的時候會在PackageManagerService的main函數中new出一個PKMS的實例m,並將PKMS的名稱和實例註冊至ServiceManager:

//frameworks\base\services\core\java\com\android\server\pm\PackageManagerService.java
public 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.java
public static final native IBinder getContextObject();
1
2
  看到getContextObject是個native方法,咱們找到它native的實現:

//frameworks/base/core/jni/android_util_Binder.cpp
static 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.cpp
jobject 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.java
static 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::ServiceManagerProxy
class 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.java
public final void writeStrongBinder(IBinder val) {
        nativeWriteStrongBinder(mNativePtr, val);
    }

  這是個Native方法實現的,找到該方法native實現的地方:

//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));
    }
}

  看到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.java
public Binder() {
    init();
    ...
}

private native final void init();

init是一個native實現的方法,咱們找到它實現的地方:

//frameworks/base/core/jni/android_util_Binder.cpp
static 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.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 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註冊本身的過程。
上圖總結下:

 

4、跨進程調用PKMS服務
  這裏以PackageInstaller使用PackageManager卸載應用爲例進行學習;

/packages/apps/PackageInstaller/src/com/android/packageinstaller/wear/WearPackageInstallerService.java
private 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.cpp
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;
}

  又是兩步操做,第一步是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);
1
  咱們在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.java
public 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.cpp
virtual 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");
1
將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.java
public 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服務方法。

5、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的註冊及調用細節。  

相關文章
相關標籤/搜索