Android Binder系列之AIDL分析(3)

前言

上一篇文章講了AIDL的使用,我們知道AIDL是方便我們使用Binder的插件,那麼AIDL到底做了哪些事情呢?不知道你有沒有看過Activity的啓動流程,最終會跨進程調用ActivityManageService,但是他並沒有使用AIDL呀,他是怎麼使用Binder的呢?看完這篇文章你就知道了。

由於跨進程並不能直接傳遞對象,所以除了一些基本類型之外要傳遞的對象都需要先進行序列化操作,java中的序列化方式有兩種:Serializable和Parcelable,Parcelable的性能更好所以是安卓推薦的方式。

代碼結構分析

還記得上一篇文章寫好AIDL後會clean一下項目嗎,這一步操作是爲了生成一個文件IMyAidlInterface.java,這個接口就是Binder通信的真正執行者,看一下這個接口的結構:
在這裏插入圖片描述
這個接口中有三個方法:basicTypes、getPeople、addPeople。
都是我們在IMyAidlInterface.aidl中定義的通信方法,接口中有兩個內部類:Default和Stub,Default我們不用管,Stub這個名字熟悉嗎?這不就是我們在Service中定義和返回的binder嗎:

    private IMyAidlInterface.Stub binder = new IMyAidlInterface.Stub() {
        @Override
        public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException {
            Log.e(TAG, "basicTypes: anInt=" + anInt + " aLong=" + aLong + " aBoolean=" + aBoolean +
                    " aFloat=" + aFloat + " aDouble=" + aDouble + " aString=" + aString);
        }

        @Override
        public People getPeople() throws RemoteException {
            return people;
        }

        @Override
        public void addPeople(People people) throws RemoteException {
            Log.e(TAG, "addPeople: " + people.toString());
        }
    };

原來這個類是從這裏來的,另外Stub中還有一個內部類Proxy,這個類就這麼多東西,我們看一下他全部的代碼:

