久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

Android 開發(fā)之漫漫長(zhǎng)途 IX——徹底掌握 Binder

 codingSmart 2021-10-22

作者:wangle12138
鏈接:http://www.cnblogs.com/wangle12138/p/8087709.html
聲明:本文是 wangle12138 原創(chuàng)投稿,,轉(zhuǎn)發(fā)等請(qǐng)聯(lián)系原作者授權(quán)。


前言

我們?cè)谏弦黄斜容^詳盡的介紹了 Android 的消息機(jī)制,,不過有一些內(nèi)容我們?cè)诓焕斫釧ndroid Binder 的話是無法講解清楚的。對(duì)于初學(xué) Android 的朋友而言,,最難卻又最想掌握的恐怕就是 Binder 機(jī)制了,,因?yàn)?Android 系統(tǒng)基本上可以看作是一個(gè)基于 Binder 通信的 C/S 架構(gòu)。 Binder 就像網(wǎng)絡(luò)一樣,,把系統(tǒng)的各個(gè)部分連接在了一起,,因此它是非常重要的,。我們下面會(huì) Android Binder 機(jī)制進(jìn)行從上到下從易到難的分層次講解,從而既能讓初學(xué)者對(duì) Binder 有一定認(rèn)識(shí),,也能讓有一定Android基礎(chǔ)的人獲得收獲,。

注:下文中的源碼均出自android-6.0.0_r5

Binder概述

對(duì)于初學(xué)者來說,深入 Android Binder 機(jī)制是非常不明智的,。Android Binder機(jī)制大都涉及Java層,、Native層、驅(qū)動(dòng)層這三三個(gè)方面,,對(duì)于初學(xué)者來說想啃這三塊硬骨頭很容易磕著牙,。我們這這一節(jié)概述從以下幾個(gè)方面讓你從比較宏觀的角度理解Android Binder。

進(jìn)程

在該系列博客中的第一章我們就說起了Android進(jìn)程相關(guān)問題,,Android故意弱化了進(jìn)程的概念,,而用相對(duì)容易理解的四大組件??墒俏覀?cè)谏晕⑸钊階ndroid的時(shí)候,,那么進(jìn)程是繞不過的。默認(rèn)情況下,,同一個(gè)應(yīng)用程序中的所有組件運(yùn)行在同一個(gè)進(jìn)程中,,而且絕大多數(shù)的應(yīng)用程序也都是這樣的。這個(gè)默認(rèn)進(jìn)程是用這個(gè)應(yīng)用的包名來命名的,。

進(jìn)程間通信

我們?cè)谶\(yùn)行App的時(shí)候經(jīng)常需要使用一些系統(tǒng)服務(wù),,比如剪切板服務(wù),而剪切板服務(wù)是運(yùn)行在SystemServer進(jìn)程中的,。那我們的App是怎么使用剪切板服務(wù)的呢,,我們都知道進(jìn)程是相互獨(dú)立的,靜態(tài)變量等等都無法共用,。這就涉及到進(jìn)程間的通信了,,即IPC。我們都知道Android是基于Linux內(nèi)核的,,那我們簡(jiǎn)單介紹下Linux下的幾種IPC機(jī)制,。

管道(Pipe)

管道是由內(nèi)核管理的一個(gè)緩沖區(qū),相當(dāng)于我們放入內(nèi)存中的一個(gè)紙條,。管道的一端連接一個(gè)進(jìn)程的輸出,。這個(gè)進(jìn)程會(huì)向管道中放入信息。管道的另一端連接一個(gè)進(jìn)程的輸入,,這個(gè)進(jìn)程取出被放入管道的信息,。

  • 管道是半雙工的,數(shù)據(jù)只能向一個(gè)方向流動(dòng);需要雙方通信時(shí),,需要建立起兩個(gè)管道

  • 只能用于父子進(jìn)程或者兄弟進(jìn)程之間(具有親緣關(guān)系的進(jìn)程),。比如fork或exec創(chuàng)建的新進(jìn)程,在使用exec創(chuàng)建新進(jìn)程時(shí),,需要將管道的文件描述符作為參數(shù)傳遞給exec創(chuàng)建的新進(jìn)程,。當(dāng)父進(jìn)程與使用fork創(chuàng)建的子進(jìn)程直接通信時(shí),發(fā)送數(shù)據(jù)的進(jìn)程關(guān)閉讀端,,接受數(shù)據(jù)的進(jìn)程關(guān)閉寫端,。

  • 管道只能在本地計(jì)算機(jī)中使用,而不可用于網(wǎng)絡(luò)間的通信,。

命名管道(FIFO)

命名管道是一種特殊類型的文件,,它在系統(tǒng)中以文件形式存在。這樣克服了管道的弊端,,他可以允許沒有親緣關(guān)系的進(jìn)程間通信,。

共享內(nèi)存(Share Memory)

