突然悟出在源碼中分析Binder的玩法

首先我們可以去這樣理解:(綜合ActivityManagerService和ApplicationThread分析)
凡是在源碼中和binder有關的最底層的抽象類都會去extends Binder并且實現Ixxxxxxx接口
就比如我們可以看到ActivityManagerService繼承的ActivityManagerNative就是最底層的抽象類。
我們可以看到

 public abstract class ActivityManagerNative extends Binder implements IActivityManager

再比如ApplicationThread(注意這個類是在ActivityThread中定義的一個內部類)繼承的ApplicationThreadNative也是最底層的抽象類,我們可以看到

public abstract class ApplicationThreadNative extends Binder implements IApplicationThread

OK,那么問題來了,還有的Service呢?跟AMS齊名的PMS呢,怎么不拿出來分析一下呢,來我們去看看PMS是怎么玩的?

public class PackageManagerService extends IPackageManager.Stub 

也就是說IPackageManager.Stub應該是PMS的最底層的抽象類,于是乎我們就去苦苦追尋這個IPackageManager.Stub東西了,結果你會發現你完!!全!!找!!不!!到!!
不要慌,讓老夫領你去看個究竟。

源碼的編譯

實際上,如果源碼里面翻多了,你會發現不單單是這個東西,很多東西都是沒有的,飄紅的。實際上android sdk manager幫我們下載的相應的api版本下的source文件都不是android的系統源碼,只能滿足你初步的查看,如果你真的想要去把源碼看個究竟,單單通過sdk目錄下的source是不夠的,你需要做的是編譯源碼http://www.lxweimin.com/writer#/notebooks/6954184/notes/8031957

改變源碼的閱讀方式

我們現在再次去看看能不能找得到IPackageManager,結果一搜就搜到了

public interface IPackageManager extends android.os.IInterface {
    /**
     * Local-side IPC implementation stub class.
     */
    public static abstract class Stub extends android.os.Binder implements android.content.pm.IPackageManager {

        .....
    }
    ...
}

我們看到這個Stub內部類也是extends 了Binder并且實現了IPackageManager
包括之前同樣看不到的WindowManagerService繼承的IWindowManager(就是我們常說的WMS)也是一模一樣的。

為什么一開始找不到

為什么AMS可以找得到,是因為AMS的Binder相關都是直接定義在源碼中的,區別于其他服務的定義,我們可以很清楚的看到AMS繼承的ActivityManagerNative是直接定義在源碼中的,而這個AMN就相當于后面出現的Stub,后面出現的IPackageManger或者是IWindowManager都是通過aidl的方式去生成的,都是我們通過編譯源碼的方式生成的,此處如果對aidl不了解可以去了學習一下aidl的知識。

Binder的結構(此處分別以AMS和PMS進行分析)

  1. AMS


    AMS的簡易關系

    最最根部的是接口IActivityManager,這個接口定義了AMS所有需要用到的服務的方法,并且需要繼承IInterface,我們可以把他理解為一個叫I的接口,因為所有的binder的東西都是跟這個前綴叫I的東西有關的,這個IInterface定義了一個asBinder的方法,可以把所有繼承這個IInterface的類統統轉化成IBinder。

/**
 * Base class for Binder interfaces.  When defining a new interface,
 * you must derive it from IInterface.
 */
public interface IInterface
{
    /**
     * Retrieve the Binder object associated with this interface.
     * You must use this instead of a plain cast, so that proxy objects
     * can return the correct result.
     */
    public IBinder asBinder();
}

OK,我們繼續往上一層看
ActivityManagerNative繼承了Binder而Binder實現了IBinder這個接口,我們暫且不去分析這兩個類事干什么用的,只需要知道跟binder機制有關系。
那么既然AMN最終實現了IBinder這個接口,又繼承了IActivityManger這個類,那么上面所說的adBinder這個方法直接返回其本身就可以了,果不其然。

public IBinder asBinder() {
        return this;
    }

但是當我們在這個類中搜索asBinder這個方法的時候我們卻發現實現的不止一處,還有一處也實現了這個方法,

public IBinder asBinder()
    {
        return mRemote;
    }

結果看到還有個代理類ActivityManagerProxy,于是乎就很好奇的去ctrl+G了。發現來自與ActivityManagerNative的方法asInterface:

/**
     * Cast a Binder object into an activity manager interface, generating
     * a proxy if needed.
     */
    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);
    }