public interface IMyAidlInterface extends android.os.IInterface
{
  /** Default implementation for IMyAidlInterface. */
  public static class Default implements com.czy.server.IMyAidlInterface
  {
    /**
         * Demonstrates some basic types that you can use as parameters
         * and return values in AIDL.
         */
    @Override public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, java.lang.String aString) throws android.os.RemoteException
    {
    }
    @Override public com.czy.server.People getPeople() throws android.os.RemoteException
    {
      return null;
    }
    @Override public void addPeople(com.czy.server.People people) throws android.os.RemoteException
    {
    }
    @Override
    public android.os.IBinder asBinder() {
      return null;
    }
  }
  /** Local-side IPC implementation stub class. */
  public static abstract class Stub extends android.os.Binder implements com.czy.server.IMyAidlInterface
  {
    private static final java.lang.String DESCRIPTOR = "com.czy.server.IMyAidlInterface";
    /** Construct the stub at attach it to the interface. */
    public Stub()
    {
      this.attachInterface(this, DESCRIPTOR);
    }
    /**
     * Cast an IBinder object into an com.czy.server.IMyAidlInterface interface,
     * generating a proxy if needed.
     */
    public static com.czy.server.IMyAidlInterface asInterface(android.os.IBinder obj)
    {
      if ((obj==null)) {
        return null;
      }
      android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
      if (((iin!=null)&&(iin instanceof com.czy.server.IMyAidlInterface))) {
        return ((com.czy.server.IMyAidlInterface)iin);
      }
      return new com.czy.server.IMyAidlInterface.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_basicTypes:
        {
          data.enforceInterface(descriptor);
          int _arg0;
          _arg0 = data.readInt();
          long _arg1;
          _arg1 = data.readLong();
          boolean _arg2;
          _arg2 = (0!=data.readInt());
          float _arg3;
          _arg3 = data.readFloat();
          double _arg4;
          _arg4 = data.readDouble();
          java.lang.String _arg5;
          _arg5 = data.readString();
          this.basicTypes(_arg0, _arg1, _arg2, _arg3, _arg4, _arg5);
          reply.writeNoException();
          return true;
        }
        case TRANSACTION_getPeople:
        {
          data.enforceInterface(descriptor);
          com.czy.server.People _result = this.getPeople();
          reply.writeNoException();
          if ((_result!=null)) {
            reply.writeInt(1);
            _result.writeToParcel(reply, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
          }
          else {
            reply.writeInt(0);
          }
          return true;
        }
        case TRANSACTION_addPeople:
        {
          data.enforceInterface(descriptor);
          com.czy.server.People _arg0;
          if ((0!=data.readInt())) {
            _arg0 = com.czy.server.People.CREATOR.createFromParcel(data);
          }
          else {
            _arg0 = null;
          }
          this.addPeople(_arg0);
          reply.writeNoException();
          return true;
        }
        default:
        {
          return super.onTransact(code, data, reply, flags);
        }
      }
    }
    private static class Proxy implements com.czy.server.IMyAidlInterface
    {
      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 basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, java.lang.String aString) 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(anInt);
          _data.writeLong(aLong);
          _data.writeInt(((aBoolean)?(1):(0)));
          _data.writeFloat(aFloat);
          _data.writeDouble(aDouble);
          _data.writeString(aString);
          boolean _status = mRemote.transact(Stub.TRANSACTION_basicTypes, _data, _reply, 0);
          if (!_status && getDefaultImpl() != null) {
            getDefaultImpl().basicTypes(anInt, aLong, aBoolean, aFloat, aDouble, aString);
            return;
          }
          _reply.readException();
        }
        finally {
          _reply.recycle();
          _data.recycle();
        }
      }
      @Override public com.czy.server.People getPeople() throws android.os.RemoteException
      {
        android.os.Parcel _data = android.os.Parcel.obtain();
        android.os.Parcel _reply = android.os.Parcel.obtain();
        com.czy.server.People _result;
        try {
          _data.writeInterfaceToken(DESCRIPTOR);
          boolean _status = mRemote.transact(Stub.TRANSACTION_getPeople, _data, _reply, 0);
          if (!_status && getDefaultImpl() != null) {
            return getDefaultImpl().getPeople();
          }
          _reply.readException();
          if ((0!=_reply.readInt())) {
            _result = com.czy.server.People.CREATOR.createFromParcel(_reply);
          }
          else {
            _result = null;
          }
        }
        finally {
          _reply.recycle();
          _data.recycle();
        }
        return _result;
      }
      @Override public void addPeople(com.czy.server.People people) throws android.os.RemoteException
      {
        android.os.Parcel _data = android.os.Parcel.obtain();
        android.os.Parcel _reply = android.os.Parcel.obtain();
        try {
          _data.writeInterfaceToken(DESCRIPTOR);
          if ((people!=null)) {
            _data.writeInt(1);
            people.writeToParcel(_data, 0);
          }
          else {
            _data.writeInt(0);
          }
          boolean _status = mRemote.transact(Stub.TRANSACTION_addPeople, _data, _reply, 0);
          if (!_status && getDefaultImpl() != null) {
            getDefaultImpl().addPeople(people);
            return;
          }
          _reply.readException();
        }
        finally {
          _reply.recycle();
          _data.recycle();
        }
      }
      public static com.czy.server.IMyAidlInterface sDefaultImpl;
    }
    static final int TRANSACTION_basicTypes = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
    static final int TRANSACTION_getPeople = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
    static final int TRANSACTION_addPeople = (android.os.IBinder.FIRST_CALL_TRANSACTION + 2);
    public static boolean setDefaultImpl(com.czy.server.IMyAidlInterface impl) {
      if (Stub.Proxy.sDefaultImpl == null && impl != null) {
        Stub.Proxy.sDefaultImpl = impl;
        return true;
      }
      return false;
    }
    public static com.czy.server.IMyAidlInterface getDefaultImpl() {
      return Stub.Proxy.sDefaultImpl;
    }
  }
  /**
       * Demonstrates some basic types that you can use as parameters
       * and return values in AIDL.
       */
  public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, java.lang.String aString) throws android.os.RemoteException;
  public com.czy.server.People getPeople() throws android.os.RemoteException;
  public void addPeople(com.czy.server.People people) throws android.os.RemoteException;
}

