Android点将台:金科玉律[-AIDL-]

我的全部文章整理在此篇,将陆续更新收录:知无涯,行者之路莫言终(个人编程之路)java

零、前言

本文接Android点将台:绝命暗杀官[-Service-]篇,本文图例见
本文经过AIDL实现了跨进程间调用Service(即App2调用App1的Service)
本篇未来探索一下AIDL自动生成的类,再从新审视一下ActivityManagerServiceandroid


1、上一篇中AIDL自动生成的IMusicPlayerService分析

1.IMusicPlayerService的类结构

太多了,有点晃眼,打开结构图来分析一下编程

类结构.png


IMusicPlayerService.png


2.从IInterface开始

IMusicPlayerService是一个接口,而且继承于IInterface接口,那IInterface是何许人也?
就这两行代码,只有一个asBinder方法,返回一个IBinder对象,注意它在的包是android.osbash

package android.os;
public interface IInterface{
    public IBinder asBinder();
}
复制代码

3.IMusicPlayerService的分析

可见除去Stub,IMusicPlayerService里只是咱们在IMusicPlayerService.aidl定义的接口
也没有什么太多要说明的地方,咱们的终极目标是看一下它的实现类是什么app

/*
 * This file is auto-generated.  DO NOT MODIFY.
    自动生成的,不要修改
 * Original file: J:\\Java\\Android\\LeverUp\\TolyService\\app\\src\\main\\aidl\\com\\toly1994\\tolyservice\\IMusicPlayerService.aidl
 原始文件在: J:\\Java\\Android\\LeverUp\\TolyService\\app\\src\\main\\aidl\\com\\toly1994\\tolyservice\\IMusicPlayerService.aidl
 */
package com.toly1994.tolyservice;
// Declare any non-default types here with import statements
//在这里使用import语句声明任何非默认类型

public interface IMusicPlayerService extends android.os.IInterface {
    //Stub类,暂略...
    /**
     * Demonstrates some basic types that you can use as parameters
     * and return values in AIDL.
      说明一些在AIDL中能够用做参数和返回值的基本类型。
     */
    public void stop() throws android.os.RemoteException;
    public void pause() throws android.os.RemoteException;
    public void start() throws android.os.RemoteException;
    public void prev() throws android.os.RemoteException;
    public void next() throws android.os.RemoteException;
    public void release() throws android.os.RemoteException;
    public boolean isPlaying() throws android.os.RemoteException;
    public void seek(int pre_100) throws android.os.RemoteException;
    public void create(java.util.List<java.lang.String> filePaths) throws android.os.RemoteException;
}
复制代码

4.而后固然是深刻一下,到Stub

英语Stub有存根的意思,看完本篇以后本身意会一下它的含义
它不只继承Binder,并且实现了IMusicPlayerService,看起来挺牛的,惋惜是个抽象类
它实现了Binder的一些东西,但并无IMusicPlayerService的任何方法,就是挂个头而已
实现从成员变量来看,每一个方法都对应了一个int常量,从switch来看应该是方法的标识
DESCRIPTOR对应了一个包名.IMusicPlayerService字符串,用于attachInterfaceide

Stub分析.png

public static abstract class Stub extends android.os.Binder implements com.toly1994.tolyservice.IMusicPlayerService {
     private static final java.lang.String DESCRIPTOR = "com.toly1994.tolyservice.IMusicPlayerService";

     /**
      * Construct the stub at attach it to the interface.
        在将关联到接口时构造stub。----注意使用了DESCRIPTOR字符串
      */
     public Stub() {
         this.attachInterface(this, DESCRIPTOR);
     }

     /**
      * Cast an IBinder object into an com.toly1994.tolyservice.IMusicPlayerService interface,
      * generating a proxy if needed.
      */
     public static com.toly1994.tolyservice.IMusicPlayerService asInterface(android.os.IBinder obj) {
         if ((obj == null)) {
             return null;
         }
         android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
         if (((iin != null) && (iin instanceof com.toly1994.tolyservice.IMusicPlayerService))) {
             return ((com.toly1994.tolyservice.IMusicPlayerService) iin);
         }
         return new com.toly1994.tolyservice.IMusicPlayerService.Stub.Proxy(obj);
     }

     @Override
     public android.os.IBinder asBinder() {
         return this;
     }

