美文网首页Android日记程序员今日看点
突然悟出在源码中分析Binder的玩法

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

作者: super_shanks | 来源:发表于2017-02-28 12:04 被阅读145次

首先我们可以去这样理解:(综合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.jianshu.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。。。

相关文章

网友评论

    本文标题:突然悟出在源码中分析Binder的玩法

    本文链接:https://www.haomeiwen.com/subject/tqwuvttx.html