代碼分析

1.IMyAidlInterface

刪除其中的內部類單純看這個接口比較簡單:

    public interface IMyAidlInterface extends android.os.IInterface {
        public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, java.lang.String aString) throws android.os.RemoteException;
        public com.czy.server.People getPeople() throws android.os.RemoteException;
        public void addPeople(com.czy.server.People people) throws android.os.RemoteException;
    }

這是一個繼承了IInterface的接口,裏面定義了進行通信的三個方法,這個接口沒有什麼實際的意義,主要是Stub和Proxy都實現它。

2.IMyAidlInterface.Stub

同樣刪除他的內部類Proxy來看他的代碼:

public static abstract class Stub extends android.os.Binder implements com.czy.server.IMyAidlInterface {
        private static final java.lang.String DESCRIPTOR = "com.czy.server.IMyAidlInterface";

        /**
         * Construct the stub at attach it to the interface.
         */
        public Stub() {
            this.attachInterface(this, DESCRIPTOR);
        }

        /**
         * Cast an IBinder object into an com.czy.server.IMyAidlInterface interface,
         * generating a proxy if needed.
         */
        public static com.czy.server.IMyAidlInterface asInterface(android.os.IBinder obj) {
            if ((obj == null)) {
                return null;
            }
            android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
            if (((iin != null) && (iin instanceof com.czy.server.IMyAidlInterface))) {
                return ((com.czy.server.IMyAidlInterface) iin);
            }
            return new com.czy.server.IMyAidlInterface.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_basicTypes: {
                    data.enforceInterface(descriptor);
                    int _arg0;
                    _arg0 = data.readInt();
                    long _arg1;
                    _arg1 = data.readLong();
                    boolean _arg2;
                    _arg2 = (0 != data.readInt());
                    float _arg3;
                    _arg3 = data.readFloat();
                    double _arg4;
                    _arg4 = data.readDouble();
                    java.lang.String _arg5;
                    _arg5 = data.readString();
                    this.basicTypes(_arg0, _arg1, _arg2, _arg3, _arg4, _arg5);
                    reply.writeNoException();
                    return true;
                }
                case TRANSACTION_getPeople: {
                    data.enforceInterface(descriptor);
                    com.czy.server.People _result = this.getPeople();
                    reply.writeNoException();
                    if ((_result != null)) {
                        reply.writeInt(1);
                        _result.writeToParcel(reply, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
                    } else {
                        reply.writeInt(0);
                    }
                    return true;
                }
                case TRANSACTION_addPeople: {
                    data.enforceInterface(descriptor);
                    com.czy.server.People _arg0;
                    if ((0 != data.readInt())) {
                        _arg0 = com.czy.server.People.CREATOR.createFromParcel(data);
                    } else {
                        _arg0 = null;
                    }
                    this.addPeople(_arg0);
                    reply.writeNoException();
                    return true;
                }
                default: {
                    return super.onTransact(code, data, reply, flags);
                }
            }
        }

        static final int TRANSACTION_basicTypes = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
        static final int TRANSACTION_getPeople = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
        static final int TRANSACTION_addPeople = (android.os.IBinder.FIRST_CALL_TRANSACTION + 2);

        public static boolean setDefaultImpl(com.czy.server.IMyAidlInterface impl) {
            if (Stub.Proxy.sDefaultImpl == null && impl != null) {
                Stub.Proxy.sDefaultImpl = impl;
                return true;
            }
            return false;
        }

        public static com.czy.server.IMyAidlInterface getDefaultImpl() {
            return Stub.Proxy.sDefaultImpl;
        }
    }