共享內(nèi)存是在多個(gè)進(jìn)程之間共享內(nèi)存區(qū)域的一種進(jìn)程間的通信方式,由IPC為進(jìn)程創(chuàng)建的一個(gè)特殊地址范圍,,它將出現(xiàn)在該進(jìn)程的地址空間中,。其他進(jìn)程可以將同一段共享內(nèi)存連接到自己的地址空間中。所有進(jìn)程都可以訪問共享內(nèi)存中的地址,,如果一個(gè)進(jìn)程向共享內(nèi)存中寫入了數(shù)據(jù),,所做的改動(dòng)將立刻被其他進(jìn)程看到。

  • 共享內(nèi)存是IPC最快捷的方式,,共享內(nèi)存方式直接將某段內(nèi)存段進(jìn)行映射,多個(gè)進(jìn)程間的共享內(nèi)存是同一塊的物理空間,,僅僅映射到各進(jìn)程的地址不同而已,,因此不需要進(jìn)行復(fù)制,可以直接使用此段空間,。

  • 共享內(nèi)存本身并沒有同步機(jī)制,,需要程序員自己控制。  

內(nèi)存映射(Memory Map)

內(nèi)存映射是由一個(gè)文件到一塊內(nèi)存的映射,,在此之后進(jìn)程操作文件,,就像操作進(jìn)程空間里的內(nèi)存地址一樣了。

套接字(Socket)

套接字機(jī)制不但可以單機(jī)的不同進(jìn)程通信,,而且使得跨網(wǎng)機(jī)器間進(jìn)程可以通信,。
套接字的創(chuàng)建和使用與管道是有區(qū)別的,套接字明確地將客戶端與服務(wù)器區(qū)分開來,,可以實(shí)現(xiàn)多個(gè)客戶端連到同一服務(wù)器,。

Binder

作為Android系統(tǒng)下的一種IPC機(jī)制,其本質(zhì)上與上面羅列出的IPC機(jī)制并無本質(zhì)上的不同,都是作為進(jìn)程間通信的一種手段,。并且在Android系統(tǒng)中也不是只存在Binder這一種進(jìn)程間通信的方式,,在有些地方也使用了Socket。既然Linux已經(jīng)提供了眾多IPC機(jī)制,,那么Android 為何還要使用Binder作為主要的進(jìn)程間通信的方式呢,,那么當(dāng)然有他的優(yōu)點(diǎn)存在。

  • 采用C/S的通信模式,。而在linux通信機(jī)制中,,目前只有socket支持C/S的通信模式,但socket有其劣勢(shì),,具體參看第二條,。

  • 有更好的傳輸性能。對(duì)比于Linux的通信機(jī)制,,socket:是一個(gè)通用接口,,導(dǎo)致其傳輸效率低,開銷大,;管道和消息隊(duì)列:因?yàn)椴捎么鎯?chǔ)轉(zhuǎn)發(fā)方式,,所以至少需要拷貝2次數(shù)據(jù),效率低,;共享內(nèi)存:雖然在傳輸時(shí)沒有拷貝數(shù)據(jù),,但其控制機(jī)制復(fù)雜(比如跨進(jìn)程通信時(shí),需獲取對(duì)方進(jìn)程的pid,,得多種機(jī)制協(xié)同操作),。

  • 安全性更高。Linux的IPC機(jī)制在本身的實(shí)現(xiàn)中,,并沒有安全措施,,得依賴上層協(xié)議來進(jìn)行安全控制。而Binder機(jī)制的UID/PID是由Binder機(jī)制本身在內(nèi)核空間添加身份標(biāo)識(shí),,安全性高,;并且Binder可以建立私有通道,這是linux的通信機(jī)制所無法實(shí)現(xiàn)的(Linux訪問的接入點(diǎn)是開放的),。

  • 對(duì)用戶來說,,通過binder屏蔽了client的調(diào)用server的隔閡,client端函數(shù)的名字,、參數(shù)和返回值和server的方法一模一樣,,對(duì)用戶來說猶如就在本地(也可以做得不一樣),這樣的體驗(yàn)或許其他ipc方式也可以實(shí)現(xiàn),,但binder出生那天就是為此而生,。

Java層Binder

Java層Binder的功能,依賴于Native層Binder來實(shí)現(xiàn),可以認(rèn)為Java層Binder架構(gòu)是Native層Binder架構(gòu)的一個(gè)鏡像,。但是這并不影響我們分析Android Java層Binder的功能,。我們用一個(gè)例子來說明這個(gè)過程。

我們?cè)诘谝黄芯椭v解了SystemServer這個(gè)進(jìn)程,,這個(gè)進(jìn)程和zygote進(jìn)程一起撐起了Android 世界,,他們之中有一個(gè)崩潰,Android世界就會(huì)砰然倒塌,。Android許多的重要的系統(tǒng)服務(wù)如AMS,、PMS等都運(yùn)行在SystemServer進(jìn)程中。但是還有一個(gè)比較重要的進(jìn)程ServiceManager進(jìn)程(簡(jiǎn)稱SM)跟zygote是兄弟進(jìn)程,。這個(gè)進(jìn)程的作用是用來統(tǒng)一管理服務(wù),,如AMS。它們之間的關(guān)系如下,。