我們看到注釋已經寫的相當明白了,把一個Binder對象轉換成Activity Manager接口,如果有必要的話搞一個Activity Manager的代理出來。我們把其中的兩個方法逐個擊破,首先是obj.queryLocalInterface,這個是IBinder的方法:

/**
     * Attempt to retrieve a local implementation of an interface
     * for this Binder object.  If null is returned, you will need
     * to instantiate a proxy class to marshall calls through
     * the transact() method.
     */
    public IInterface queryLocalInterface(String descriptor);

其實就是要去獲得這個binder接口的本地實現,上面也說了,如果獲取不到,需要通過搞一個代理出來,直接看這個接口方法還是比較難理解這玩意兒到底是干嘛的,那我們就去找一找什么地方使用到了這個asInterface方法,全局一下(此處真的體會到導入源碼的重要性),發現有三處調用,我們只看重要的一處:

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

這個是用的非常平凡的方法,ActivityManagerNative的gDefault變量,實際上就是維護這一個IActivityManager的單例,我們看到這個IBinder b是來自于ServiceManager的serviceMap(這個之前看過一點binder的服務注冊的應該都會知道),但是我之前一直不知道到底是什么時候把activityManagerservice這個東西注冊進去的,現在有了源碼了,找了一下,果然就找到了,在ActivityManagerService中有這么一個方法,里面把AMS自生注冊到了ServiceManager中:

public void setSystemProcess() {
        try {
            ServiceManager.addService(Context.ACTIVITY_SERVICE, this, true);
            ServiceManager.addService(ProcessStats.SERVICE_NAME, mProcessStats);
            ServiceManager.addService("meminfo", new MemBinder(this));
            ServiceManager.addService("gfxinfo", new GraphicsBinder(this));
            ServiceManager.addService("dbinfo", new DbBinder(this));
            if (MONITOR_CPU_USAGE) {
                ServiceManager.addService("cpuinfo", new CpuBinder(this));
            }
            ServiceManager.addService("permission", new PermissionController(this));
            ServiceManager.addService("processinfo", new ProcessInfoService(this));
            ....
        }
        ....
    }
    ....
}

我們看到傳的是this,這個時候我們終于要去點開那個神器的queryLocalInterface方法了,看看它是怎么實現的:

/**
     * Use information supplied to attachInterface() to return the
     * associated IInterface if it matches the requested
     * descriptor.
     */
    public IInterface queryLocalInterface(String descriptor) {
        if (mDescriptor.equals(descriptor)) {
            return mOwner;
        }
        return null;
    }

很明顯,做了一個字符串匹配,如果相同就把mOwner返回出去,我們在Binder.java中找到了這兩個變量的定義:

public void attachInterface(IInterface owner, String descriptor) {
        mOwner = owner;
        mDescriptor = descriptor;
    }

然后我們又在ActivityManagerNative中找到了這個方法的調用:

public ActivityManagerNative() {
        attachInterface(this, descriptor);
    }
    String descriptor = "android.app.IActivityManager";

水落石出了吧,捋一捋邏輯之后我們發現,實際上最初的那個queryLocalInterface方法,實際上就是去對穿進來的binder最一個教研,看這個binder是不是AMS,如果是AMS那么就去把它轉換成IActivityManager,如果不是那么就搞一個ActivityManagerProxy代理出來。其實這里面就涉及到一個問題,大家會不會覺得這個queryLocalInterface方法永遠都是有效的呢,其實不然,這里就要涉及到跨進程的東西了,在單進程中去理解事沒有問題的,但是跨進程的時候就會有問題了,這里其實我們可以從ActivityManagerProxy的構造函數能夠看的出來:

public ActivityManagerProxy(IBinder remote)
    {
        mRemote = remote;
    }
private IBinder mRemote;

這個傳進來的remote就是另外一個進程的binder,那么我們如何去理解呢?
queryLocalInterface這個方法實際上真正的用途是去判斷一下,這個binder是否是在當前的進程,如果不在,那么就去搞一個代理,如果在當前進程,就直接把它轉成IActivityManager進行使用(因為服務真正的方法都定義在了IActivityManager這個接口里面,那么轉成接口就可以直接去使用它的方法了)。

拋開底層Binder不談的整個framework層的IPC交互流程