Stub繼承了Binder並實現了IMyAidlInterface,我們來一個個分析他的方法:
Stub()
首先他的構造函數調用了父類的attachInterface方法,並將本身和Stub的唯一標識DESCRIPTOR傳遞過,看一下這個方法:

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

只是將傳遞的參數保存起來,兩個參數後面會用到。

asInterface
不知道大家還記不記得這是在連接遠程服務之後將Binder對象轉化爲IMyAidlInterface接口類型的方法:

    private ServiceConnection serviceConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            myAidlInterface = IMyAidlInterface.Stub.asInterface(service);
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {

        }
    };

看一下這個方法的具體內容:

    public static com.czy.server.IMyAidlInterface asInterface(android.os.IBinder obj) {
        if ((obj == null)) {
            return null;
        }
        android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
        if (((iin != null) && (iin instanceof com.czy.server.IMyAidlInterface))) {
            return ((com.czy.server.IMyAidlInterface) iin);
        }
        return new com.czy.server.IMyAidlInterface.Stub.Proxy(obj);
    }

這裏根據參數不同會有兩種情況,如果服務端和客戶端在同一個進程就會返回iin,如果在不同進程就會new一個Proxy返回。
那麼怎麼判斷在不在一個進程呢,這就看queryLocalInterface方法了:

    public @Nullable IInterface queryLocalInterface(@NonNull String descriptor) {
        if (mDescriptor != null && mDescriptor.equals(descriptor)) {
            return mOwner;
        }
        return null;
    }

這裏用到了mDescriptor,還記得Stub的構造函數嗎,這是DESCRIPTOR的值,這裏就是判斷是不是同一個Stub,是就返回自己。
通過這個判斷我們可以知道IMyAidlInterface.Stub.asInterface(service)中的service和IMyAidlInterface.Stub是不是一個類,這只是一個類型判斷,但是這也不能區分在不在一個進程呀,後面還有一個判斷

(iin instanceof com.czy.server.IMyAidlInterface)

這還是類型判斷,確保轉換的對象是正確的,看來一開始的思路錯了,不賣關子了,其實同一個進程和不同進程傳遞中asInterface(android.os.IBinder obj)傳遞的參數是不一樣的,同一個進程是服務端返回的binder(IMyAidlInterface.Stub binder = new IMyAidlInterface.Stub()),而不同進程是BinderProxy,這是爲什麼暫時不說,BinderProxy和Binder一樣實現了IBinder接口,看一下他的queryLocalInterface方法

public IInterface queryLocalInterface(String descriptor) {
        return null;
    }

這裏是百分百返回null,所以asInterface最後也就返回了Proxy。

asBinder

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

返回自己沒什麼說的。

TRANSACTION
Stub定義了很多TRANSACTION開頭的常量:

    static final int TRANSACTION_basicTypes = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
    static final int TRANSACTION_getPeople = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
    static final int TRANSACTION_addPeople = (android.os.IBinder.FIRST_CALL_TRANSACTION + 2);

這個是用來在不同進程間標識一個方法的方式,跨進程的方法並不能直接調用,所以服務端收到消息後知道你調用那個方法,就是通過這個來標識的。

onTransact
到了最重要的方法了,這裏是調用服務端方法並返回的地方:

@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_basicTypes: {
                data.enforceInterface(descriptor);
                int _arg0;
                _arg0 = data.readInt();
                long _arg1;
                _arg1 = data.readLong();
                boolean _arg2;
                _arg2 = (0 != data.readInt());
                float _arg3;
                _arg3 = data.readFloat();
                double _arg4;
                _arg4 = data.readDouble();
                java.lang.String _arg5;
                _arg5 = data.readString();
                this.basicTypes(_arg0, _arg1, _arg2, _arg3, _arg4, _arg5);
                reply.writeNoException();
                return true;
            }
            case TRANSACTION_getPeople: {
                data.enforceInterface(descriptor);
                //調用自己的getPeople方法
                com.czy.server.People _result = this.getPeople();
                reply.writeNoException();
                if ((_result != null)) {
                    reply.writeInt(1);
                    //將返回值寫入reply中
                    _result.writeToParcel(reply, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
                } else {
                    reply.writeInt(0);
                }
                return true;
            }
            case TRANSACTION_addPeople: {
                data.enforceInterface(descriptor);
                com.czy.server.People _arg0;
                if ((0 != data.readInt())) {
                    //取出data中的參數
                    _arg0 = com.czy.server.People.CREATOR.createFromParcel(data);
                } else {
                    _arg0 = null;
                }
                //調用自己的addPeople方法
                this.addPeople(_arg0);
                reply.writeNoException();
                return true;
            }
            default: {
                return super.onTransact(code, data, reply, flags);
            }
        }
    }