我們的AMS需要向SM進(jìn)程中注冊(cè)信息,,其他進(jìn)程如果想使用AMS,那么先和ServiceManager進(jìn)程進(jìn)行通信查詢,,接著再和AMS所在SystemServer進(jìn)程通信,。這部分關(guān)系圖如下

我們這里僅上圖分析①②③中的一條道路,我們來分析③,,即我們的應(yīng)用進(jìn)程(Client)如何與服務(wù)進(jìn)程(Server)交互,。

Java層的Binder,我們來看涉及的類的結(jié)構(gòu)圖

[IBinder.java]

public interface IBinder {
   //交互函數(shù)
   public boolean transact(int code, Parcel data, Parcel reply, int flags)
       throws RemoteException
;
}

我們接著來看Binder和BinderProxy 他們都聲明在Binder.java中

[Binder.java]

/**
   Binder類
   */

public class Binder implements IBinder {
   public final boolean transact(int code, Parcel data, Parcel reply,
               int flags)
throws RemoteException
{
       ......
       //這里調(diào)用了onTransact函數(shù)進(jìn)行處理,一般情況下這個(gè)函數(shù)都會(huì)被它的子類重寫
       boolean r = onTransact(code, data, reply, flags);
       if (reply != null) {
           reply.setDataPosition(0);
       }
       return r;
   }
}
/**
   BinderProxy類
   */

final class BinderProxy implements IBinder {
   public boolean transact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
       //直接以JNI的方式調(diào)用Native層的transact函數(shù)
       return transactNative(code, data, reply, flags);
   }
   public native boolean transactNative(int code, Parcel data, Parcel reply,
           int flags)
throws RemoteException
;
}

通用的IPC流程如下

現(xiàn)在假設(shè)下面一個(gè)場(chǎng)景,,我們的應(yīng)用進(jìn)程即我們的App想要使用ActivityManagerService的startActivity函數(shù)(這種場(chǎng)景肯定有的,,當(dāng)我們拿到手機(jī)的時(shí)候,手機(jī)已經(jīng)預(yù)裝了許多App,其中Launcher App(桌面管理App)是在Android系統(tǒng)啟動(dòng)完成之后啟動(dòng)的第一個(gè)App,,我們安裝好一個(gè)應(yīng)用后,,點(diǎn)擊應(yīng)用圖標(biāo)即發(fā)出Intent,想要啟動(dòng)另一個(gè)App中的Activity,,我們?cè)贏ndroidManifest.xml中注冊(cè)了Main Activity)。Launcher App所在的進(jìn)程要與AMS所在的進(jìn)程SystemServer進(jìn)程交互,。
我們來看這個(gè)例子,。按照上面的通用流程我們猜測(cè)Launcher進(jìn)程與SystemServer進(jìn)程交互過程也如上圖所示,那么按照這個(gè)思路我們來看,。分為3點(diǎn):

是否存在業(yè)務(wù)函數(shù)的統(tǒng)一聲明,?

這一部分是我們的上圖中的test函數(shù)所聲明的類或者接口,我們的Client端代理和Server端服務(wù)都要實(shí)現(xiàn)這個(gè)函數(shù),。果然有
[IActivityManager.java]

public interface IActivityManager extends IInterface {
   public int startActivity(IApplicationThread caller, String callingPackage, Intent intent,
           String resolvedType, IBinder resultTo, String resultWho, int requestCode, int flags,
           ProfilerInfo profilerInfo, Bundle options)
throws RemoteException
;
   ......
}

這里聲明了我們將要調(diào)用的業(yè)務(wù)函數(shù)startActivity,,那么接著第二點(diǎn)

是否存在Server端服務(wù)代理?

ActivityManagerProxy是在ActivityManagerNative.java中聲明的內(nèi)部類

class ActivityManagerProxy implements IActivityManager
{
   public ActivityManagerProxy(IBinder remote)
   
{
       mRemote = remote;
   }
   public IBinder asBinder()
   
{
       return mRemote;
   }
   public int startActivity(IApplicationThread caller, String callingPackage, Intent intent,
           String resolvedType, IBinder resultTo, String resultWho, int requestCode,
           int startFlags, ProfilerInfo profilerInfo, Bundle options)
throws RemoteException
{
       Parcel data = Parcel.obtain();
       Parcel reply = Parcel.obtain();
       data.writeInterfaceToken(IActivityManager.descriptor);
       data.writeStrongBinder(caller != null ? caller.asBinder() : null);
       data.writeString(callingPackage);
       intent.writeToParcel(data, 0);
       data.writeString(resolvedType);
       data.writeStrongBinder(resultTo);
       data.writeString(resultWho);
       data.writeInt(requestCode);
       data.writeInt(startFlags);
       if (profilerInfo != null) {
           data.writeInt(1);
           profilerInfo.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
       } else {
           data.writeInt(0);
       }
       if (options != null) {
           data.writeInt(1);
           options.writeToParcel(data, 0);
       } else {
           data.writeInt(0);
       }
       //看這里果然是通過mRemote.transact函數(shù),,這里的mRemote是BinderProxy類,,關(guān)于這一點(diǎn)我們?cè)贜ative層分析的時(shí)候再給出
       mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0);
       reply.readException();
       int result = reply.readInt();
       reply.recycle();
       data.recycle();
       return result;
   }
   ......
}