我們在這里停一下,先來看一下整個涉及到binder的類的結構(以AMS和PMS這兩個典型為例)

  1. AMS


    AMS結構

    我們可以看到系統基本在使用AMS的時候直接使用的是ActivityManagerNative.getDefault()去做調用,就跟標注的一樣,如果AMS服務就在當前的進程中那么直接調用ActivityManagerService中的相應方法。如果不在一個進程中,那么就調用Proxy的方法,就要涉及到使用IPC通信了,我們可以看到Proxy的方法都會涉及到mRemote.transact方法,然后在遠程進程的繼承ActivityManagerNative的AMS會首先觸發onTransact方法,并在onTransact中去調用相應的請求方法。
    我們以AMS的startActivity方法為例:
    (1) 如果在一個進程中,那么直接就去調用AMS的startActivity方法:

@Override
    public final int startActivity(IApplicationThread caller, String callingPackage,
            Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
            int startFlags, ProfilerInfo profilerInfo, Bundle bOptions) {
        return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
                resultWho, requestCode, startFlags, profilerInfo, bOptions,
                UserHandle.getCallingUserId());
    }

(2) 如果不在一個進程中,那么就先去調用ActivityManagerProxy的startActivity方法:

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(START_ACTIVITY_TRANSACTION, data, reply, 0);
        reply.readException();
        int result = reply.readInt();
        reply.recycle();
        data.recycle();
        return result;
    }

然后在另外一個進程中的ActivityMangerService接收到了transact請求,觸發了onTransact方法(這個方法定義在了基類ActivityManagerNative中:

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

我們看到會在onTransact方法中再去調用AMS中的startActivity方法。
基本frameWork級別的都是直接調用的ActivityManagerNative.getDefault()去處理的,而我們平時需要使用到AMS的服務的時候都是直接去使用ActivityManager的相應方法的(當然只會局限于部分方法,因為AMS里的大部分方法我們是用不到的),比如getDeviceConfigurationInfo方法:

/**
     * Get the device configuration attributes.
     */
    public ConfigurationInfo getDeviceConfigurationInfo() {
        try {
            return ActivityManagerNative.getDefault().getDeviceConfigurationInfo();
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

很明顯了,我們所使用到的ActivityManager實際上就是對ActivityManagerNative的一個封裝,把常用的方法放出來給用戶使用。

  1. PMS


    PMS結構

    與AMS有幾點不同:
    (1)沒有了類似于ActivityManagerNative這樣的類,凡是使用aidl文件生成的Binder文件都是這樣的結構,在IPackageManager中定義了內部類Stub和Proxy,分別對應ActivityMangaerNative和ActivityManagerNative.ActivityManagerProxy.
    (2) PackageMange是一個抽象類,具體的實現在ApplicationPackageManager中,而我們平時直接去使用PackageManger都是直接在Activity中調用getPackageManager:

@Override
    public PackageManager getPackageManager() {
        if (mPackageManager != null) {
            return mPackageManager;
        }

        IPackageManager pm = ActivityThread.getPackageManager();
        if (pm != null) {
            // Doesn't matter if we make more than one instance.
            return (mPackageManager = new ApplicationPackageManager(this, pm));
        }

        return null;
    }

我們可以看到IPackageManger來自與 ActivityThread.getPackageManager():

public static IPackageManager getPackageManager() {
        if (sPackageManager != null) {
            //Slog.v("PackageManager", "returning cur default = " + sPackageManager);
            return sPackageManager;
        }
        IBinder b = ServiceManager.getService("package");
        //Slog.v("PackageManager", "default service binder = " + b);
        sPackageManager = IPackageManager.Stub.asInterface(b);
        //Slog.v("PackageManager", "default service = " + sPackageManager);
        return sPackageManager;
    }

而返回的PackageManger是new ApplicationPackageManager(this, pm)

ApplicationPackageManager(ContextImpl context,
                              IPackageManager pm) {
        mContext = context;
        mPM = pm;
    }

然后我們平時使用PackageManager的方法實際上都是類似于如下的調用:

@Override
    public ActivityInfo getActivityInfo(ComponentName className, int flags)
            throws NameNotFoundException {
        try {
            ActivityInfo ai = mPM.getActivityInfo(className, flags, mContext.getUserId());
            if (ai != null) {
                return ai;
            }
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }

        throw new NameNotFoundException(className.toString());
    }

至此FrameWork層的Binder基本吃透,TBC。。。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容