     @Override
     public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException {
         java.lang.String descriptor = DESCRIPTOR;
         switch (code) {
             case INTERFACE_TRANSACTION: {
                 reply.writeString(descriptor);
                 return true;
             }
             case TRANSACTION_stop: {//暂略...
                 return true;
             }
             case TRANSACTION_pause: {//暂略...
                 return true;
             }
             case TRANSACTION_start: {//暂略...
                 return true;
             }
             case TRANSACTION_prev: {//暂略...
                 return true;
             }
             case TRANSACTION_next: {//暂略...
                 return true;
             }
             case TRANSACTION_release: {//暂略...
                 return true;
             }
             case TRANSACTION_isPlaying: {//暂略...
                 return true;
             }
             case TRANSACTION_seek: {//暂略...
                 return true;
             }
             case TRANSACTION_create: {//暂略...
                 return true;
             }
             default: {
                 return super.onTransact(code, data, reply, flags);
             }
         }
     }
     
     //Proxy类,暂略...
     static final int TRANSACTION_stop = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
     static final int TRANSACTION_pause = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
     static final int TRANSACTION_start = (android.os.IBinder.FIRST_CALL_TRANSACTION + 2);
     static final int TRANSACTION_prev = (android.os.IBinder.FIRST_CALL_TRANSACTION + 3);
     static final int TRANSACTION_next = (android.os.IBinder.FIRST_CALL_TRANSACTION + 4);
     static final int TRANSACTION_release = (android.os.IBinder.FIRST_CALL_TRANSACTION + 5);
     static final int TRANSACTION_isPlaying = (android.os.IBinder.FIRST_CALL_TRANSACTION + 6);
     static final int TRANSACTION_seek = (android.os.IBinder.FIRST_CALL_TRANSACTION + 7);
     static final int TRANSACTION_create = (android.os.IBinder.FIRST_CALL_TRANSACTION + 8);
 }
复制代码

5.如今看最后一层奶油夹心:Proxy

如今把聚光灯打到Stub的内部类Proxy上,Proxy是个敲代码的都知道是代理的意思
既然是代理,它代理什么?成员变量有个IBinder mRemote,构造方法要传一个IBinder,so...
它实现了IMusicPlayerService,而且有所动做,并且动做基本一致函数

Proxy.png

private static class Proxy implements com.toly1994.tolyservice.IMusicPlayerService {
    private android.os.IBinder mRemote;

    Proxy(android.os.IBinder remote) {
        mRemote = remote;
    }

    @Override
    public android.os.IBinder asBinder() {
        return mRemote;
    }

    public java.lang.String getInterfaceDescriptor() {
        return DESCRIPTOR;
    }

    /**
     * Demonstrates some basic types that you can use as parameters
     * and return values in AIDL.
     */
    @Override
    public void stop() throws android.os.RemoteException {
        android.os.Parcel _data = android.os.Parcel.obtain();
        android.os.Parcel _reply = android.os.Parcel.obtain();
        try {
            _data.writeInterfaceToken(DESCRIPTOR);
            mRemote.transact(Stub.TRANSACTION_stop, _data, _reply, 0);
            _reply.readException();
        } finally {
            _reply.recycle();
            _data.recycle();
        }
    }

    @Override
    public void pause() throws android.os.RemoteException {//暂略...
    }

    @Override
    public void start() throws android.os.RemoteException {//暂略...
    }

    @Override
    public void prev() throws android.os.RemoteException {//暂略...
    }

    @Override
    public void next() throws android.os.RemoteException {//暂略...
    }

    @Override
    public void release() throws android.os.RemoteException {//暂略...
    }

    @Override
    public boolean isPlaying() throws android.os.RemoteException {//暂略...
    }

    @Override
    public void seek(int pre_100) throws android.os.RemoteException {//暂略...
    }

    @Override
    public void create(java.util.List<java.lang.String> filePaths) throws android.os.RemoteException {//暂略...
    }
}
复制代码

到如今为止,它们几个的关系理清了,下面就来详细看看哪些//暂略...的方法post


2、Binder和IBinder的个别方法

这里先列举出上面使用到的方法ui

binder与Ibinder.png