是否存在Server端服務(wù)

ActivityManagerNative是繼承于Binder的抽象類,,并重寫了onTransact方法

public abstract class ActivityManagerNative extends Binder implements IActivityManager{
    @Override
   public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
           throws RemoteException
{
       //根據(jù)code處理相應(yīng)的業(yè)務(wù)邏輯,,我們這里是START_ACTIVITY_TRANSACTION
       switch (code) {
       case START_ACTIVITY_TRANSACTION:
       {
           data.enforceInterface(IActivityManager.descriptor);
           IBinder b = data.readStrongBinder();
           IApplicationThread app = ApplicationThreadNative.asInterface(b);
           String callingPackage = data.readString();
           Intent intent = Intent.CREATOR.createFromParcel(data);
           String resolvedType = data.readString();
           IBinder resultTo = data.readStrongBinder();
           String resultWho = data.readString();
           int requestCode = data.readInt();
           int startFlags = data.readInt();
           ProfilerInfo profilerInfo = data.readInt() != 0
                   ? ProfilerInfo.CREATOR.createFromParcel(data) : null;
           Bundle options = data.readInt() != 0
                   ? Bundle.CREATOR.createFromParcel(data) : null;
           int result = startActivity(app, callingPackage, intent, resolvedType,
                   resultTo, resultWho, requestCode, startFlags, profilerInfo, options);
           reply.writeNoException();
           reply.writeInt(result);
           return true;
       }
   }
}

既然ActivityManagerNative是個(gè)抽象類,,那么誰(shuí)真正實(shí)現(xiàn)了呢


[ActivityManagerService.java]

public final class ActivityManagerService extends ActivityManagerNative
       implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback
{
   //重寫了onTransact函數(shù)
   @Override
   public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
           throws RemoteException
{
       ......
       try {
           //調(diào)用父類即ActivityManagerNative的onTransact函數(shù)
           return super.onTransact(code, data, reply, flags);
       } catch (RuntimeException e) {
           throw e;
       }
   }
}

Launcher進(jìn)程與SystemServer進(jìn)程交互過程如下

本節(jié)小結(jié)

關(guān)于Java層的Binder機(jī)制,,我們只需要理解以BinderProxy代表的代理端和Binder代表的服務(wù)端的概念即可,,例如我們本例中的AMS,,AMS是運(yùn)行在SystemServer進(jìn)程中的服務(wù)端,,它間接繼承于Binder,,在得到相關(guān)請(qǐng)求后,會(huì)調(diào)用AMS重寫的onTransact函數(shù)進(jìn)行邏輯處理,。那么這個(gè)請(qǐng)求就是是AMS的客戶端ActivityManagerProxy通過Binder的方式發(fā)給它的,,ActivityManagerProxy發(fā)送這個(gè)請(qǐng)求的方式,是通過調(diào)用其內(nèi)部的成員變量mRemote,這個(gè)mRemote其實(shí)是BinderProxy的對(duì)象,,然后BinderProxy通過JNI調(diào)用Native層對(duì)應(yīng)函數(shù),,最終通過Binder驅(qū)動(dòng)達(dá)到與SystemServer交互的目的。

那么還遺留下以下幾個(gè)問題:

1. 服務(wù)器端的代理怎么獲得的

2. 位于代理類中的mRemote這個(gè)變量

要想理解好上面的個(gè)問題,,我們必須向Native層進(jìn)軍,。

Native層Binder

我們依然以AMS分析,我們先來想一下我們?cè)谟脩暨M(jìn)程中即我們的App中想使用AMS或者其他剪切板之類的系統(tǒng)服務(wù)函數(shù)了怎么辦,?,?按照上面的分析我們要獲得AMS的代理ActivityManagerProxy

[ActivityManagerNative.java]

//這里我們的App進(jìn)程從SM進(jìn)程得到AMS服務(wù)對(duì)應(yīng)的客戶端代理BinderProxy
IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
//以BinderProxy為參數(shù)得到我們ActivityManagerProxy,并把BinderProxy對(duì)象存儲(chǔ)在mRemote變量中
IActivityManager am = asInterface(b);
return am;

到這里我們就有以下問題,,本小節(jié)分析1,2

1. 既然可以通過SM獲得對(duì)應(yīng)的客戶端代理,,那么AMS必定已經(jīng)注冊(cè)在SM中了,那么怎么注冊(cè)的呢,?

2. AMS代理是如何獲得的,?

3. AMS代理是如何與Binder通信的?

我們來一一分析,,在分析問題之前我們先做一個(gè)假設(shè),,這個(gè)假設(shè)至關(guān)重要,那就是不管我們的SystemServer進(jìn)程與SM進(jìn)程交互也好還是我們的App進(jìn)程與SM進(jìn)程也好,,SM的代理已經(jīng)事先創(chuàng)建完畢,,即不管我們?cè)赟ystemServer端還是App端,在與SM進(jìn)程交互的時(shí)候不用考慮代理怎么獲得的,。為什么會(huì)有如此假設(shè),,因?yàn)槲易约荷钍芷浜Γ捎谏鲜鋈齻€(gè)過程均是通過Binder,,很容易陷入思維混亂,。

