Java層 Binder筆記相關(guān)(一)

前言:

1.Binder是什么?
2.Binder的原理是什么?
3.Binder如何實(shí)現(xiàn)?

1.Binder是什么?

Binder是Anroid平臺跨進(jìn)程通信的一種重要的實(shí)現(xiàn)方式(
另外三種:

  • Messenger
  • broadcast
  • socket

),是Google基于OpenBinder實(shí)現(xiàn)的進(jìn)程間通信的驅(qū)動(dòng)程序框架, 由于Android是每個(gè)應(yīng)用或者服務(wù)(AMS,IMS)都運(yùn)行在一個(gè)獨(dú)立的進(jìn)程,每個(gè)進(jìn)程之間的數(shù)據(jù)是獨(dú)立的,想要通信就需要一種跨進(jìn)程的技術(shù).

2.Binder的原理是什么?

2.2 Binder對應(yīng)的驅(qū)動(dòng)設(shè)備文件為:/dev/binder.

  • 2.2.1通過Client/Service模式 : C/S之間維護(hù)一個(gè)線程池進(jìn)程通信,通過dev/binder該設(shè)備文件調(diào)用內(nèi)核中的bingder驅(qū)動(dòng)程序

2.2.1.1.Client組件對應(yīng)的是BnInterface,描述本地binder對象,service組件對應(yīng)的是BpInterface。描述本地binder代理對象.
2.2.1.2系統(tǒng)定義了IBinder接口,其中Binder和BinderProxy分別實(shí)現(xiàn)了IBinder接口,前者代表服務(wù)端Bn,而后者代表客戶端Bp.

  • 2.2.2 Binder進(jìn)行進(jìn)程間通信: 首先要調(diào)用open函數(shù)打開設(shè)備文件dev/binder獲得文件描述符,再調(diào)用mmp將該描述符映射到內(nèi)核地址空間,然后分配內(nèi)核緩沖區(qū),該緩沖區(qū)是用來傳遞數(shù)據(jù)的,才能通過這個(gè)和binder驅(qū)動(dòng)程序交互。

2.3 .
Android應(yīng)用層系統(tǒng)想啟動(dòng)另外一個(gè)進(jìn)程里面的service或者activity等組件,最終都是通過一個(gè)遠(yuǎn)程的mRemote Binder對象去跨進(jìn)程通信想AMS發(fā)送一個(gè)請求啟動(dòng),下面通過分析AMS來分析Binder的原理。

其中AMS的繼承方式:

ActivityManagerService ->ActivityManagerService->Binder

    public ActivityManagerNative() {
        attachInterface(this, descriptor);
    }

    /**
     * Convenience method for associating a specific interface with the Binder.
     * After calling, queryLocalInterface() will be implemented for you
     * to return the given owner IInterface when the corresponding
     * descriptor is requested.
     */
    public void attachInterface(IInterface owner, String descriptor) {
        mOwner = owner;
        mDescriptor = descriptor;
    }
      //from IActivityManager
    String descriptor = "android.app.IActivityManager";

當(dāng)啟動(dòng)一個(gè)Activity的流程為:

Activity.java:
public void startActivityForResult(Intent intent, int requestCode,@Nullable Bundle options) {
        if (mParent == null) {
            Instrumentation.ActivityResult ar =
                mInstrumentation.execStartActivity(
                    this, mMainThread.getApplicationThread(), mToken, this,
                    intent, requestCode, options);
        }



Instrumentation.java:
public void execStartActivitiesAsUser() {

int result = ActivityManagerNative.getDefault()
                .startActivities(whoThread, who.getBasePackageName(), intents, resolvedTypes,
                        token, options, userId);

}

ActivityManagerNative.java:
    /**
     * Retrieve the system's default/global activity manager.
     */
    static public IActivityManager getDefault() {
        return gDefault.get();
    }

//
    private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
        protected IActivityManager create() {
                        //拿到對應(yīng)的ServiceManaerService
                         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;
                }
                。
                。
                。
        }
}

其中g(shù)Default最終拿到的是一個(gè)面向底層的客戶端BinderProxy對象(ActivityManagerProxy)

從上面代碼可以看出最終是調(diào)用AMN的startActivity方法。
但是該Binder客戶端對象就是是跟底層那個(gè)目標(biāo)通信呢?

ServiceManager.getService("activity");

    /**
     * Returns a reference to a service with the given name.
     * 
     * @param name the name of the service to get
     * @return a reference to the service, or <code>null</code> if the service doesn't exist
     */
    public static IBinder getService(String name) {
        try {
            IBinder service = sCache.get(name);
            if (service != null) {
                return service;
            } else {
                return getIServiceManager().getService(name);
            }
        } catch (RemoteException e) {
            Log.e(TAG, "error in getService", e);
        }
        return null;
    }

    private static IServiceManager getIServiceManager() {
        if (sServiceManager != null) {
            return sServiceManager;
        }

        // Find the service manager
        sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());
        return sServiceManager;
    }


    /**
     * Return the global "context object" of the system.  This is usually
     * an implementation of IServiceManager, which you can use to find
     * other services.
     */
        public static final native IBinder getContextObject();

從上面可以知道getContextObject返回了一個(gè)指向地城ServiceManager的Native BinderProxy對象,并且在JAVA層封裝 起來給JAVA調(diào)用,如下:

    /**
     * Cast a Binder object into a service manager interface, generating
     * a proxy if needed.
     */
//其中obj就是上面?zhèn)鬟M(jìn)來指向Native BinderProxy對象的地址。
    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);
    }

上面ServiceManagerProxy對象就是封裝了在BinderInternal拿到的Native對象的。

下面通過分析getService方法,分析客戶端發(fā)送請求過程:

    
    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就是BinderInternal. getContextObjectd的navtive對象。
也就是說,將數(shù)據(jù)封裝成Parcel對象,然后通過native binder發(fā)起請求。

上面是客戶端的請求。

ActivityManagerService.java:

@Override
    public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
            throws RemoteException {
        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;
        }

上面是AMS實(shí)現(xiàn)的接受到客戶端請求的實(shí)現(xiàn)方法。
我們知道AMS是繼承Binder,當(dāng)?shù)讓邮盏秸埱笫?,最終會(huì)調(diào)用Binder.java對應(yīng)的方法:


    // 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);
        // theoretically, we should call transact, which will call onTransact,
        // but all that does is rewind it, and we just got these from an IPC,
        // so we'll just call it directly.
        boolean res;
        // Log any exceptions as warnings, don't silently suppress them.
        // If the call was FLAG_ONEWAY then these exceptions disappear into the ether.
        try {
            res = onTransact(code, data, reply, flags);
}

其中onTransact是一個(gè)抽象方法,其中AMS上面實(shí)現(xiàn)了該方法,完成請求。
流程如圖:


image.png

后記:JAVA中搭建了一整套框架,如IBinder接口,Binder類,和BiindeProxy(如ServiceManagerProxy)其中本質(zhì)就是向binder驅(qū)動(dòng)發(fā)送請求或者接受回復(fù)。
即使不使用JAVA的框架,也是可以實(shí)現(xiàn),比如ServiceManager作為Binder的一個(gè)核心程序,就是直接讀取/dev/binder設(shè)備。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容