Android ActivityManagerService 註冊到 Service Manager 的流程(上)

前面兩章學習分析了 ServiceManager 的啓動流程與獲取它代理對象的流程, 本章節開始對 Service 組件啓動後註冊到 ServiceManager 的流程進行分析.

前言

Service 組件是在 Server 進程中運行的. Server 進程在啓動時, 會首先將它裏面的 Service 組件註冊到 SM 中, 接着再啓動一個 Binder 線程池來等待和處理 Client 進程的通信請求.
本章內容以 ActivityManagerService 爲例, 一步步分析它是怎麼從啓動到註冊到 SM 中的. 在AMS 服務的的時候不會太詳細, 後面會有單獨的章節來分析它. 重點在於是如何註冊到 SM 中的.

首先是先來到系統服務 SystemServer 中. 看它的 main 方法

一. AMS 的啓動

1. SystemServer.main

源碼路徑 /frameworks/base/services/java/com/android/server/SystemServer.java

 public static void main(String[] args) {
   new SystemServer().run();
 }

在內部看到又調用了 run

2. SystemServer.run

源碼路徑 /frameworks/base/services/java/com/android/server/SystemServer.java

private void run() {
    ...
    mSystemServiceManager = new SystemServiceManager(mSystemContext);
    ...
    try {
            //啓動引導類服務
02        startBootstrapServices();
          //啓動核心類服務
          startCoreServices();
          //啓動其他服務
          startOtherServices();
    } catch (Throwable ex) {
        ...
    }
    ...
}

這裏會先創建 SystemServiceManager 對象, 這個後面會分析到, 直接進入到 2 處 startBootstrapServices(). AMS 屬於引導類服務, 很多服務也都依賴 AMS.

3. SystemServer.startBootstrapServices() 在啓動引導類服務中創建 AMS.

源碼路徑 /frameworks/base/services/java/com/android/server/SystemServer.java

private void startBootstrapServices() {
    ...
01   mActivityManagerService = mSystemServiceManager.startService(ActivityManagerService.Lifecycle.class).getService();
    ...
02  mActivityManagerService.setSystemProcess();
    ...
}

在代碼 01 處, 看到調用了 mSystemServiceManager.startService 傳入的參數是 Class, 那麼猜想應該是用來反射的. 進去看一下 startService 這個函數.

4. SystemServiceManager.startService 傳入 ActivityManagerService.Lifecycle.class

源碼路徑: /frameworks/base/services/core/java/com/android/server/SystemServiceManager.java


    private final ArrayList<SystemService> mServices = new ArrayList<SystemService>();

    public <T extends SystemService> T startService(Class<T> serviceClass) {
        final String name = serviceClass.getName();
        ...
        final T service;
        try {
01          Constructor<T> constructor = serviceClass.getConstructor(Context.class);
02          service = constructor.newInstance(mContext);
        } catch (InstantiationException ex) {
          ...  
        } 
        ...

03      mServices.add(service);
        try {
04         service.onStart();
        } catch (RuntimeException ex) {
            ...
        }
        return service;
    }

代碼 01 處 與 02 處創建了 ActivityManagerService.Lifecycle 對象, 並賦值給變量 service.
代碼 03 處將這個創建的 ActivityManagerService.Lifecycle 對象添加到變量 mServices 中. 在最上面看到 mServices 是一個集合. 保存的內容就是 SystemService 類型的.
代碼 04 處, 調用 ActivityManagerService.LifecycleonStart 函數.

找到 ActivityManagerService.Lifecycle 看一下它的構造函數和 onStart 函數.

5. ActivityManagerService.Lifecycle() & ActivityManagerService.Lifecycle.onStart()

源碼路徑:/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java


public final class ActivityManagerService extends ActivityManagerNative
        implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
  ...
  public static final class Lifecycle extends SystemService {
      private final ActivityManagerService mService;

      public Lifecycle(Context context) {
          super(context);
          mService = new ActivityManagerService(context);
      }

      @Override
      public void onStart() {
          mService.start();
      }

      public ActivityManagerService getService() {
          return mService;
      }
  }
  ...

Lifecycle 是 AMS 中的一個靜態內部類. 在構造函數內可以看到, 是在這裏創建了 ActivityManagerService 並保存到 mService 中.

然後在上面第4步中調用的 service.onStart(); 實際上調用的就是 ActivityManagerService.start() 函數.

接着將 AMS 添加到 SM 中. 回到第 3 步中. getService() 獲得了 AMS 對象, 接着在 02 行代碼處將 AMS 添加至 SM 中.

private void startBootstrapServices() {
    ...
01   mActivityManagerService = mSystemServiceManager.startService(ActivityManagerService.Lifecycle.class).getService();
    ...
02  mActivityManagerService.setSystemProcess();
    ...
}

二. 將 ActivityManagerService 添加至 ServiceManager

6. mActivityManagerService.setSystemProcess()

源碼路徑:/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

public void setSystemProcess() {
     ...
   ServiceManager.addService(Context.ACTIVITY_SERVICE, this, true);
   ...
}