AMS是如何注冊(cè)的,?

我們SystemServer進(jìn)程中的AMS通過SM的代理與SM進(jìn)程交互(讀者也可以把這個(gè)過程想象為你所能理解的進(jìn)程間通信方式,例如管道,、Socket等),,并把自己注冊(cè)在SM中
SystemServer創(chuàng)建出ActivityManagerService后,最終將調(diào)用其setSystemProcess方法:

[SystemServer.java]

public void setSystemProcess() {
   try {
       //注冊(cè)服務(wù),,第二個(gè)參數(shù)為this,,這里假設(shè)SystemServer通過“socket”與SM交互
       ServiceManager.addService(Context.ACTIVITY_SERVICE, this, true);
       ..........
   } catch (PackageManager.NameNotFoundException e) {
       ........
   }
}

上面的請(qǐng)求最終是通過SM服務(wù)代理發(fā)送的()

[ServiceManagerNative.java]

public void addService(String name, IBinder service, boolean allowIsolated)
       throws RemoteException
{
   //將數(shù)據(jù)打包寫入Parcel對(duì)象
   Parcel data = Parcel.obtain();
   Parcel reply = Parcel.obtain();
   data.writeInterfaceToken(IServiceManager.descriptor);
   data.writeString(name);
   //注意這個(gè)地方,后文分析,,此時(shí)的service為ActivityManagerService
   data.writeStrongBinder(service);
   data.writeInt(allowIsolated ? 1 : 0);
   //調(diào)用BindProxy的transact函數(shù)
   mRemote.transact(ADD_SERVICE_TRANSACTION, data, reply, 0);
   reply.recycle();
   data.recycle();
}

上面的過程已經(jīng)分析過了,, 這里我們主要看一下哪個(gè)對(duì)應(yīng)的native層的transact函數(shù)

[android_ util_Binder.cpp]

static jboolean android_os_BinderProxy_transact(JNIEnv* env, jobject obj,
       jint code, jobject dataObj, jobject replyObj, jint flags)

{
   ........
   //將java對(duì)象轉(zhuǎn)化為native對(duì)象
   Parcel* data = parcelForJavaObject(env, dataObj);
   .........
   Parcel* reply = parcelForJavaObject(env, replyObj);
   ........
   //得到native層的BpBinder
   IBinder* target = (IBinder*)
       env->GetLongField(obj, gBinderProxyOffsets.mObject);
   ........
   //通過BpBinder利用IPCThreadState,將請(qǐng)求通過Binder驅(qū)動(dòng)發(fā)送給SM進(jìn)程
   status_t err = target->transact(code, *data, reply, flags);
   ........
}

SM進(jìn)程收到信息后便處理這個(gè)消息(這個(gè)說法并不準(zhǔn)確,,準(zhǔn)確的說法是,,SM進(jìn)程中主線程一直在與binder設(shè)備交互,想必讀者也猜到了for(;;)),有消息時(shí)便通過預(yù)先定義好的函數(shù)進(jìn)行處理

[service_manager.c]

switch(txn->code) {
   case SVC_MGR_ADD_SERVICE:
       s = bio_get_string16(msg, &len);
       if (s == NULL) {
           return -1;
       }
       handle = bio_get_ref(msg);
       allow_isolated = bio_get_uint32(msg) ? 1 : 0;
       //do_add_service
       if (do_add_service(bs, s, len, handle, txn->sender_euid,
           allow_isolated, txn->sender_pid))
           return -1;
   break;
}
int do_add_service(struct binder_state *bs,
                  const uint16_t *s, size_t len,
                  uint32_t handle, uid_t uid, int allow_isolated,
                  pid_t spid)

{
   //結(jié)構(gòu)體si,用來存儲(chǔ)服務(wù)信息
   struct svcinfo *si;
   //判斷服務(wù)有沒有權(quán)限注冊(cè),,并不是所有的服務(wù)都能注冊(cè)
   if (!svc_can_register(s, len, spid)) {
       return -1;
   }
   //查詢服務(wù)有沒有注冊(cè)過
   si = find_svc(s, len);
   if (si) {//已經(jīng)注冊(cè)過
       if (si->handle) {
           ALOGE("add_service('%s',%x) uid=%d - ALREADY REGISTERED, OVERRIDE\n",
                str8(s, len), handle, uid);
           svcinfo_death(bs, si);
       }
       si->handle = handle;
   } else {//還沒有注冊(cè)過,,我們進(jìn)入這個(gè)分支
       si = malloc(sizeof(*si) + (len + 1) * sizeof(uint16_t));
       if (!si) {
           ALOGE("add_service('%s',%x) uid=%d - OUT OF MEMORY\n",
                str8(s, len), handle, uid);
           return -1;
       }
       //保存一些handle等信息
       si->handle = handle;
       si->len = len;
       memcpy(si->name, s, (len + 1) * sizeof(uint16_t));
       si->name[len] = '\0';
       si->death.func = (void*) svcinfo_death;
       si->death.ptr = si;
       si->allow_isolated = allow_isolated;
       si->next = svclist;
       svclist = si;
   }
   binder_acquire(bs, handle);
   binder_link_to_death(bs, handle, &si->death);
   return 0;
}