首先通過code也就是TRANSACTION判斷調用的那一個方法,比如TRANSACTION_getPeople,先是調用了自己的getPeople方法,也就是MyService中的getPeople方法,然後向reply中寫入返回值。
如果是有參數的方法,比如TRANSACTION_addPeople,會從data中取出參數,然後調用自己的addPeople方法並把參數傳入。
不知道你注意到了沒有,上面的取出參數和寫入返回值就是對象的序列化和反序列化。

3.IMyAidlInterface.Stub.Proxy

在不同的進程中asInterface會返回Proxy,那麼Proxy到底做了什麼呢?

 private static class Proxy implements com.czy.server.IMyAidlInterface {
        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 basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, java.lang.String aString) 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(anInt);
                _data.writeLong(aLong);
                _data.writeInt(((aBoolean) ? (1) : (0)));
                _data.writeFloat(aFloat);
                _data.writeDouble(aDouble);
                _data.writeString(aString);
                boolean _status = mRemote.transact(Stub.TRANSACTION_basicTypes, _data, _reply, 0);
                if (!_status && getDefaultImpl() != null) {
                    getDefaultImpl().basicTypes(anInt, aLong, aBoolean, aFloat, aDouble, aString);
                    return;
                }
                _reply.readException();
            } finally {
                _reply.recycle();
                _data.recycle();
            }
        }

        @Override
        public com.czy.server.People getPeople() throws android.os.RemoteException {
            android.os.Parcel _data = android.os.Parcel.obtain();
            android.os.Parcel _reply = android.os.Parcel.obtain();
            com.czy.server.People _result;
            try {
                _data.writeInterfaceToken(DESCRIPTOR);
                boolean _status = mRemote.transact(Stub.TRANSACTION_getPeople, _data, _reply, 0);
                if (!_status && getDefaultImpl() != null) {
                    return getDefaultImpl().getPeople();
                }
                _reply.readException();
                if ((0 != _reply.readInt())) {
                    _result = com.czy.server.People.CREATOR.createFromParcel(_reply);
                } else {
                    _result = null;
                }
            } finally {
                _reply.recycle();
                _data.recycle();
            }
            return _result;
        }

        @Override
        public void addPeople(com.czy.server.People people) throws android.os.RemoteException {
            android.os.Parcel _data = android.os.Parcel.obtain();
            android.os.Parcel _reply = android.os.Parcel.obtain();
            try {
                _data.writeInterfaceToken(DESCRIPTOR);
                if ((people != null)) {
                    _data.writeInt(1);
                    people.writeToParcel(_data, 0);
                } else {
                    _data.writeInt(0);
                }
                boolean _status = mRemote.transact(Stub.TRANSACTION_addPeople, _data, _reply, 0);
                if (!_status && getDefaultImpl() != null) {
                    getDefaultImpl().addPeople(people);
                    return;
                }
                _reply.readException();
            } finally {
                _reply.recycle();
                _data.recycle();
            }
        }

        public static com.czy.server.IMyAidlInterface sDefaultImpl;
    }

Proxy也實現了IMyAidlInterface ,既然asInterface返回的是Proxy,那麼調用的getPeople和addPeople就是這裏面的方法了。
實際上Proxy裏也就只有這些方法。

