Android BInder機制

最近研究了下binder 機制 發下你好難理解 然後寫下 我的理解吧 。可能有些地方不是很準確。但是總體還是沒問題的

binder 機制是我們android 中一個跨進程通信的好關於解釋我引用了之前看到的一片文章 覺得總的還行 所以羞恥的 拿過來了 希望原作者看到不要見怪大笑。。。

Binder是一種基於C/S的架構,主要包括四個部分:服務端(Server),客戶端(Client),Binder驅動,ServiceManager。Binder是Android系統中非常重要的一種IPC機制,如果你想研究Frameworks,必須先對Binder機制誘有一定的認識,否則是無法看懂Frameworks源碼的。上述四個部分分別在不同的進程中,他們之間的交互都是通過Binder實現,現在站在宏觀的角度來分析Server,Client,ServiceManager之間的關係,如下圖:



(1)    當一個服務進程啓動後,需要將其中的Service註冊到ServiceManager中,此時底層會有兩個變化:①後臺啓動一個監聽線程,監聽Binder驅動發過來的消息 ② 在Binder驅動中生存一個Service的Binder引用

(2)    Client想和某一個Service交互,需要向ServiceManager申請獲得該Service在Binder中的引用,並存放在自身的mRemote變量中,之後通過mRemote調用 transact 進而調用 ontransact 就是server 重寫的ontransact 然後來實現交互

下面我要寫的是我 研究源碼對這一過程的 研究 大家可以 跟着我看看源碼  。 我們經常 在 程序中 調用系統服務的某些方法 那 其實這一過程就是 binder 機制 所以我記錄了查看源碼的研究過程。我們以   ActivityManager 爲例 依次進入源碼觀看請大家系好安全帶不然會飛起來的

<span style="font-size:18px;">    ActivityManager ma= (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
    ma.getRunningAppProcesses();


    public List<RunningAppProcessInfo> getRunningAppProcesses() {
        try {
            return ActivityManagerNative.getDefault().getRunningAppProcesses();
        } catch (RemoteException e) {
            return null;
        }
    }


    /// ActivityManagerNative.getDefault()-- >
    static public IActivityManager getDefault() {
        return gDefault.get();
    }</span>




    gDefault  是個什麼玩意  他就是 Singleton 一個獲取泛型的單例對象的玩意  gDefault.get(); 獲取了一個 IActivityManager 對象 -->
   
<span style="font-size:18px;">private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
        protected IActivityManager create() {
            IBinder b = ServiceManager.getService("activity");




            if (false) {
                Log.v("ActivityManager", "default service binder = " + b);
            }
            IActivityManager am = asInterface(b);
            if (false) {
                Log.v("ActivityManager", "default service = " + am);
            }
            return am;
        }
    };</span>


    看源碼我們發現 這裏面 又 在獲取IActivityManager 對象時 同時獲取了actvity service 的ibinder.
對象IBinder b = ServiceManager.getService("activity");  --》

<span style="font-size:18px;">    public static IBinder getService(String name) {
        try {
            IBinder service = sCache.get(name);  // 拿到 service的iBinder 對象 所以 service 的ibinder
            // 一定是實現了ibinder接口
                        if (service != null) {
                                return service;
                            } else {
                               return getIServiceManager().getService(name);
                            }
                    } catch (RemoteException e) {
                        Log.e(TAG, "error in getService", e);
                   }
                return null;
    }</span>




    IActivityManager am = asInterface(b);  --->這裏 傳給代理proxy 一個service 的ibinder 對象 然後返回一個am 對象
    IActivityManager 這是 ActivityManger 與service 的 交互協議的指定類 就是 service 提供給外界的調用的抽象接口
   下面的代碼都是在ActivityManagerNative 類中 他實現了 IActivityManager
<span style="font-size:18px;">  static public IActivityManager asInterface(IBinder obj) {
        if (obj == null) {
            return null;
        }
        IActivityManager in =
                (IActivityManager)obj.queryLocalInterface(descriptor);
        if (in != null) {
            return in;
        }


        return new ActivityManagerProxy(obj);//傳給代理proxy 一個service 的ibinder 對象
    }</span>


    // return new ActivityManagerProxy(obj);-->  講service 的ibinder 對象存起來  mRemote
   
<span style="font-size:18px;">public ActivityManagerProxy(IBinder remote)
    {
        mRemote = remote;
    }
</span>



    接下來 可以通過 ActivityManagerProxy 類(寫在了 ActivityManagerNative 文件裏)。 與 service 進行通信 了終於到了  ma.getRunningAppProcesses(); 其實 上面這一對除了我 附上的說明外 還 證明了實際就是 ActivityManagerProxy  裏面的 getRunningAppProcesses,我再給你們捋一捋
ma.getRunningAppProcesses();--》 ActivityManagerNative.getDefault().getRunningAppProcesses();
ActivityManagerNative.getDefault() 是什麼  ? 他是  IActivityManager 那麼在getdefault 的過程中我們其實是創建了
IActivityManager 的實現類 ActivityManagerProxy對象 所以
ma.getRunningAppProcesses(); 就是 ActivityManagerProxy.getRunningAppProcesses
那麼看看源碼
   