看到這里SM貌似只保留了一些AMS的信息而已,實(shí)際上并不只是如此,,我們來看一下上面的保留問題

[Parcel.java]

data.writeStrongBinder(service);
public final void writeStrongBinder(IBinder val) {
   //調(diào)用了native函數(shù)
   nativeWriteStrongBinder(mNativePtr, val);
}

跟進(jìn)[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) {
       //native層的parcel
       const status_t err = parcel->writeStrongBinder(ibinderForJavaObject(env, object));
       if (err != NO_ERROR) {
           signalExceptionForError(env, clazz, err);
       }
   }
}
sp<IBinder> ibinderForJavaObject(JNIEnv* env, jobject obj)
{
   if (obj == NULL) return NULL;
   //obj為Binder類
   if (env->IsInstanceOf(obj, gBinderOffsets.mClass)) {
       JavaBBinderHolder* jbh = (JavaBBinderHolder*)
           env->GetLongField(obj, gBinderOffsets.mObject);
       //調(diào)用了JavaBBinderHolder的get方法
       return jbh != NULL ? jbh->get(env, obj) : NULL;
   }
   //obj為BinderProxy類
   if (env->IsInstanceOf(obj, gBinderProxyOffsets.mClass)) {
       return (IBinder*)
           env->GetLongField(obj, gBinderProxyOffsets.mObject);
   }
   ALOGW("ibinderForJavaObject: %p is not a Binder object", obj);
   return NULL;
}

跟進(jìn)[Pacel.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) {//binder不為空
       IBinder *local = binder->localBinder();//是不是本地binder,,本地的意思是同一個(gè)進(jìn)程中的調(diào)用
       if (!local) {
           BpBinder *proxy = binder->remoteBinder();
           if (proxy == NULL) {
               ALOGE("null proxy");
           }
           const int32_t handle = proxy ? proxy->handle() : 0;
           obj.type = BINDER_TYPE_HANDLE;
           obj.binder = 0; /* Don't pass uninitialized stack data to a remote process */
           obj.handle = handle;
           obj.cookie = 0;
       } else {//我們這里明顯不是
           obj.type = BINDER_TYPE_BINDER;
           obj.binder = reinterpret_cast<uintptr_t>(local->getWeakRefs());
           obj.cookie = reinterpret_cast<uintptr_t>(local);
       }
   } else {//錯(cuò)誤信息
       obj.type = BINDER_TYPE_BINDER;
       obj.binder = 0;
       obj.cookie = 0;
   }
   return finish_flatten_binder(binder, obj, out);
}

通過上面的代碼,我們可以看到當(dāng)一個(gè)服務(wù)進(jìn)行注冊(cè)時(shí),,會(huì)將Java層的Binder對(duì)象和Native層的BBinder關(guān)聯(lián)起來,,于是服務(wù)端綁定到了Native層的Binder架構(gòu)。
此外,,addService中打包傳入的其實(shí)不是ActivityManagerService本身,,而是對(duì)應(yīng)的JavaBBinder對(duì)象。
這里對(duì)應(yīng)的結(jié)構(gòu)如下圖所示:

AMS代理是如何獲得的,?

我們上面SystemServer中的AMS已經(jīng)在SM中準(zhǔn)備好了,,那我們ServiceManager.getService(Context.ACTIVITY_SERVICE);
一樣的過程,我們知道最終會(huì)在service_manager.c中處理

switch(txn->code) {
   //這里有個(gè)case穿透,,,,好吧
   case SVC_MGR_GET_SERVICE:
   case SVC_MGR_CHECK_SERVICE:
       s = bio_get_string16(msg, &len);
       if (s == NULL) {
           return -1;
       }
       //查詢AMS保存在SM中對(duì)應(yīng)的的那個(gè)handle
       handle = do_find_service(bs, s, len, txn->sender_euid, txn->sender_pid);
       if (!handle)
           break;
       bio_put_ref(reply, handle);
       return 0;
}
把寫入數(shù)據(jù)后的reply返回
bio_put_uint32(reply, 0);

回到我們的調(diào)用處
[ServiceManagerNative.java]

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);
   //看這里readStrongBinder,是不是感覺跟我們上面的writeStrongBinder感覺是一對(duì)的
   IBinder binder = reply.readStrongBinder();
   reply.recycle();
   data.recycle();
   return binder;
}

Parcel的readStrongBinder還是個(gè)JNI調(diào)用

[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) {
       //這里我們看到了什么,,,,看函數(shù)名字應(yīng)該是為Binder生成一個(gè)java對(duì)象吧
       return javaObjectForIBinder(env, parcel->readStrongBinder());
   }
   return NULL;
}

我們先看Pacel的readStrongBinder方法
[Parcel.cpp]