getPeople

  @Override
    public com.czy.server.People getPeople() throws android.os.RemoteException {
        //初始化參數Parcel 
        android.os.Parcel _data = android.os.Parcel.obtain();
        //初始化返回值Parcel 
        android.os.Parcel _reply = android.os.Parcel.obtain();
        com.czy.server.People _result;
        try {
            _data.writeInterfaceToken(DESCRIPTOR);
            //遠程調用方法
            boolean _status = mRemote.transact(Stub.TRANSACTION_getPeople, _data, _reply, 0);
            if (!_status && getDefaultImpl() != null) {
                return getDefaultImpl().getPeople();
            }
            _reply.readException();
            if ((0 != _reply.readInt())) {
                //獲取返回值對象
                _result = com.czy.server.People.CREATOR.createFromParcel(_reply);
            } else {
                _result = null;
            }
        } finally {
            _reply.recycle();
            _data.recycle();
        }
        return _result;
    }

首先初始化了參數和返回值Parcel,由於沒有參數所以_data中並沒有值,然後就去調用transact方法遠程調用getPeople,調用完成之後將_reply中的返回值反序列化,最後將反序列化後的返回值返回給調用方。

addPeople
和getPeople類似,只是沒有返回值就不看了。

到這裏整個IMyAidlInterface.java就講完了,Binder的應用層也就講完了,在往下就要牽扯到framework層了,基本上理解上面講的那麼多就夠日常使用了。爲了驗證你已經理解了我們還要做一件事情,就是把IMyAidlInterface.java這個文件拆分(其實上面分析的時候我已經把他拆開了),我們看到ActivityManageService並沒有Stub、Proxy這些就是因爲他沒有放到一起,而且Stub、Proxy這些名字也是可以隨意改的,我就不把過程寫出來了,直接把已經分離的代碼貼出來。

代碼分離

在這裏插入圖片描述

1.IMyAidlInterface

public interface IMyAidlInterface extends android.os.IInterface {
    static final java.lang.String DESCRIPTOR = "com.czy.server.IMyAidlInterface";

    static final int TRANSACTION_basicTypes = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
    static final int TRANSACTION_getPeople = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
    static final int TRANSACTION_addPeople = (android.os.IBinder.FIRST_CALL_TRANSACTION + 2);

    public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, java.lang.String aString) throws android.os.RemoteException;

    public com.czy.server.People getPeople() throws android.os.RemoteException;

    public void addPeople(com.czy.server.People people) throws android.os.RemoteException;
}

2.IMyAidlInterfaceStubImpl

public abstract class IMyAidlInterfaceStubImpl extends android.os.Binder implements com.czy.server.IMyAidlInterface {

    /**
     * Construct the stub at attach it to the interface.
     */
    public IMyAidlInterfaceStubImpl() {
        this.attachInterface(this, DESCRIPTOR);
    }