1.目前IBinder台面上出现的方法
public interface 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.
     尝试检索此绑定器对象的本地接口实现。
     若是返回null,则须要经过transact()方法实例化一个代理类来调用。
     */
    public @Nullable IInterface queryLocalInterface(@NonNull String descriptor);

    /**
     * Perform a generic operation with the object.
     * 使用对象执行通常操做。
     * @param code The action to perform.  This should be a number between {@link #FIRST_CALL_TRANSACTION} and {@link #LAST_CALL_TRANSACTION}.
    code 操做的行为码  0x00000001 ~ 0x00ffffff 之间 1~16777215
     * @param data Marshalled data to send to the target.  Must not be null.If you are not sending any data, you must create an empty Parcel that is given here.
    data 发送到目标的编组数据。不能为空。若是您没有发送任何数据,则必须建立这里给出的空包。
     * @param reply Marshalled data to be received from the target.  May be null if you are not interested in the return value.
     从目标接收到的编组数据。若是您对返回值不感兴趣,则可能为null。
     * @param flags Additional operation flags.  Either 0 for a normal RPC, or {@link #FLAG_ONEWAY} for a one-way RPC.
   flags  额外的操做标志,对于普通RPC为0,对于单向RPC为1{@link #FLAG_ONEWAY}。
    
     * @return Returns the result from {@link Binder#onTransact}. A successful call generally returns true; false generally means the transaction code was not understood.
   return  从Binder.onTransact()返回结果。成功调用一般返回true;false一般表示事务代码未被理解。
     */
    public boolean transact(int code, @NonNull Parcel data, @Nullable Parcel reply, int flags)
        throws RemoteException;
    //其余...略
}
复制代码

2.目前Binder台面上出现的方法
---->[Binder]-------------
private IInterface mOwner;
private String mDescriptor;