sp<IBinder> Parcel::readStrongBinder() const
{
   sp<IBinder> val;
   //看到這里,還記得writeStrongBinder中的flatten_binder,,這里是unflatten_binder
   unflatten_binder(ProcessState::self(), *this, &val);
   return 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:
               //到這里我們也清楚了進(jìn)入這個(gè)分支
               //調(diào)用ProcessState的getStrongProxyForHandle函數(shù)
               *out = proc->getStrongProxyForHandle(flat->handle);
               return finish_unflatten_binder(
                   static_cast<BpBinder*>(out->get()), *flat, in);
       }
   }
   return BAD_TYPE;
}

繼續(xù)跟進(jìn)[ProcessState.cpp]

sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)
{
   sp<IBinder> result;
   AutoMutex _l(mLock);
   handle_entry* e = lookupHandleLocked(handle);
   if (e != NULL) {
       IBinder* b = e->binder;
       if (b == NULL || !e->refs->attemptIncWeak(this)) {
           if (handle == 0) {//這里handle為0的情況是為SM準(zhǔn)備的,
               Parcel data;
               status_t status = IPCThreadState::self()->transact(
                       0, IBinder::PING_TRANSACTION, data, NULL, 0);
               if (status == DEAD_OBJECT)
                  return NULL;
           }
           //我們的不為0,,在這里創(chuàng)建了BpBinder
           b = new BpBinder(handle);
           e->binder = b;
           if (b) e->refs = b->getWeakRefs();
           result = b;
       } else {
           result.force_set(b);
           e->refs->decWeak(this);
       }
   }
   return result;
}

好了剩下最后一個(gè)了javaObjectForIBinder

[android_ util_Binder.cpp]

jobject javaObjectForIBinder(JNIEnv* env, const sp<IBinder>& val) {
   if (val == NULL) return NULL;
   //如果val是Binder對(duì)象,,進(jìn)入下面分支,,此時(shí)val是BpBinder
   if (val->checkSubclass(&gBinderOffsets)) {
       // One of our own!
       jobject object = static_cast<JavaBBinder*>(val.get())->object();
       LOGDEATH("objectForBinder %p: it's our own %p!\n", val.get(), object);
       return object;
   }
   .........
   //調(diào)用BpBinder的findObject函數(shù)
   //在Native層的BpBinder中有一個(gè)ObjectManager,它用來管理在Native BpBinder上創(chuàng)建的Java BinderProxy對(duì)象
   //findObject用于判斷gBinderProxyOffsets中,,是否存儲(chǔ)了已經(jīng)被ObjectManager管理的Java BinderProxy對(duì)象
   jobject object = (jobject)val->findObject(&gBinderProxyOffsets);
   if (object != NULL) {
       jobject res = jniGetReferent(env, object);
       ............
       //如果該Java BinderProxy已經(jīng)被管理,,則刪除這個(gè)舊的BinderProxy
       android_atomic_dec(&gNumProxyRefs);
       val->detachObject(&gBinderProxyOffsets);
       env->DeleteGlobalRef(object);
   }
   //創(chuàng)建一個(gè)新的BinderProxy對(duì)象
   object = env->NewObject(gBinderProxyOffsets.mClass, gBinderProxyOffsets.mConstructor);
   if (object != NULL) {
       // The proxy holds a reference to the native object.
       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));
       //新創(chuàng)建的BinderProxy對(duì)象注冊(cè)到BpBinder的ObjectManager中,同時(shí)注冊(cè)一個(gè)回收函數(shù)proxy_cleanup
       //當(dāng)BinderProxy對(duì)象detach時(shí),,proxy_cleanup函數(shù)將被調(diào)用,,以釋放一些資源
       val->attachObject(&gBinderProxyOffsets, refObject,
               jnienv_to_javavm(env), proxy_cleanup);
       // Also remember the death recipients registered on this proxy
       sp<DeathRecipientList> drl = new DeathRecipientList;
       drl->incStrong((void*)javaObjectForIBinder);
       //將死亡通知list和BinderProxy聯(lián)系起來
       env->SetLongField(object, gBinderProxyOffsets.mOrgue, reinterpret_cast<jlong>(drl.get()));
       // Note that a new object reference has been created.
       android_atomic_inc(&gNumProxyRefs);
       //垃圾回收相關(guān);利用gNumRefsCreated記錄創(chuàng)建出的BinderProxy數(shù)量
       //當(dāng)創(chuàng)建出的BinderProxy數(shù)量大于200時(shí),,該函數(shù)將利用BinderInternal的ForceGc函數(shù)進(jìn)行一個(gè)垃圾回收
       incRefsCreated(env);
       return object;
   }
}

到這里總算都打通了總體流程如下

驅(qū)動(dòng)層Binder

AMS代理是如何與Binder通信的,?

通過Java層的服務(wù)端代理最終調(diào)用到BpBinder.transact函數(shù)

[BpBinder.cpp]