    /**
     * Cast an IBinder object into an com.czy.server.IMyAidlInterface interface,
     * generating a proxy if needed.
     */
    public static com.czy.server.IMyAidlInterface asInterface(android.os.IBinder obj) {
        if ((obj == null)) {
            return null;
        }
        android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
        if (((iin != null) && (iin instanceof com.czy.server.IMyAidlInterface))) {
            return ((com.czy.server.IMyAidlInterface) iin);
        }
        return new IMyAidlInterfaceProxyImpl(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_basicTypes: {
                data.enforceInterface(descriptor);
                int _arg0;
                _arg0 = data.readInt();
                long _arg1;
                _arg1 = data.readLong();
                boolean _arg2;
                _arg2 = (0 != data.readInt());
                float _arg3;
                _arg3 = data.readFloat();
                double _arg4;
                _arg4 = data.readDouble();
                java.lang.String _arg5;
                _arg5 = data.readString();
                this.basicTypes(_arg0, _arg1, _arg2, _arg3, _arg4, _arg5);
                reply.writeNoException();
                return true;
            }
            case TRANSACTION_getPeople: {
                data.enforceInterface(descriptor);
                com.czy.server.People _result = this.getPeople();
                reply.writeNoException();
                if ((_result != null)) {
                    reply.writeInt(1);
                    _result.writeToParcel(reply, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
                } else {
                    reply.writeInt(0);
                }
                return true;
            }
            case TRANSACTION_addPeople: {
                data.enforceInterface(descriptor);
                com.czy.server.People _arg0;
                if ((0 != data.readInt())) {
                    _arg0 = com.czy.server.People.CREATOR.createFromParcel(data);
                } else {
                    _arg0 = null;
                }
                this.addPeople(_arg0);
                reply.writeNoException();
                return true;
            }
            default: {
                return super.onTransact(code, data, reply, flags);
            }
        }
    }

    public static boolean setDefaultImpl(com.czy.server.IMyAidlInterface impl) {
        if (IMyAidlInterfaceProxyImpl.sDefaultImpl == null && impl != null) {
            IMyAidlInterfaceProxyImpl.sDefaultImpl = impl;
            return true;
        }
        return false;
    }

    public static com.czy.server.IMyAidlInterface getDefaultImpl() {
        return IMyAidlInterfaceProxyImpl.sDefaultImpl;
    }
}

3.IMyAidlInterfaceProxyImpl

public class IMyAidlInterfaceProxyImpl implements com.czy.server.IMyAidlInterface {
    private android.os.IBinder mRemote;

    IMyAidlInterfaceProxyImpl(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 basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, java.lang.String aString) 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(anInt);
            _data.writeLong(aLong);
            _data.writeInt(((aBoolean) ? (1) : (0)));
            _data.writeFloat(aFloat);
            _data.writeDouble(aDouble);
            _data.writeString(aString);
            boolean _status = mRemote.transact(TRANSACTION_basicTypes, _data, _reply, 0);
            if (!_status && IMyAidlInterfaceStubImpl.getDefaultImpl() != null) {
                IMyAidlInterfaceStubImpl.getDefaultImpl().basicTypes(anInt, aLong, aBoolean, aFloat, aDouble, aString);
                return;
            }
            _reply.readException();
        } finally {
            _reply.recycle();
            _data.recycle();
        }
    }

    @Override
    public com.czy.server.People getPeople() throws android.os.RemoteException {
        android.os.Parcel _data = android.os.Parcel.obtain();
        android.os.Parcel _reply = android.os.Parcel.obtain();
        com.czy.server.People _result;
        try {
            _data.writeInterfaceToken(DESCRIPTOR);
            boolean _status = mRemote.transact(TRANSACTION_getPeople, _data, _reply, 0);
            if (!_status && IMyAidlInterfaceStubImpl.getDefaultImpl() != null) {
                return IMyAidlInterfaceStubImpl.getDefaultImpl().getPeople();
            }
            _reply.readException();
            if ((0 != _reply.readInt())) {
                _result = com.czy.server.People.CREATOR.createFromParcel(_reply);
            } else {
                _result = null;
            }
        } finally {
            _reply.recycle();
            _data.recycle();
        }
        return _result;
    }

    @Override
    public void addPeople(com.czy.server.People people) throws android.os.RemoteException {
        android.os.Parcel _data = android.os.Parcel.obtain();
        android.os.Parcel _reply = android.os.Parcel.obtain();
        try {
            _data.writeInterfaceToken(DESCRIPTOR);
            if ((people != null)) {
                _data.writeInt(1);
                people.writeToParcel(_data, 0);
            } else {
                _data.writeInt(0);
            }
            boolean _status = mRemote.transact(TRANSACTION_addPeople, _data, _reply, 0);
            if (!_status && IMyAidlInterfaceStubImpl.getDefaultImpl() != null) {
                IMyAidlInterfaceStubImpl.getDefaultImpl().addPeople(people);
                return;
            }
            _reply.readException();
        } finally {
            _reply.recycle();
            _data.recycle();
        }
    }

    public static com.czy.server.IMyAidlInterface sDefaultImpl;
}

最後不要忘了把AIDL文件夾刪掉。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章