---->[Binder#attachInterface]-------------
 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.
|--译:一个将特定接口与Binder关联的方便方法。调用后,将为你实现queryLocalInterface(),
|--以便在请求相应的描述符时返回owner (IInterface对象)。
public void attachInterface(@Nullable IInterface owner, @Nullable Stringdescriptor) {
    mOwner = owner;
    mDescriptor = descriptor;
}

---->[Binder#queryLocalInterface]-------------
 Use information supplied to attachInterface() to return the associated 
 IInterface if it matches the requested descriptor.
 若是提供的描述符,与经过attachInterface()方法进行关联的IInterface一致
 返回该IInterface,不然返回null
public @Nullable IInterface queryLocalInterface(@NonNull String descriptor) {
    if (mDescriptor.equals(descriptor)) {
        return mOwner;
    }
    return null;
}

---->[Binder#onTransact]-------------
 * Default implementation is a stub that returns false.  You will want
 * to override this to do the appropriate unmarshalling of transactions.
 * 默认实现是stub返回false。您会想要覆谢它,以便对事务进行适当的反编组。
 * <p>If you want to call this, call transact().
protected boolean onTransact(int code, @NonNull Parcel data, @Nullable Parcel
reply,int flags) throws RemoteException {
复制代码

3.再来看刚才暂略的方法
3.1:attachInterface

此方法在Stub的构造函数中调用,为成员变量mOwnermDescriptor赋值this

attachInterface.png

---->[IMusicPlayerService.Stub#Stub]-------------
public Stub() {
    this.attachInterface(this, DESCRIPTOR);
}
|---这里调用了attachInterface方法,参数是本身和描述符

---->[Binder]-------------
private IInterface mOwner;
private String mDescriptor;

---->[Binder#attachInterface]-------------
public void attachInterface(@Nullable IInterface owner, @Nullable String descriptor) {
    mOwner = owner;
    mDescriptor = descriptor;
}
复制代码

3.2:asInterface

传入一个IBinder对象obj,调用obj的queryLocalInterface方法生成IInterface对象
再进行强转,若是强转不成功,才会建立Proxy代理对象

asInterface.png

---->[IMusicPlayerService.Stub#asInterface]-------------
public static com.toly1994.tolyservice.IMusicPlayerService asInterface(android.os.IBinder obj) {
    if ((obj == null)) {
        return null;
    }
    android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
    if (((iin != null) && (iin instanceof com.toly1994.tolyservice.IMusicPlayerService))) {
        return ((com.toly1994.tolyservice.IMusicPlayerService) iin);
    }
    return new com.toly1994.tolyservice.IMusicPlayerService.Stub.Proxy(obj);
}
复制代码

3.3: asBinder

asBinder是IInterface接口的方法,把本身(Stub继承自Binder)返回去,没什么好说的

---->[IMusicPlayerService.Stub#asInterface]-------------
@Override
public android.os.IBinder asBinder() {
    return this;
}
复制代码

3.4: onTransact

此方法运行在服务端Binder线程池中,客户端发起跨进程请求时,远程请求经过系统底层封装后交由此方法处理。
处理的逻辑基本上都同样,经过判断code来调用方法,这里看两个startseek,

onTransact.png

@Override
public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel
reply, int flags) throws android.os.RemoteException {
    java.lang.String descriptor = DESCRIPTOR;
    switch (code) {
    //略...
        case TRANSACTION_start: {
            data.enforceInterface(descriptor);//执行接口
            this.start();//调用start方法
            reply.writeNoException();//将计算结果写入reply中
            return true;
        }
        case TRANSACTION_seek: {
            data.enforceInterface(descriptor);//执行接口
            int _arg0;
            _arg0 = data.readInt();//获取数据
            this.seek(_arg0);//调用seek方法
            reply.writeNoException();//将计算结果写入reply中
            return true;
        }
  //略...
复制代码

3.5:Proxy中的实现方法

Proxy是代理类,运行在客户端,也就是Stub#asInterface中iin
没法强转成IMusicPlayerService是返回Proxy类对象

---->[IMusicPlayerService.Stub.Proxy#start]--------
@Override
public void start() throws android.os.RemoteException {
    android.os.Parcel _data = android.os.Parcel.obtain();
    android.os.Parcel _reply = android.os.Parcel.obtain();
    try {
         //向_data中写入参数
        _data.writeInterfaceToken(DESCRIPTOR);
        //经过transact方法向服务端传递参数,并写入_reply
        mRemote.transact(Stub.TRANSACTION_start, _data, _reply, 0);
        _reply.readException();
    } finally {
        _reply.recycle();
        _data.recycle();
    }
}

@Override
public void seek(int pre_100) throws android.os.RemoteException {
    android.os.Parcel _data = android.os.Parcel.obtain();
    android.os.Parcel _reply = android.os.Parcel.obtain();
    try {
        _data.writeInterfaceToken(DESCRIPTOR);
        _data.writeInt(pre_100);
        mRemote.transact(Stub.TRANSACTION_seek, _data, _reply, 0);
        _reply.readException();
    } finally {
        _reply.recycle();
        _data.recycle();
    }
}
复制代码

4.如今再来看咱们在Service中画的最后一张图

ServiceConnection的onServiceConnected方法会回调一个IBinder对象service
并经过IMusicPlayerService.Stub.asInterface方法将service变成IMusicPlayerService对象
还记得asInterface里作了什么吗?下面再看一遍,aidl在使用层面的逻辑是否是清晰了一些?

这里要强调一下:
图中:蓝色区域可在任意app中使用,至关于客户端:只要链接就好了   
其余区域是服务端的逻辑,为客户端提供业务逻辑处理 
复制代码

aidl绑定服务.png

asInterface.png

至于Binder在底层怎么跑的,那是后话,那根钻石级的硬骨头仍是最后啃吧


5.小结一下:如今回头再看
1.在一个aidl的服务中,业务逻辑的处理是在哪的?
|--- 这还用问吗,固然在MusicPlayerStub里面,否则还能在哪?

2.IMusicPlayerService和Stub有什么用
|--- IMusicPlayerService是可调用的接口
|--- Stub在台面上有一个功劳,用asInterface将IBinder对象转化为IMusicPlayerService对象

3.Proxy有什么用?
|---Proxy惟一出现的是在asInterface方法中,在inn没法强转成IMusicPlayerService时使用Proxy  

4.何时inn没法转成IMusicPlayerService?(见下图)
|--- 我作了一个实验,就是分别看一下客户端和服务端绑定时回调的IBinder对象类型
再调用queryLocalInterface方法获得inn,看一下它的类型
服务端是:MusicPlayerStub ,它何许人也? Stub之子,Stub实现了IMusicPlayerService,强转ok  
客户端是:BinderProxy对象queryLocalInterface后为null,使用Proxy  
复制代码

客户端与服务端绑定服务的区别.png

queryLocalInterface.png


3、ActivityManagerService初探

1.对于系统级跨进程通讯的Service如何分析
当咱们研究源码时遇到这种代码应该怎么分析?(如ActivityManagerNative)
能够看出不管Stub和Proxy或Binder对代码的逻辑性的分析并无太大的用处,
他们只是实现类跨进程通讯的机制,这种机制和逻辑相关性不是很是大

IXXXService只是规定接口方法,须要了解一下,着重的业务逻辑全在XXXXStub的实现类当中,
通常XXXXStub是做为XXXXService的内部类,也就是说看到有关aidl的系统服务源码时,
直接分析XXXXService就好了,逻辑全在那里
复制代码

2.AIDL为什么而生
|--- 一个字:懒...   
自动生成的那个类,本身敲出来也能跑,既然能自动生成,那就生成呗,AIDL就出来了
这样就简化了跨进程间通讯,可是凡事都有两面性,一旦简化了,就很难玩花样
Binder能够很复杂,IBinder还有不少控制的方法,因此AIDL只是最简单的跨进程间通讯机制  
就像快速生产的板凳和精心雕刻的板凳,虽然都能坐,但价值是天差地别的
复制代码

3.ActivityManagerNative分析

还记得第一篇中Activity启动时出场的ActivityManagerNative吗?
这就是传说中的ActivityManagerNative你能够和最上面的IMusicPlayerService对比一下

ActivityManagerNative分析.png


4.ActivityManagerNative的幕后大佬

通常来讲都是调用ActivityManagerNative.getDefault()生成一个IActivityManager对象
而后调用IActivityManager的相应抽象方法,那具体的实现类是谁?
ActivityManagerNative的做用至关于上面的Stub,须要找到一个继承他的类
这即是ActivityManagerService,注意它并非Service类对象,而是服务的核心逻辑
它的价值也就至关于咱们上面的MusicPlayerStub,不是Service,却更似服务

ActivityManagerService.png


5.ActivityManagerNative.getDefault()方法说了什么?

返回一个IActivityManager对象,实际类型为ActivityManagerService

ActivityManagerNative.getDefalut.png

---->[ActivityManagerNative#getDefault]--------------------
static public IActivityManager对象 getDefault() {
    return gDefault.get();
}

//|--这里经过gDefault成员变量的get()方法获取了一个IActivityManager对象
|----如今焦点在gDefault身上,来看一下他是什么

---->[ActivityManagerNativegetDefault.gDefault]--------------------
private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
    protected IActivityManager create() {
        //经过ServiceManager获取activity的IBinder对象
        IBinder b = ServiceManager获取.getService("activity");
        if (false) {
            Log.v("ActivityManager", "default service binder = " + b);
        }
        //asInterface方法使用IBinder对象,获取IActivityManager对象
        IActivityManager am = asInterface(b);
        if (false) {
            Log.v("ActivityManager", "default service = " + am);
        }
        return am;
    }
};

//|--gDefault的数据类型是Singleton<IActivityManager>,有点意思,看一下Singleton类
----单例辅助类啊!create()方法用于穿件对象,get方法获取单例对象,但它是@hide的,咱们不能用
public abstract class Singleton<T> {
    private T mInstance;
    protected abstract T create();
    public final T get() {
        synchronized (this) {
            if (mInstance == null) {
                mInstance = create();
            }
            return mInstance;
        }
    }
}

---->[ActivityManagerNativegetDefault.asInterface]--------------------
static public IActivityManager asInterface(IBinder obj) {
    if (obj == null) {
        return null;
    }
    //若是obj(即Bundle) queryLocalInterface 不为空,就使用in
    IActivityManager in =
        (IActivityManager)obj.queryLocalInterface(descriptor);
    if (in != null) {
        return in;
    }
    //不然返回ActivityManagerProxy对象
    return new ActivityManagerProxy(obj);
}

---->[ActivityManagerNativegetDefault$ActivityManagerProxy]--------------------
class ActivityManagerProxy implements IActivityManager{
    public ActivityManagerProxy(IBinder remote){
        mRemote = remote;
    }
    public IBinder asBinder(){
        return mRemote;
    }
    //略...
        public int broadcastIntent(IApplicationThread caller,
            Intent intent, String resolvedType, IIntentReceiver resultTo,
            int resultCode, String resultData, Bundle map,
            String[] requiredPermissions, int appOp, Bundle options, boolean serialized,
            boolean sticky, int userId) throws RemoteException
    //略...
    }
复制代码

这样使用ActivityManagerNative.getDefault()即可以得到一个IActivityManager对象,
该对象的实现类型为ActivityManagerService,也就是传说中的AMS,
因此在看源码时ActivityManagerNative.getDefault(),就至关于看到了AMS