終於看到了 addService 函數的調用. 進入 ServiceManager.addService 看是如何添加的.
其中 Context.ACTIVITY_SERVICE 的定義爲 public static final String ACTIVITY_SERVICE = "activity";
`

7. ServiceManager.addService

源碼路徑: /frameworks/base/core/java/android/os/ServiceManager.java

public static void addService(String name, IBinder service, boolean allowIsolated) {
    try {
        getIServiceManager().addService(name, service, allowIsolated);
    } catch (RemoteException e) {
        Log.e(TAG, "error in addService", e);
    }
}

先調用 ServiceManager 類的靜態成員函數 getIServiceManager 來獲得一個 ServiceManager 的 Java 代理對象 ServiceManagerProxy. 接着再調用這個 Java 代理對象的成員函數 addService 將 AMS 註冊到 SM 中. 指定了這個 Service 的註冊名稱爲 activity.

這裏通過兩步來分析先來看 getIServiceManager

8. getIServiceManager 獲得 SM 的代理對象

源碼路徑: /frameworks/base/core/java/android/os/ServiceManager.java

  private static IServiceManager sServiceManager;

  private static IServiceManager getIServiceManager() {
      if (sServiceManager != null) {
          return sServiceManager;
      }
      ...
      sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());
      return sServiceManager;
  }

首先判斷 ServiceManager.java 類的靜態成員變量 sServiceManager 是否爲 NULL, 不爲 NULL 說明之前已經獲創建過代理對象. 所以直接返回給調用者.
否則就先通過 BinderInternal 類的靜態成員函數 getContextObject 創建一個句柄值等等於 0 的 Java 服務代理對象, 接着再通過 ServiceManagerNative.asInterface 函數將這個 Java 服務代理對象封裝成一個 ServiceManagerProxy 對象.保存在 sServiceManager 中並返回給調用者.

下面分別分析BinderInternal.getContextObject()ServiceManagerNative.asInterface

9. BinderInternal.getContextObject()

BinderInternal 類的靜態成員函數 getContextObject 是一個 JNI 方法, 定義如下
源碼路徑: /frameworks/base/core/java/com/android/internal/os/BinderInternal.java

public static final native IBinder getContextObject();

它是由 C++ 層中的函數 android_os_BinderInternal_getContextObject() 來實現的.
源碼路徑: /frameworks/base/core/java/jni/android_util_Binder.cpp

static jobject android_os_BinderInternal_getContextObject(JNIEnv* env, jobject clazz)
{
    sp<IBinder> b = ProcessState::self()->getContextObject(NULL);
    return javaObjectForIBinder(env, b);
}

看到這裏, 終於看到熟悉的了 ProcessState::self()->getContextObject. 如果看過上一章, 對這個肯定不會陌生.
這行代碼就是創建一個 BpBinder 對象. 接着調用 javaObjectForIBinder 對這個 Binder 代理對象創建一個 Java 服務代理對象, 即一個 BinderProxy 對象. 返回給調用者.

10. javaObjectForIBinder 創建 Java 服務代理對象

源碼路徑: /frameworks/base/core/java/com/android/internal/os/BinderInternal.java

jobject javaObjectForIBinder(JNIEnv* env, const sp<IBinder>& val)
{
      if (val == NULL) return NULL;
  
          //檢查是 Binder 代理對象還是 本地丟西
      if (val->checkSubclass(&gBinderOffsets)) {
         ...
      }


01    jobject object = (jobject)val->findObject(&gBinderProxyOffsets);
      if (object != NULL) {
02        jobject res = jniGetReferent(env, object);
          if (res != NULL) {
                ...
              return res;
          }
          
                    ...
03        val->detachObject(&gBinderProxyOffsets);
          ...
      }

04    object = env->NewObject(gBinderProxyOffsets.mClass, gBinderProxyOffsets.mConstructor);
      if (object != NULL) {
05        env->SetLongField(object, gBinderProxyOffsets.mObject, (jlong)val.get());
06          val->incStrong((void*)javaObjectForIBinder);

          jobject refObject = env->NewGlobalRef(
            env->GetObjectField(object, gBinderProxyOffsets.mSelf));
07          val->attachObject(&gBinderProxyOffsets, refObject, jnienv_to_javavm(env), proxy_cleanup);
                ...
      }

      return object;
}

代碼 01 處調用 Binder 代理對象(BpBinder) val 的成員函數 findObject 來檢查當前進程之前是否已經創建過一個 Java 服務代理對象了(BinderProxy), 如果是接着在代碼 02 處接着檢查它的有效性, 如果未失效則直接返回給調用者. 如果失效就在代碼 03 處調用 Binder 代理對象(BpBinder) val 的成員函數 detachObject 來解除它與一個無效 Java 服務代理對象(BinderProxy) 的對應關係.

如果代碼 01 處檢查之前沒有創建過一個 Java 服務代理對象(BinderProxy), 在代碼 04 處就會爲它創建一個 Java 服務代理對象(BinderProxy) object. 如果創建成功, 接着來在代碼 05 處將 Binder 代理對象(BpBinder) val 的地址值設置到上一步創建的 Java 服務代理對象(BinderProxy) object 的成員變量 mObject 中. 即 BinderProxy.mObject 記錄了 BpBinder 對象. 因此在代碼 06 處增加 Binder 代理對象(BpBinder) val的強引用計數, 因爲它被 Java 服務代理對象(BinderProxy) object 引用了

代碼 07 處通過全局變量 gBinderProxyOffsets 將這個全局引用對象與 Binder 代理對象(BpBinder) val 關聯起來. 相當於將創建的 Java 服務代理對象(BinderProxy) object 與 Binder 代理對象(BpBinder)的 val 關聯起來. 這樣以後再以 Binder 代理對象(BpBinder) val 爲參數來調用函數 javaObjectForIBinder 時, 就可以直接獲得保存在它內部的成員變量 mObjects 中的 Java 服務代理對象(BinderProxy) 了.

Binder 代理對象內部有一個成員變量 mObjects, 類型是 ObjectManager, 用來管理與 Binder 代理對象關聯的外部對象. 例如 javaObjectForIBinder函數在爲一個 Binder 代理對象創建一個 Java 服務代理對象時, 就會將創建出來的 Java 服務代理對象保存在該 Binder 代理對象的成員變量 mObjects 中, 以便以後需要獲取與該 Binder 代理對象對應的 Java 服務代理對象時, 就可以通過它的成員變量 mObjects 來直接獲得. 由於一個 Binder 代理對象所關聯的外部對象可能不止一個, 因此需要通過額外的一個參數來關聯一個 Binder 代理對象和一個 Java 服務代理對象, 這個參數就是全局變量 gBinderProxyOffsets 的地址值.

注: Java 服務代理對象即: BinderProxy.
注: Binder 代理對象級: BpBinder.

最後返回這個 Java 服務代理對象. 接着回到第 8 步. 繼續向下分析.
BinderInternal.getContextObject() 已經分析完了, 它返回了一個句柄值等於 0 的Java 服務代理對象. 接下來就可以調用 ServiceManagerNative 類的靜態成員函數 asInterface 將它封裝成一個 ServiceManager 的 Java 代理對象了

  private static IServiceManager sServiceManager;

  private static IServiceManager getIServiceManager() {
      if (sServiceManager != null) {
          return sServiceManager;
      }
      ...
      sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());
      return sServiceManager;
  }

11. ServiceManagerNative.asInterface 創建 ServiceManagerProxy 對象

源碼路徑: /frameworks/base/core/java/android/os/ServiceManagerNative.java

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

參數 obj 指向的是一個 Java 服務代理對象.即一個 BinderProxy 對象. 它的成員函數 queryLocalInterface的返回值爲 NULL, 因此最後會創建一個 ServiceManagerProxy 代理對象. 即 SM 的 Java 代理對象. 返回給調用者.

class ServiceManagerProxy implements IServiceManager {
    public ServiceManagerProxy(IBinder remote) {
        mRemote = remote;
    }
}

ServiceManagerProxy 構造方法中將傳入的Java 服務代理對象賦值給 ServiceManagerProxy 中的類成員變量 mRemote.

注: mRemote 指向的是句柄值是 0 的 Java 服務代理對象, 即 BinderProxy, BinderProxy 在第 10 步被創建出來後又與 Binder 代理對象 BpBinder 進行了關聯.

現在第8步分析完成了, 最終返回了一個 Java 代理對象 ServiceManagerProxy, 繼續向上返回, 返回到第 7 步. 代碼如下.

public static void addService(String name, IBinder service, boolean allowIsolated) {
    try {
        getIServiceManager().addService(name, service, allowIsolated);
    } catch (RemoteException e) {
        Log.e(TAG, "error in addService", e);
    }
}

看到又調用了 ServiceManagerProxy 中的函數 addService, 其中參數 name 對應的值爲 activity. service 爲 AMS 對象.

12. ServiceManagerProxy.addService

源碼路徑: frameworks/base/core/java/android/os/ServiceManagerNative.java$ServiceManagerProxy.java

public void addService(String name, IBinder service, boolean allowIsolated)
        throws RemoteException {
      Parcel data = Parcel.obtain();
      Parcel reply = Parcel.obtain();
01    data.writeInterfaceToken(IServiceManager.descriptor);
02    data.writeString(name);
03    data.writeStrongBinder(service);
      data.writeInt(allowIsolated ? 1 : 0);
 04   mRemote.transact(ADD_SERVICE_TRANSACTION, data, reply, 0);
      reply.recycle();
      data.recycle();
}

創建了兩個 Parcel 對象 datareply, data 是用來封裝進程間通信數據的, reply 是用來封裝進程間通信結果數據的.

代碼 01 處調用 Parcel 對象 data 的成員函數 writeInterfaceToken 寫入一個進程間通信頭.
代碼 02 處是寫入即將要註冊的 Java 服務的名稱. 這裏的名稱爲 activity.
代碼 03 處寫入要註冊的 Java 服務對象.
代碼 04 處調用成員變量 mRemotetransact 函數向 SM 發送一個類型爲 ADD_SERVICE_TRANSACTION 的進程間通信請求, 即請求 SM 將一個 Java 服務註冊進去.

mRemote 在第 11 步中有強調過. 它指向一個句柄值爲 0 的 Java 服務代理對象 BinderProxy.

這裏呢先來分析 data.writeStrongBinder 看是如何將 AMS 寫入到 data 中的.
接着再來看 mRemote.transact 是如何處理這個進程間通信請求的.

Parcel 是用來封裝進程間通信數據的, Java 層中的每一個 Parcel 對象在 C++層中都有一個對應的 Parcel 對象, 後者的地址就保存在前者的成員變量 mObject 中. 當將進程間通信的數據封裝在一個 Java 層的 Parcel 對象時, 這個 Java 層中的 Parcel 對象就會通過其成員變量 mObject 找到與它對應的運行在 C++ 層中的 Parcel 對象.並且將這些進程間通信數據封裝到 C++ 層中的 Parcel 對象裏面去.

13. Parcel.writeStrongBinder

Java 層的 writeStrongBinder 是一個 JNI 方法. 定義如下
源碼路徑: /frameworks/base/core/java/android/os/Parcel.java

public final void writeStrongBinder(IBinder val) {
    nativeWriteStrongBinder(mNativePtr, val);
}

對應的實現函數爲 android_os_Parcel_writeStrongBinder.

14. android_os_Parcel.android_os_Parcel_writeStrongBinder

源碼路徑: /frameworks/base/core/jni/android_os_Parcel.cpp

static void android_os_Parcel_writeStrongBinder(JNIEnv* env, jclass clazz, jlong nativePtr, jobject object)
{
01    Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
      if (parcel != NULL) {
02        const status_t err = parcel->writeStrongBinder(ibinderForJavaObject(env, object));
        ...
    }
}

代碼 01 處. 調用函數 reinterpret_cast 得到一個與 Java 層 Parcel 對應的, 運行在 C++ 層的 Parcel 對象 parcel.

代碼 02 處先調用函數 ibinderForJavaObject 來獲得一個與他對應的 Binder 本地對象, 再將這個 Binder 本地對象寫入到上一步得到的 C++層的 Parcel 對象 parcel 中.

這裏也分爲兩步. 先看 ibinderForJavaObject 如何獲得一個對應的 Binder 本地對象的.
接着再分析 writeStrongBinder 寫入.

15. android_util_Binder.ibinderForJavaObject

源碼路徑: /frameworks/base/core/jni/android_util_Binder.cpp

sp<IBinder> ibinderForJavaObject(JNIEnv* env, jobject obj)
{
    ...
    //是否是 Java 服務
    if (env->IsInstanceOf(obj, gBinderOffsets.mClass)) {
01      JavaBBinderHolder* jbh = (JavaBBinderHolder*) env->GetLongField(obj, gBinderOffsets.mObject);
        return jbh != NULL ? jbh->get(env, obj) : NULL;
    }
    //是否是 Java 服務代理對象
    if (env->IsInstanceOf(obj, gBinderProxyOffsets.mClass)) {
        return (IBinder*) env->GetLongField(obj, gBinderProxyOffsets.mObject);
    }
  ...
  return NULL;
}

這兩個 if 意思是 參數 obj 要麼指向一個 Java 服務, 要麼指向一個 Java 服務代理對象. 否則最後會返回 NULL, 表示它不能將參數 obj 轉換成一個 Binder 本地對象或者 Binder 代理對象.

此時我們傳入的 obj 是 AMS, 即是一個 Java 服務.所以命中第一個 if. gBinderOffsets.mObject 指向的是一個 Java 服務的成員變量 mObject 中保存的與其對應的一個 JavaBBinderHolder 對象.

代碼 01 處就是將參數 obj 即 AMS 服務對象的成員變量 mObject 轉換爲一個 JavaBBinderHolder 對象 jbh.
接着調用 JavaBBinderHolder 對象的 jbh 的成員函數 get 來獲得一個 Binder 本地對象 BBinder.

如果傳入的 obj 是一個 Java 服務代理對象, 那麼命中第二個 if, 就找到與它對應的一個 Binder 代理對象. 並將這個 Binder 代理對象返回給調用者. 在上面第 10 步中的 05 行代碼處創建好 Java 服務代理後將 Binder 代理服務對象的地址保存在 Java 服務代理對象的成員變量 mObject 中. 因此這裏可以輕易的根據 Java 服務代理對象 BinderProxy 找到與之對應的 Binder 代理對象 BpBinder.

16. JavaBBinderHolder.get 獲得 BBinder

源碼路徑: /frameworks/base/core/jni/android_util_Binder.cpp$JavaBBinderHolder

class JavaBBinderHolder : public RefBase
{
private:
    ...
    wp<JavaBBinder> mBinder;

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

成員變量 mBinder 指向的是一個類型爲 JavaBBinder 的 Binder 本地對象.
參數 obj 指向的是一個 Java 服務即 AMS 服務.

成員函數 get 用來將成員變量 mBinder 所指向的一個JavaBBinder 對象返回給調用者. 由於成員變量 mBinder是一個弱指針, 此時可能已經被銷燬, 因此在返回給調用者之前, 先要調用 mBinder.promote() 將它升級爲一個強指針, 如果升級成功, 直接返回給調用者.

否則就需要先創建一個 JavaBBinder 對象, 將 AMS 服務傳入, 同時將結果保存在成員變量 mBinder 中.

17. new JavaBBinder

源碼路徑: /frameworks/base/core/jni/android_util_Binder.cpp$JavaBBinder

class JavaBBinder : public BBinder
{
private:
    ...
    jobject const   mObject;

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

JavaBBinder 的 Binder 本地對象內部也有一個成員變量 mObject, 指向的是一個 Java 服務. 在構造函數中被初始化. 流程走到這裏 mObject 指向的就是 AMS 服務.

好了, 第 14 步中的 ibinderForJavaObject 分析完了, 返回了一個了一個 JavaBBinder 對象. 第 14 步代碼如下

static void android_os_Parcel_writeStrongBinder(JNIEnv* env, jclass clazz, jlong nativePtr, jobject object)
{
01    Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
      if (parcel != NULL) {
02        const status_t err = parcel->writeStrongBinder(ibinderForJavaObject(env, object));
        ...
    }
}

接着調用 parcel->writeStrongBinder 函數, 傳入參數爲 JavaBBinder對象.

18. parcel->writeStrongBinder

源碼路徑: /frameworks/native/libs/binder/Parcel.cpp

status_t Parcel::writeStrongBinder(const sp<IBinder>& val)
{
    return flatten_binder(ProcessState::self(), val, this);
}

這一步操作是調用全局函數 flatten_binderJavaBBinder 封裝成爲一個 flat_binder_object 結構體.

19. parcel->flatten_binder

源碼路徑: /frameworks/native/libs/binder/Parcel.cpp

status_t flatten_binder(const sp<ProcessState>& /*proc*/,
    const sp<IBinder>& binder, Parcel* out)
{
    flat_binder_object obj;
        ...
    if (binder != NULL) {
        IBinder *local = binder->localBinder();
        if (!local) {
            ...
        } else {
            obj.type = BINDER_TYPE_BINDER;
            obj.binder = reinterpret_cast<uintptr_t>(local->getWeakRefs());
            obj.cookie = reinterpret_cast<uintptr_t>(local);
        }
    } else {
       ...
    }
    return finish_flatten_binder(binder, obj, out);
}

首先定義了一個 flat_binder_object 結構體 obj. 接着判參數 binder 是否爲 NULL, 我們傳入的參數是 JavaBBinder 對象不爲 NULL, 所以直接命中 if.

通過前面的調用知道參數 binder 指向的是 JavaBBinder, 它繼承了 BBinder. 而 BBinder 又是用來描述一個 Binder 本地對象的. 因此 localBinder 函數返回不爲 NULL. 所以 if(!local) 不會命中, 而是直接執行 else 中的代碼. 將flat_binder_object 結構體 obj 設置爲一個 BINDER_TYPE_BINDER 類型的 Binder 對象, 並且將它的成員變量 cookiebinder 的值分別設置爲 Binder 本地對象 local 的地址以及其內部的一個弱引用計數對象的地址值.

最後調用全局函數 finish_flatten_binderobj 寫入到 Parcel 對象 out 中.

當結構體 flat_binder_object 描述的是一個 Binder 實體對象時, 就使用成員變量 binder 來指向與該 Binder 實體對象對應的一個 Service 組件內部的一個弱引用計數對象的地址, 並且使用成員變量 cookie 來指向該 Service 組件的地址.

當結構體 flat_binder_object 描述的是一個 Binder 引用對象時, 那麼就使用成員變量 handle 來描述該 Binder 引用對象的句柄值.

20. parcel->finish_flatten_binder

源碼路徑: /frameworks/native/libs/binder/Parcel.cpp

inline static status_t finish_flatten_binder(
    const sp<IBinder>& /*binder*/, const flat_binder_object& flat, Parcel* out)
{
    return out->writeObject(flat, false);
}

至此, 在第 12 步中的 data.writeStrongBinder(service); 到這裏就分析完了. 在第 12 步中傳入的 AMS 服務, 到最後寫入的實際上是一個 flat_binder_object 結構體. 接下來繼續分析第 12 步中的下一個操作. 第 12 步代碼如下

public void addService(String name, IBinder service, boolean allowIsolated)
        throws RemoteException {
      Parcel data = Parcel.obtain();
      Parcel reply = Parcel.obtain();
01    data.writeInterfaceToken(IServiceManager.descriptor);
02    data.writeString(name);
03    data.writeStrongBinder(service);
      data.writeInt(allowIsolated ? 1 : 0);
 04   mRemote.transact(ADD_SERVICE_TRANSACTION, data, reply, 0);
      reply.recycle();
      data.recycle();
}

代碼 04 處調用成員變量 mRemote 的 transact 函數向 SM 發送一個類型爲 ADD_SERVICE_TRANSACTION 的進程間通信請求, 即請求 SM 將一個 Java 服務註冊進去. mRemote 即 BinderProxy. 指向一個句柄值爲 0 的 Java 服務代理對象.

21. BinderProxy.transact 開始發送進程間通信請求.

BinderProxy 類的成員函數 transact 是一個 JNI 方法. 定義如下

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;

對應的實現在 android_util_Binder.cpp 中的 android_os_BinderProxy_transact 函數.

22. android_util_Binder.android_os_BinderProxy_transact

源碼路徑 /frameworks/base/core/jni/android_util_Binder.cpp

static jboolean android_os_BinderProxy_transact(JNIEnv* env, jobject obj,
        jint code, jobject dataObj, jobject replyObj, jint flags) // throws RemoteException
{
      ...
01    Parcel* data = parcelForJavaObject(env, dataObj);
      ...
02    Parcel* reply = parcelForJavaObject(env, replyObj);
      ...
03    IBinder* target = (IBinder*) env->GetLongField(obj, gBinderProxyOffsets.mObject);
      ...
04    status_t err = target->transact(code, *data, reply, flags);
      ...
}

代碼 01 處與 02 處分別將 Java 層中的兩個 Parcel 對象 dataObj, replyObj 轉爲 C++層中的 Parcel 對象data ,reply . data 中包含了要傳遞給 SM 的進程間通信數據, reply 用來保存從 SM 返回的數據結果.

參數 obj 指向的是一個 Java 服務代理對象, 即 BinderProxy.
代碼 03 處就是獲得這個代理對象的 Binder 代理對象. 即 BpBinder. 保存到變量 target 中.

代碼 04 處調用 target 的成員函數 transact 想 SM 發送一個類型爲 code 的進程間通信請求. code 值爲 ADD_SERVICE_TRANSACTION. 當 SM 收到這個進程間通信請求後, 就會將保存在 Parcel對象 data 中的一個 Binder 本地對象的信息取出來後註冊到它的內部去. 那現在進入到 BpBinder 的 transact 函數內.

data 中保存的 Binder 本地對象信息即在第 13 - 20 步中寫入的 flat_binder_object 結構體, 在 19 步中將這個結構體的成員變量 cookie 設置爲 Binder 本地對象. 這個本地對象是在 17 步中創建的 JavaBBinder.

23. BpBinder.transact

源碼路徑: /frameworks/native/libs/binder/BpBinder.cpp

status_t BpBinder::transact(
    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
    if (mAlive) {
        status_t status = IPCThreadState::self()->transact(mHandle, code, data, reply, flags);
        if (status == DEAD_OBJECT) mAlive = 0;
        return status;
    }
    return DEAD_OBJECT;
}

從前面的調用過程可以知道, 第一個參數 code 值爲 ADD_SERVICE_TRANSACTION, 第二個參數 data 包含了要傳遞給 Binder 驅動程序進程間通信數據. 第三個參數 reply 是一個輸出參數, 用來保存進程間通信的結果. 第四個參數 flags 用來描述這是一個同步的進程間通信請求還是異步的. 默認值爲 0, 表示同步.

成員變量 mAlive 用來描述 Binder 代理對象所引用的 Binder 本地對象是否還活着, 如果還活着,即值爲 1. 在 if內纔會調用當前線程的 IPCThreadState 對象的成員函數 transact 想 Binder 驅動發送一個 BC_TRANSACTION 命令協議.

Binder 代理對象中的成員變量 mHandle 用來描述該 Binder 代理對象的句柄值. 由於目前正在處理的 Binder 代理對象指向的是 SM 的代理對象. 因此 mHandle 的值就等於 0.

現在進入 IPCThreadStatetransact 函數.

24.IPCThreadState.transact 向 Binder 驅動程序發送 BC_TRANSACTION 命令協議

源碼路徑: /frameworks/native/libs/binder/IPCThreadState.cpp

status_t IPCThreadState::transact(int32_t handle,
                                  uint32_t code, const Parcel& data,
                                  Parcel* reply, uint32_t flags)
{
01    status_t err = data.errorCheck();
02    flags |= TF_ACCEPT_FDS;
          ...
       if (err == NO_ERROR) {
         ...
03       err = writeTransactionData(BC_TRANSACTION, flags, handle, code, data, NULL);
      }
          ...    
04    if ((flags & TF_ONE_WAY) == 0) {
                ...
          if (reply) {
05            err = waitForResponse(reply);
          } else {
              ...
          }
                ...
      } else {
         ...
      }
      
      return err;
}

代碼 01 處是檢查 Parcel 對象 data 中的進程間通信數據是否正確.

代碼 02 處將參數 flagTF_ACCEPT_FDS 位設置爲 1, 表示允許 Server 進程在返回結果中攜帶文件描述.
如果 data 中的數據沒有問題, 執行代碼 03 處. 調用成員函數 writeTransactionData 將它的內容寫到一個 binder_transaction_data 結構體中.

代碼 04 處判斷是同步請求還是異步請求, 本次爲同步請求, 接着判斷用來保存通信結果的 reply 是否爲 NULL, 不爲 NULL 就調用成員函數 waitForResponse 向 Binder 驅動程序發送一個 BC_TRANSACTION 命令協議.

接下來主要是分析兩個函數, writeTransactionDatawaitForResponse 的實現

25. IPCThreadState.writeTransactionData

源碼路徑: /frameworks/native/libs/binder/IPCThreadState.cpp

status_t IPCThreadState::writeTransactionData(int32_t cmd, uint32_t binderFlags,
    int32_t handle, uint32_t code, const Parcel& data, status_t* statusBuffer)
{
01    binder_transaction_data tr;

      ...
      tr.target.handle = handle;
      tr.code = code;
      tr.flags = binderFlags;
          ...
        
02    const status_t err = data.errorCheck();
      if (err == NO_ERROR) {
          tr.data_size = data.ipcDataSize();
          tr.data.ptr.buffer = data.ipcData();
          tr.offsets_size = data.ipcObjectsCount()*sizeof(binder_size_t);
          tr.data.ptr.offsets = data.ipcObjects();
      } else if (statusBuffer) {
         ...
      } else {
              ...
      }
03    mOut.writeInt32(cmd);
04    mOut.write(&tr, sizeof(tr));
    return NO_ERROR;
}

在代碼 01 處, 先定義了一個 binder_transaction_data 結構體 tr, 接着下面幾行代碼就對它進行了初始化操作. 經過前面調用已知 handle = 0, code = ADD_SERVICE_TRANSACTION, binderFlags = TF_ACCEPT_FDS.

代碼 02 處再次確認 data 中進程間通信數據的正確性. 如果沒有問題則命中if.
data 內部的數據緩衝區和偏移數組設置爲 binder_transaction_data 結構體 tr 的數據緩衝區與偏移數組.

代碼 03 與 04 處將 BC_TRANSACTION 命令協議以及 binder_transaction_data 寫入到 IPCThreadState 成員變量 mOut 所描述的一個命令協議緩衝區中. 表示它有一個 BC_TRANSACTION命令協議需要發送給 Binder 驅動程序處理.

BC_TRANSACTION 命令協議寫入到 IPCThreadState類內部的命令協議緩衝區後, 回到 第 24 步. 接下來就需要調用成員函數 waitForResponse 向 Binder 驅動程序發送這個命令協議了.

26. IPCThreadState.waitForResponse

源碼路徑: /frameworks/native/libs/binder/IPCThreadState.cpp

status_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult)
{
    uint32_t cmd;
    int32_t err;

    while (1) {
        if ((err=talkWithDriver()) < NO_ERROR) break;
       ...
    }
    return err;
}

通過一個 while 循環不斷的調用成員函數 talkWithDriver 來與 Binder 驅動程序進行交互. 以便可以將在第 25 步中準備好的 BC_TRANSACTION 命令協議發送給 Binder 驅動程序處理. 並等待 Binder 驅動程序將進程通信結果返回回來.

OK. 其實一路分析到這裏, 纔算是開始. 現在進入 talkWithDriver

27. IPCThreadState.talkWithDriver

源碼路徑: /frameworks/native/libs/binder/IPCThreadState.cpp

 //參數 doReceive 用來描述調用者是否希望函數 talkWithDriver  
 //只接受 Binder 驅動程序發送給該進程的返回協議. 該參數默認爲 `true`. 
 status_t IPCThreadState::talkWithDriver(bool doReceive)
{
        ...
    //talkWithDriver 函數使用 IO 控制命令 BINDER_WRITE_READ 來與 Binder 驅動程序進行交互
    //因此這裏需要先定義一個結構體來指定輸入緩衝區和輸出緩衝區.
    //其中輸出緩衝區是保存的是進程發給 Binder 驅動程序的命令協議, 
    //而輸入緩衝區保存的是 Binder 驅動程序發送給進程的返回協議, 
    //它們分別與 `IPCThreadState` 類內部的命令協議緩衝區 `mOut` 和返回協議緩衝區 `mIn` 相對應.
    binder_write_read bwr;
    
 01   const bool needRead = mIn.dataPosition() >= mIn.dataSize();
    
 02   const size_t outAvail = (!doReceive || needRead) ? mOut.dataSize() : 0;
      
      //將變量 write_size 的值設置爲 binder_write_read 結構體 bwr 的
      //輸出緩衝區的長度 write_size     
      bwr.write_size = outAvail;

      //將 IPCThreadState 類內部的命令協議緩衝區 mOut 
      //設置爲 binder_write_read 結構體 bwr 的輸出緩衝區.
      bwr.write_buffer = (uintptr_t)mOut.data();

03    if (doReceive && needRead) {
        bwr.read_size = mIn.dataCapacity();
        bwr.read_buffer = (uintptr_t)mIn.data();
      } else {
        bwr.read_size = 0;
        bwr.read_buffer = 0;
      }
    ...
04    do {
        ...
        if (ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr) >= 0)
            err = NO_ERROR;
        else
            err = -errno;
                ...
 05   } while (err == -EINTR);
    ...
    if (err >= NO_ERROR) {
06        if (bwr.write_consumed > 0) {
            if (bwr.write_consumed < mOut.dataSize())
                mOut.remove(0, bwr.write_consumed);
            else
                mOut.setDataSize(0);
07        }
        if (bwr.read_consumed > 0) {
             mIn.setDataSize(bwr.read_consumed);
 08          mIn.setDataPosition(0);
        }
        ...
        return NO_ERROR;
    }
    
    return err;
}

從前面的調用可知, mOut 中存在一個 BC_TRANSACTION 命令協議.

IPCThreadState 內部, 除了使用緩衝區 mOut 來保存即將要發送給 Binder 驅動程序的命令協議外, 還用緩衝區 mIn 來保存那些從 Binder 驅動程序接收到的返回協議

一個進程使用 IO 控制命令 BINDER_WRITE_READ 進入到 Binder 驅動程序, 傳遞的 binder_write_read 結構體的輸出緩衝區和輸入緩衝區的長度分別等於 0 和大於 0 時, Binder 驅動程序就不會處理進程發送的命令協議, 而只會對該進程發送返回命令協議, 這樣進程就達到了接收返回協議的結果.

只接收返回協議還會受到返回協議緩衝區 mIn 的影響. 如果上次 Binder 發送給進程的返回協議已經處理完成, 即返回協議緩衝區 mIn 中的返回協議已經處理完成, 那麼即使參數 doReceivetrue, IPCThreadState 的成員函數 talkWithDriver 也會向 Binder 驅動程序發送命令協議.

因此如果返回協議緩衝區 mIn 的返回協議已經處理完成, 即代碼 01 處得到的 needRead 變量值爲 true. 或者調用者不是隻希望接收 Binder 驅動程序發送給進程的返回協議, 及參數 doReceivefalse, 那麼代碼 02 處就將變量 outAvail 的值設置爲 IPCThreadState 類內部的命令協議緩衝區的長度. 否則就設置爲 0.

從前面的調用過程可以知道, 參數 doReceive 的值爲 true, 假設此時 IPCThreadState 類內部的返回協議緩衝區 mIn 沒有包含未處理的返回協議, 那麼 needRead 值爲 true. 命中代碼 03 處 if 判斷. 在判斷內將 binder_write_read結構體 bwr 的輸入緩衝區 read_buffer設置爲類內部的返回協議緩衝區 mIn.

代碼 04 處到 05 處的 while 循環使用 IO 控制命令 BINDER_WRITE_READ 來與 Binder 驅動程序進行交互. 由於這時候傳遞給 Binder 驅動程序的 binder_write_read 結構體 bwr 輸出緩衝區的長度 write_size 和 輸入緩衝區 read_size 的長度均大於 0. 因此 Binder 驅動程序在處理 IO 控制命令 BINDER_WRITE_READ 時, 就會首先調用函數 binder_thread_write 來處理進程發送給它的 BC_TRANSACTION 命令協議. 接着又會調用函數 binder_thread_read 來讀取 Binder 驅動程序給進程發送的返回協議.

當從驅動層返回後, 代碼 06-07 處將 Binder 驅動程序已經處理的命令協議從 IPCThreadState 類內部的命令協議緩衝區 mOut 中移除, 接着在代碼 08 處將從 Binder 驅動程序中讀取出來的返回協議保存在類內部的返回協議緩衝區 mIn 中. 這樣這個函數執行完再返回到第 26 步的時候. 就可以通過解析返回協議緩衝區 mIn 的內容來執行相對應的操作了.

現在就要進入到 Binder 驅動層了, 來分析是如何處理這個命令協議的.

28. binder_ioctl_write_read

源碼路徑: kernel 3.18下的 /drivers/staging/android/binder.c

static int binder_ioctl_write_read(struct file *filp,
                unsigned int cmd, unsigned long arg,
                struct binder_thread *thread)
{
    ...
    ...

        ret = binder_thread_write(proc, thread,
                      bwr.write_buffer,
                      bwr.write_size,
                      &bwr.write_consumed);
    ...
}

直接進入到 binder_thread_write 函數

29. binder_thread_write

源碼路徑: kernel 3.18下的 /drivers/staging/android/binder.c

static int binder_thread_write(struct binder_proc *proc,
            struct binder_thread *thread,
            binder_uintptr_t binder_buffer, size_t size,
            binder_size_t *consumed)
{

    while (ptr < end && thread->return_error == BR_OK) {
        switch (cmd) {
        ...
        case BC_TRANSACTION:
        case BC_REPLY: {
            ...
            binder_transaction(proc, thread, &tr, cmd == BC_REPLY, 0);
            break;
        }
        ...
        }
        *consumed = ptr - buffer;
    }
    return 0;
}

從代碼中可以看出又調用了 binder_transaction 函數. 進入到這個函數. 傳入的參數中
cmd == BC_REPLY 值爲 false, 因爲這個時候 cmd 的值爲 BC_TRANSACTION.

30. binder_transaction

源碼路徑: kernel 3.18下的 /drivers/staging/android/binder.c
這個函數有點長, 將會分爲四段來分析.

static void binder_transaction(struct binder_proc *proc,
                   struct binder_thread *thread,
                   struct binder_transaction_data *tr, int reply,
                   binder_size_t extra_buffers_size)
{
        struct binder_proc *target_proc;
        struct binder_node *target_node = NULL;
    ...
    if (reply) {
        ...
    } else {
        if (tr->target.handle) {
            ...
01      } else {
            target_node = context->binder_context_mgr_node;
            ...
        }
        ...
02      target_proc = target_node->proc;
                ...
    }
03  if (target_thread) {
        e->to_thread = target_thread->pid;
        target_list = &target_thread->todo;
        target_wait = &target_thread->wait;
    } else {
        target_list = &target_proc->todo;
        target_wait = &target_proc->wait;
    }

在上一步知道 replyfale , 所以直接進 else. 由於目標 Binder 的引用對象的句柄值爲 0, 所以直接執行代碼 01 處的 else 邏輯. 將目標 Binder 實體對象 target_node 指向一個引用了 SM 的 Binder 實體對象 binder_context_mgr_node. 如果進的是 if 就需要先獲得與句柄值對應的 Binder 引用對象. 再通過這個引用對象的成員變量 node 來找到目標 Binder 實體對象 target_node.

binder_context_mgr_node 的賦值是在 上一章 Android Service Manager 的啓動流程中的第6 步忘記的,可以返回去看一下.

找到了目標 Binder 實體對象以後, 代碼 02 處就可以根據它的成員變量 proc 來找到目標進程 target_proc.

如果在目標進程 target_proc 中找到了一個最優的目標線程 target_thread 來接收 BR_TRANSACTION 返回協議那麼就命中代碼 03 處 if, 將變量 target_listtarget_wait 分別指向最優線程的 todowait 隊列.. 否則就指向目標進程的 todowait 隊列. 有了這兩個隊列後, 函數接下來就可以將一個 BR_TRANSACTION 返回協議相關的待處理工作項加入到 todo 隊列中. 以及通過等待隊列將目標進程或線程喚醒來處理這個工作項.

binder_transaction 函數第二部分代碼

01  t = kzalloc(sizeof(*t), GFP_KERNEL);
    ...
02  tcomplete = kzalloc(sizeof(*tcomplete), GFP_KERNEL);
    ...
03  if (!reply && !(tr->flags & TF_ONE_WAY))
        t->from = thread;
    else
        t->from = NULL;
    ...
    ...
04  t->buffer = binder_alloc_buf(target_proc, tr->data_size, tr->offsets_size, extra_buffers_size, !reply && (t->flags & TF_ONE_WAY));
    ...
    if (target_node)
        binder_inc_node(target_node, 1, 0, NULL);
    ...
05  if (copy_from_user(t->buffer->data, (const void __user *)(uintptr_t)
               tr->data.ptr.buffer, tr->data_size)) {
    
    }
06  if (copy_from_user(offp, (const void __user *)(uintptr_t)
               tr->data.ptr.offsets, tr->offsets_size)) {
    }

代碼 01 處分配一個 binder_transaction 結構體 t, 後面會將它封裝爲一個 BINDER_WORKTRANSACTION 類型的工作項加入到目標的 todo 隊列中. 以便目標線程可以接收到一個 BR_TRANSACTION 返回協議.

代碼 02 處分配了一個 binder_work 結構體 tcomplete. 後面會將它封裝成一個 BINDER_WORK_TRANSACTION_COMPLETE 類型的工作項加入到源線程的 todo 隊列中, 以便該線程知道可以馬上返回用戶空間. 並且知道它之前發送給 Binder 驅動程序的 BC_TRANSACTION 命令協議已經被接收了.

代碼 03 處判斷如果正在處理的是一個 BC_TRANSACTION 命令協議. 並不且它所描述的是一個同步的進程間通信請求, 那麼命中 if 就會將 binder_transaction結構體 t的成員變量 from 指向源線程, 以便目標進程 target_proc 或者目標線程 target_thread 處理完該進程間通信請求之後, 能夠找到發出改進程通信請求的線程. 最終將通信結果返回給它.

代碼 04 處是爲 binder_transaction 結構體 t 分配內核緩衝區, 以便可以將進程間通信結果拷貝到它裏面, 最後傳遞給目標進程 target_proc 或者目標線程處理.

當前目標進程爲 SM . 源線程/進程爲 AMS

代碼 05, 06 處是分別將 binder_transaction 結構體 tr 的數據緩衝區以及偏移數組的內容拷貝到在代碼 04 處爲 binder_transaction 結構體 t 分配的內核緩衝區中.

binder_transaction 函數第三部分代碼

    for (; offp < off_end; offp++) {
        struct binder_object_header *hdr;
        ...
        switch (hdr->type) {
        case BINDER_TYPE_BINDER:
        case BINDER_TYPE_WEAK_BINDER: {
01          struct flat_binder_object *fp;
02          struct binder_ref *ref;
03          fp = to_flat_binder_object(hdr);
04          ret = binder_translate_binder(fp, t, thread);
            if (ret < 0) {
                return_error = BR_FAILED_REPLY;
                goto err_translate_failed;
            }
        } break;
        ...
    }

這整個 for 循環就是依次處理進程間通信數據中的 Binder 對象. 如果 Binder 驅動程序是第一次碰到這些 Binder 對象, 那麼 Binder 驅動程序就會根據它們的類型分別創建一個 Binder 實體對象或者 Binder 引用對象.
否則, 就會將之前爲他們創建的 Binder 實體對象或者 Binder 引用對象獲取回來, 增加引用計數, 避免過早銷燬.

代碼 01 處定義一個 flat_binder_object 結構體 fp.

從第 19 步的調用可以知道, 進程間通信數據中包含一個類型爲 BINDER_TYPE_BINDER 的 Binder 對象, 即一個 flat_binder_object 結構體. 用來描述即將要註冊到 SM 中的 Service 組件 AMS.

代碼 02 處定義一個 binder_ref 結構體 ref. 表示 Binder 的引用對象.

代碼 03 處獲取獲取在 19 步寫入的 flat_binder_object 結構體, 保存在 fp 中.

主要分析代碼 04 處 binder_translate_binder 函數. 進去看一下

31. binder_translate_binder

源碼路徑: kernel 3.18下的 /drivers/staging/android/binder.c

static int binder_translate_binder(struct flat_binder_object *fp,
                   struct binder_transaction *t,
                   struct binder_thread *thread)
{
    ...
01  node = binder_get_node(proc, fp->binder);
02  if (!node) {
        ...
    }
    ...
03  ref = binder_get_ref_for_node(target_proc, node);
    ...
    if (fp->hdr.type == BINDER_TYPE_BINDER)
04      fp->hdr.type = BINDER_TYPE_HANDLE;
    else
        fp->hdr.type = BINDER_TYPE_WEAK_HANDLE;
    fp->binder = 0;
    fp->handle = ref->desc;
    fp->cookie = 0;
05  binder_inc_ref(ref, fp->hdr.type == BINDER_TYPE_HANDLE, &thread->todo);
        ...
    return 0;
}

代碼 01 處獲得 Binder 實體對象 node. 接着在代碼 02 處判斷是否爲 NULL, 此處我們獲得的 Binder 實體對象不爲 NULL,

binder_get_node 函數是根據 flat_binder_object 結構體中弱引用計數對象的地址 binder 在目標進程 proc 中找到一個對應的 Binder 實體對象. 在第 19 步中被賦值.

在代碼 03 處調用 binder_get_ref_for_node 函數, 在目標進程 target_proc 中創建一個 Binder 引用對象來引用該 Service 組件 AMS.

在代碼 04 處將 flat_binder_object 結構體 fp 的類型修改爲 BINDER_TYPE_HANDLE, 並設置好它的句柄值. 這是因爲當 Binder 驅動程序將進程間通信數據傳遞給目標進程 target_proc 時, 進程間通信數據中的 Binder 實體對象就變量 Binder 引用對象. 所以需要修改它的類型.

在目標進程 target_proc 創建好一個 Binder 引用對象 ref 後, 接着就要將它傳遞給該目標進程了. 在傳遞過程中, 必須要保證 Binder 引用對象 ref 不會被銷燬, 因此在代碼 05 處調用函數 binder_inc_ref 來增加它的引用計數.

繼續回到 binder_transaction中, 看第三部分代碼

32. binder_transaction 發送進程間通信

第四部分代碼

01 if (reply) {
        ...
02  } else if (!(t->flags & TF_ONE_WAY)) {
        t->need_reply = 1;
        t->from_parent = thread->transaction_stack;
        thread->transaction_stack = t;
    } else {
        ...
    }
03  t->work.type = BINDER_WORK_TRANSACTION;
04  list_add_tail(&t->work.entry, target_list);
05  tcomplete->type = BINDER_WORK_TRANSACTION_COMPLETE;
06  list_add_tail(&tcomplete->entry, &thread->todo);
07  if (target_wait)
08      wake_up_interruptible(target_wait);

代碼 01 處值爲 false 在第 29 步中有說明.
代碼 02 處判斷正常處理的是否是一個同步的進程間通信請求, 即 binder_transaction 接頭體 t的成員變量 flagsTF_ONE_WAY 爲等於 0. 那麼命中 else if, 設置它的成員變量 need_reply 的值爲 1, 表示它需要等待回覆. 接着將事務 t 壓入到源線程 thread 的事務堆棧 transaction_stack 中.

代碼 03 與 04 處將 binder_transaction 結構體 t 封裝成一個類型爲 BINDER_WORK_TRANSACTION 的工作項添加到目標進程 target_proc 或者目標線程 target_threadtodo 隊列中, 並且在 08 行代碼處將目標進程喚醒, 以便處理該工作項.

Android Service Manager 的啓動流程 一文中的第 12 步分析 3 處調用了 wait_event_freezable_exclusive 函數進行睡眠等待直到其所屬的進程有新的未處理工作項. 所以接下來分析SM的時候, 直接從 binder_thread_read 處接着分析 SM 被喚醒後的操作.

如果目標進程 todo 隊列 target_list 指向的是一個 Binder 實體對象的異步事務隊列 async_todo, 那麼目標 wait 等待隊列 target_wait 就會等於 NULL, 這時候就不需要喚醒目標進程.

代碼 05 與 06 行代碼處將 binder_work 結構體 tcomplete 封裝成一個類型爲 BINDER_WORK_TRANSACTION_COMPLETE 的工作項添加到源線程的 todo 隊列中, 以便它從 Binder 驅動程序返回到用戶空間之前, 可以處理該工作項.

程序執行到這裏, 源線程, 目標進程或者目標線程就會併發的去處理各自 todo 隊列中的工作項. 爲了方便描述,
假設源線程會首先它的 todo 隊列中類型爲BINDER_WORK_TRANSACTION_COMPLETE 的工作項.
接着目標進程再處理它隊列中的類型爲 BINDER_WORK_TRANSACTION 的工作項.

注:
此時源線程爲 AMS 進程中請求註冊 Service 組件的線程與目標進程 SM 需要處理的工作項類型如下

  • 源線程: ActivityManagerService 要處理的工作項類型爲: BINDER_WORK_TRANSACTION_COMPLETE
  • 目標進程 SM. 需要處理的工作項類型爲 BINDER_WORK_TRANSACTION.

未完待續......

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章