status_t BpBinder:transact(uint32_t code,const Parcel&data,Parcel*reply,uint32_t flags){
   if(mAlive){
       //BpBinder把transact工作交給了IPCThreadState,。
       status_t status=IPCThreadState:self()->transact(
       mHandle,code,data,reply,flags),;//mHandle也是參數(shù)
       if(status==DEAD_OBJECT)mAlive=0
       return status,;
   }
   return DEAD_OBJECT,;
}

[IPCThreadState.cpp]

IPCThreadState::IPCThreadState()
   : mProcess(ProcessState::self()),
     mMyThreadId(gettid()),
     mStrictModePolicy(0),
     mLastTransactionBinderFlags(0)
{
   pthread_setspecific(gTLS, this);
   clearCaller();
   //mIn和mOut是兩個(gè)Parcel。 把它看成是發(fā)送和接收命令的緩沖區(qū)即可,。
   mIn.setDataCapacity(256);
   mOut.setDataCapacity(256);
}
status_t IPCThreadState::transact(int32_t handle,
                                 uint32_t code, const Parcel& data,
                                 Parcel* reply, uint32_t flags)
{
   ......
   /*
   注意這里的第一個(gè)參數(shù)BC_TRANSACTION,,它是應(yīng)用程序向binder設(shè)備發(fā)送消息的消
   息碼,而binder設(shè)備向應(yīng)用程序回復(fù)消息的消息碼以BR_開頭,。 消息碼的定義在
   binder_module.h中,,請(qǐng)求消息碼和回應(yīng)消息碼的對(duì)應(yīng)關(guān)系,需要查看Binder驅(qū)動(dòng)的實(shí)
   現(xiàn)才能將其理清楚,,我們這里暫時(shí)用不上,。
   */

   err = writeTransactionData(BC_TRANSACTION, flags, handle, code, data, NULL);
   ......
   err = waitForResponse(NULL, NULL);
   ......
   return err;
}
status_t IPCThreadState::writeTransactionData(int32_t cmd, uint32_t binderFlags,
int32_t handle, uint32_t code, const Parcel& data, status_t* statusBuffer)
{
  //binder_transaction_data是和binder設(shè)備通信的數(shù)據(jù)結(jié)構(gòu)。
   binder_transaction_data tr,;
   //果然,,handle的值傳遞給了target,用來標(biāo)識(shí)目的端,,其中0是ServiceManager的標(biāo)志,。
   tr.target.handle=handle;
   //code是消息碼,,是用來switch/case的,!
   tr.code = code;
   tr.flags = binderFlags;
   tr.cookie = 0;
   tr.sender_pid = 0;
   tr.sender_euid = 0;
   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) {
       tr.flags |= TF_STATUS_CODE;
       *statusBuffer = err;
       tr.data_size = sizeof(status_t);
       tr.data.ptr.buffer = reinterpret_cast<uintptr_t>(statusBuffer);
       tr.offsets_size = 0;
       tr.data.ptr.offsets = 0;
   } else {
       return (mLastError = err);
   }
   //把命令寫到mOut中,而不是直接發(fā)出去,,可見這個(gè)函數(shù)有點(diǎn)名不副實(shí)。
   mOut.writeInt32(cmd);
   mOut.write(&tr, sizeof(tr));
   return NO_ERROR;
}
status_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult)
{
   uint32_t cmd;
   int32_t err;
   while (1) {
       if ((err=talkWithDriver()) <NO_ERROR) break;
       err = mIn.errorCheck();
       if (err < NO_ERROR) break;
       if (mIn.dataAvail() == 0) continue;
       //看見沒,?這里開始操作mIn了,,看來talkWithDriver中
       //把mOut發(fā)出去,,然后從driver中讀到數(shù)據(jù)放到mIn中了。
       cmd = mIn.readInt32();
  }
}
status_t IPCThreadState::talkWithDriver(bool doReceive)
{
   binder_write_read bwr;
      //中間東西太復(fù)雜了,,不就是把mOut數(shù)據(jù)和mIn接收數(shù)據(jù)的處理后賦值給bwr嗎,?
       status_t err;
       do {
           //用ioctl來讀寫
           if (ioctl(mProcess->mDriverFD,BINDER_WRITE_READ, &bwr) >= 0)
               err = NO_ERROR;
           else
               err = -errno;
       } while (err == -EINTR);
           //到這里,回復(fù)數(shù)據(jù)就在bwr中了,,bmr接收回復(fù)數(shù)據(jù)的buffer就是mIn提供的
           if (bwr.read_consumed > 0) {
               mIn.setDataSize(bwr.read_consumed);
               mIn.setDataPosition(0);
           }
   return NO_ERROR;
}

本篇總結(jié)

我們本篇詳細(xì)分析了Binder機(jī)制,,從概述->Java層Binder->Native層Binder->Binder驅(qū)動(dòng),位于各層次的讀者都能獲得收獲,。


下篇預(yù)告

不好意思各位,,下周有個(gè)比較重要的面試,所以暫時(shí)不會(huì)更新該系列的博客,,但是也會(huì)更新其他博客,。記錄準(zhǔn)備面試的過程中需要用到的比較容易錯(cuò)誤的知識(shí)。


此致,,敬禮

    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多