<span style="font-size:18px;"> public List<ActivityManager.RunningAppProcessInfo> getRunningAppProcesses()
            throws RemoteException {
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        data.writeInterfaceToken(IActivityManager.descriptor);
        mRemote.transact(GET_RUNNING_APP_PROCESSES_TRANSACTION, data, reply, 0);
        reply.readException();
        ArrayList<ActivityManager.RunningAppProcessInfo> list
                = reply.createTypedArrayList(ActivityManager.RunningAppProcessInfo.CREATOR);
        data.recycle();
        reply.recycle();
        return list;
    }</span>


    // 這裏調用了 ibinde 的transact 方法   transact 方法是什麼看下ibinder 類


    public boolean transact(int code, Parcel data, Parcel reply, int flags)
            throws RemoteException;
    這都是啥 code 標識 方便 service 識別具體需要進行那個操作
    data parcel 類型 parcel 是一個進程間的交換數據的容器 那 data
    是client 發送給 service 的數據
    reply 其實是 service 返回給client 的數據
    那麼問題來了 這也沒有交互 啊。。 那麼我們看看那Ibinder 的子類 binder 發現了 transact 方法
   
<span style="font-size:18px;">public final boolean transact(int code, Parcel data, Parcel reply,
                                  int flags) throws RemoteException {
        if (false) Log.v("Binder", "Transact: " + code + " to " + this);
        if (data != null) {
            data.setDataPosition(0);
        }
        boolean r = onTransact(code, data, reply, flags);
        if (reply != null) {
            reply.setDataPosition(0);
        }
        return r;
    }</span>


    這裏調用了 ontranct 那麼ontransact 是什麼 ,所以我們之前能到的service 的ibinder 對象 其實是應該是binder對象
    實現了binder對象就複寫了ontransact 方法 這樣 client 調用binder對象的transact 的時候就同時調用了 ontransact 這樣就
    實現了客戶端與服務端的跨進程通信   我們來看看
    回到 ActivityManagerNative
    他繼承了binder   有實現了 IActivityManager  但是他是一個抽象類  所以我們猜測 我們獲取的activityservice的binder 對象可能是  繼承了    IActivityManager 的子類的對象 。。下面看他裏面的源碼
   
<span style="font-size:18px;">  @Override
    public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
            throws RemoteException {
        case GET_RUNNING_APP_PROCESSES_TRANSACTION: {
            data.enforceInterface(IActivityManager.descriptor);
            List<ActivityManager.RunningAppProcessInfo> list = getRunningAppProcesses();
            reply.writeNoException();
            reply.writeTypedList(list);
            return true;
        }


    }
    }</span>

   我們看 這裏 根據code 判斷出要 執行service 的  getRunningAppProcesses 方法
這裏 其實我還是沒有弄得十分的明白但是肯定是 ActivityManagerProxy 調用 mRemote.transact()後 binder對象 同時調用了 ontranact 然後
  但是發現getRunningAppProcesses 沒有在這個類中實現  所以我猜測 。我們在獲取activityservice 服務的binder對時 其實獲取的是一個 繼承了activityMangerNative 的子類 的對象,他實現了getRunningAppProcesses 方法。也就是service端的具體實現方法。這樣我們整個流程就通了 。

        1.ActivityManger getrunningAppProgress 時。先是拿到ActivityManagerProxy 對象同時獲取 實現了activityMangerNative  子類的對象 也就是binder對象也是IActivityManger的實現類。 

2.通過 真個binder 對象 transact 方法 我們同時有調用了ontransact 方法 真個方法調用了getRunningAppProcesses 

3.拿到具體數據 寫入到 rely 裏。 返給ActivityManagerProxy    ActivityManagerProxy    方法返給ActivityManger
   
    這樣我們就拿到了服務的數據。跨進程通信完成。

<span style="font-size:18px;"><span style="white-space:pre">	</span><pre name="code" class="html">	public List<ActivityManager.RunningAppProcessInfo> getRunningAppProcesses()
        throws RemoteException {
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        data.writeInterfaceToken(IActivityManager.descriptor);
        mRemote.transact(GET_RUNNING_APP_PROCESSES_TRANSACTION, data, reply, 0);
        reply.readException();
        ArrayList<ActivityManager.RunningAppProcessInfo> list
        = reply.createTypedArrayList(ActivityManager.RunningAppProcessInfo.CREATOR);
        data.recycle();
        reply.recycle();
        return list;
        }</span>




    ArrayList<ActivityManager.RunningAppProcessInfo> list
            = reply.createTypedArrayList(ActivityManager.RunningAppProcessInfo.CREATOR);
    就是通過reply 包拿到了剛纔 service 寫進去的list 集合 到這裏交互完成 了。 所以 我其實在 binder 與service 之前如何進行的 通 信還不是很清晰如果有哪位大神 看到了這篇文章可以 幫我指正下 不足 還有幫我 解下疑惑 、多謝!

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