藉助 AIDL 理解 Android Binder 機制——AIDL 的使用和原理分析

在上一篇文章——藉助 AIDL 理解 Android Binder 機制——Binder 前因後果中咱們已經分析了使用 Binder 機制的緣由以及分析了 Binder 機制,本章咱們將繼續從 AIDL 的使用過程體驗 Binder 在應用層的使用和原理。java

AIDL 使用步驟

1.建立 UserManager.aidl 接口文件,聲明做爲 Server 端的遠程 Service 具備哪些能力

UserManager.aidl:android

package com.me.guanpj.binder;

import com.me.guanpj.binder.User;
// Declare any non-default types here with import statements

interface UserManager {
    void addUser(in User user);

    List<User> getUserList();
}
複製代碼

對於對象引用,還須要引入實體類git

User.aidl:github

// User.aidl
package com.me.guanpj.binder;

// Declare any non-default types here with import statements

parcelable User;
複製代碼

跨進程傳輸對象必須實現 Parcelable 接口bash

User.javamarkdown

public class User implements Parcelable {
    public int id;
    public String name;

    public User() {}

    public User(int id, String name) {
        this.id = id;
        this.name = name;
    }

    protected User(Parcel in) {
        id = in.readInt();
        name = in.readString();
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeInt(id);
        dest.writeString(name);
    }

    @Override
    public int describeContents() {
        return 0;
    }

    public static final Creator<User> CREATOR = new Creator<User>() {
        @Override
        public User createFromParcel(Parcel in) {
            return new User(in);
        }

        @Override
        public User[] newArray(int size) {
            return new User[size];
        }
    };
}
複製代碼

生成的 UserManager 類以下:ide

UserManager.java:函數

package com.me.guanpj.binder;
// Declare any non-default types here with import statements

public interface UserManager extends android.os.IInterface
{
    /** Local-side IPC implementation stub class. */
    public static abstract class Stub extends android.os.Binder implements com.me.guanpj.binder.UserManager
    {
        private static final java.lang.String DESCRIPTOR = "com.me.guanpj.binder.UserManager";
        /** Construct the stub at attach it to the interface. */
        public Stub()
        {
            this.attachInterface(this, DESCRIPTOR);
        }
        /**
         * Cast an IBinder object into an com.me.guanpj.binder.UserManager interface,
         * generating a proxy if needed.
         */
        public static com.me.guanpj.binder.UserManager asInterface(android.os.IBinder obj)
        {
            if ((obj==null)) {
                return null;
            }
            android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
            if (((iin!=null)&&(iin instanceof com.me.guanpj.binder.UserManager))) {
                return ((com.me.guanpj.binder.UserManager)iin);
            }
            return new com.me.guanpj.binder.UserManager.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_addUser:
                {
                    data.enforceInterface(descriptor);
                    com.me.guanpj.binder.User _arg0;
                    if ((0!=data.readInt())) {
                        _arg0 = com.me.guanpj.binder.User.CREATOR.createFromParcel(data);
                    }
                    else {
                        _arg0 = null;
                    }
                    this.addUser(_arg0);
                    reply.writeNoException();
                    return true;
                }
                case TRANSACTION_getUserList:
                {
                    data.enforceInterface(descriptor);
                    java.util.List<com.me.guanpj.binder.User> _result = this.getUserList();
                    reply.writeNoException();
                    reply.writeTypedList(_result);
                    return true;
                }
                default:
                {
                    return super.onTransact(code, data, reply, flags);
                }
            }
        }
        private static class Proxy implements com.me.guanpj.binder.UserManager
        {
            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;
            }
            @Override public void addUser(com.me.guanpj.binder.User user) 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 ((user!=null)) {
                        _data.writeInt(1);
                        user.writeToParcel(_data, 0);
                    }
                    else {
                        _data.writeInt(0);
                    }
                    mRemote.transact(Stub.TRANSACTION_addUser, _data, _reply, 0);
                    _reply.readException();
                }
                finally {
                    _reply.recycle();
                    _data.recycle();
                }
            }
            @Override public java.util.List<com.me.guanpj.binder.User> getUserList() throws android.os.RemoteException
            {
                android.os.Parcel _data = android.os.Parcel.obtain();
                android.os.Parcel _reply = android.os.Parcel.obtain();
                java.util.List<com.me.guanpj.binder.User> _result;
                try {
                    _data.writeInterfaceToken(DESCRIPTOR);
                    mRemote.transact(Stub.TRANSACTION_getUserList, _data, _reply, 0);
                    _reply.readException();
                    _result = _reply.createTypedArrayList(com.me.guanpj.binder.User.CREATOR);
                }
                finally {
                    _reply.recycle();
                    _data.recycle();
                }
                return _result;
            }
        }
        static final int TRANSACTION_addUser = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
        static final int TRANSACTION_getUserList = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
    }
    public void addUser(com.me.guanpj.binder.User user) throws android.os.RemoteException;
    public java.util.List<com.me.guanpj.binder.User> getUserList() throws android.os.RemoteException;
}
複製代碼

3.建立 Service,實現 UserManager.Stub 類並將該實現類的實例在 onBind 方法返回

MyService.java:oop

public class MyService extends Service {

    class UserManagerNative extends UserManager.Stub {

        List<User> users = new ArrayList<>();

        @Override
        public void addUser(User user) {
            Log.e("gpj", "進程:" + Utils.getProcessName(getApplicationContext())
                    + ",線程:" + Thread.currentThread().getName() + "————" + "Server 執行 addUser");
            users.add(user);
        }

        @Override
        public List<User> getUserList() {
            Log.e("gpj", "進程:" + Utils.getProcessName(getApplicationContext())
                    + ",線程:" + Thread.currentThread().getName() + "————" + "Server 執行 getUserList");
            return users;
        }
    }

    private UserManagerNative mUserManagerNative = new UserManagerNative();

    @Override
    public IBinder onBind(Intent intent) {
        Log.e("gpj", "進程:" + Utils.getProcessName(getApplicationContext())
                + ",線程:" + Thread.currentThread().getName() + "————" + "Server onBind");
        return mUserManagerNative;
    }
}
複製代碼

4.在做爲 Client 端的 Activity 中,綁定遠程 Service 並獲得 Server 的代理對象

5.經過 Server 代理對象,調用 Server 的具體方法

MainActivity.java:post

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    Button btnBind;
    Button btnAddUser;
    Button btnGetSize;
    TextView tvResult;
    IUserManager mUserManager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        btnBind = (Button) findViewById(R.id.btn_bind);
        btnAddUser = (Button) findViewById(R.id.btn_add_user);
        btnGetSize = (Button) findViewById(R.id.btn_get_size);

        btnBind.setOnClickListener(this);
        btnAddUser.setOnClickListener(this);
        btnGetSize.setOnClickListener(this);

        tvResult = (TextView) findViewById(R.id.txt_result);
    }

    @Override
    protected void onDestroy() {
        unbindService(mConn);
        super.onDestroy();
    }

    private ServiceConnection mConn = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            Log.e("gpj", "進程:" + Utils.getProcessName(getApplicationContext())
                    + ",線程:" + Thread.currentThread().getName() + "————" + "Client onServiceConnected");
            mUserManager = UserManagerImpl.asInterface(service);
            try {
                //註冊遠程服務死亡通知
                service.linkToDeath(mDeathRecipient, 0);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            mUserManager = null;
        }
    };

    private IBinder.DeathRecipient mDeathRecipient = new IBinder.DeathRecipient() {
        @Override
        public void binderDied() {
            if (mUserManager != null) {
                mUserManager.asBinder().unlinkToDeath(mDeathRecipient, 0);
                mUserManager = null;
                //從新綁定服務
                bindService();
            }
        }
    };

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.btn_bind:
                bindService();
                break;
            case R.id.btn_add_user:
                if (null != mUserManager) {
                    try {
                        Log.e("gpj", "線程:" + Thread.currentThread().getName() + "————" +"Client 調用 addUser");
                        mUserManager.addUser(new User(111, "gpj"));
                    } catch (RemoteException e) {
                        e.printStackTrace();
                    }
                } else {
                    Toast.makeText(MainActivity.this, "先綁定 Service 才能調用方法", Toast.LENGTH_LONG).show();
                }
                break;
            case R.id.btn_get_size:
                if (null != mUserManager) {
                    try {
                        Log.e("gpj", "線程:" + Thread.currentThread().getName() + "————" +"Client 調用 getUserList");
                        List<User> userList = mUserManager.getUserList();
                        tvResult.setText("getUserList size:" + userList.size());
                        Log.e("gpj", "線程:" + Thread.currentThread().getName() + "————" +"調用結果:" + userList.size());
                    } catch (RemoteException e) {
                        e.printStackTrace();
                    }
                } else {
                    Toast.makeText(MainActivity.this, "先綁定 Service 才能調用方法", Toast.LENGTH_LONG).show();
                }
                break;
            default:
        }
    }

    private void bindService() {
        Intent intent = new Intent();
        intent.setAction("com.me.guanpj.binder");
        intent.setComponent(new ComponentName("com.me.guanpj.binder", "com.me.guanpj.binder.MyService"));

        Log.e("gpj", "進程:" + Utils.getProcessName(getApplicationContext())
                + ",線程:" + Thread.currentThread().getName() + "————" + "開始綁定服務");
        bindService(intent, mConn, Context.BIND_AUTO_CREATE);
    }
}
複製代碼

AIDL 的實現過程

爲了便於理解,這裏用一個 Demo 來展現 AIDL 的實現過程:Activity 做爲 Client 與做爲 Server 端的遠程 Service 實現數據交互,在綁定遠程 Service 以後,點擊 AddUser 後 Service 會將 Client 端傳進來的 User 對象加入列表中,點擊 GetSize 後遠程 Service 將會把列表的長度返回給客戶端。建議在繼續閱讀以前先查看或者運行一下項目源碼

Demo

在項目中建立 UserManager.aidl 文件以後,系統會自動在 build 目錄生成一個與 UserManager.java 接口類,它繼承了 IInterface 接口,UserManager 接口只有一個靜態抽象類 Stub,Stub 繼承自 Binder 並實現了 UserManager 接口,Stub 裏面也有一個靜態內部類 Proxy,Proxy 也繼承了 UserManager(是否是有點亂,亂就對了,我也很亂)。

如此嵌套是爲了不有多個 .aidl 文件的時候自動生成這些類的類名不會重複,爲了提升代碼可讀性,咱們將生成的 UserManager 和 Stub 類 拆解並從新命名成了 IUserManager 類和 UserManagerImpl 類並在關鍵方法上添加了註釋或者 Log。

AIDL

IUserManager.java:

public interface IUserManager extends android.os.IInterface {
    //惟一性標識
    static final java.lang.String DESCRIPTOR = "com.me.guanpj.binder.IUserManager";

    //方法標識,用十六進制表示
    int TRANSACTION_addUser = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
    int TRANSACTION_getUserList = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);

    //Server 具備的能力
    void addUser(User user) throws android.os.RemoteException;
    List<User> getUserList() throws android.os.RemoteException;
}
複製代碼

UserManagerImpl.java:

public abstract class UserManagerImpl extends Binder implements IUserManager {
    /**
     * Construct the mLocalStub at attach it to the interface.
     */
    public UserManagerImpl() {
        this.attachInterface(this, DESCRIPTOR);
    }

    /**
     * 根據 Binder 本地對象或者代理對象返回 IUserManager 接口
     */
    public static IUserManager asInterface(android.os.IBinder obj) {
        if ((obj == null)) {
            return null;
        }
        //查找本地對象
        android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
        if (((iin != null) && (iin instanceof IUserManager))) {
            Log.e("gpj", "線程:" + Thread.currentThread().getName() + "————" + "返回本地對象");
            return ((IUserManager) iin);
        }
        Log.e("gpj", "線程:" + Thread.currentThread().getName() + "————" + "返回代理對象");
        return new UserManagerImpl.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 {
        switch (code) {
            case INTERFACE_TRANSACTION: {
                reply.writeString(DESCRIPTOR);
                return true;
            }
            case TRANSACTION_addUser: {
                Log.e("gpj", "線程:" + Thread.currentThread().getName() + "————" + "本地對象經過 Binder 執行 addUser");
                data.enforceInterface(DESCRIPTOR);
                User arg0;
                if ((0 != data.readInt())) {
                    //取出客戶端傳遞過來的數據
                    arg0 = User.CREATOR.createFromParcel(data);
                } else {
                    arg0 = null;
                }
                //調用 Binder 本地對象
                this.addUser(arg0);
                reply.writeNoException();
                return true;
            }
            case TRANSACTION_getUserList: {
                Log.e("gpj", "線程:" + Thread.currentThread().getName() + "————" + "本地對象經過 Binder 執行 getUserList");
                data.enforceInterface(DESCRIPTOR);
                //調用 Binder 本地對象
                List<User> result = this.getUserList();
                reply.writeNoException();
                //將結果返回給客戶端
                reply.writeTypedList(result);
                return true;
            }
            default:
                break;
        }
        return super.onTransact(code, data, reply, flags);
    }

    private static class Proxy implements IUserManager {
        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;
        }

        @Override
        public void addUser(User user) 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 (user != null) {
                   _data.writeInt(1);
                   user.writeToParcel(_data, 0);
               } else {
                   _data.writeInt(0);
               }
                Log.e("gpj", "線程:" + Thread.currentThread().getName() + "————" + "代理對象經過 Binder 調用 addUser");
                mRemote.transact(UserManagerImpl.TRANSACTION_addUser, _data, _reply, 0);
                _reply.readException();
            } finally {
                _reply.recycle();
                _data.recycle();
            }
        }

        @Override
        public List<User> getUserList() throws android.os.RemoteException {
            android.os.Parcel _data = android.os.Parcel.obtain();
            android.os.Parcel _reply = android.os.Parcel.obtain();
            List<User> _result;
            try {
                _data.writeInterfaceToken(DESCRIPTOR);
                Log.e("gpj", "線程:" + Thread.currentThread().getName() + "————" + "代理對象經過 Binder 調用 getUserList");
                mRemote.transact(UserManagerImpl.TRANSACTION_getUserList, _data, _reply, 0);
                _reply.readException();
                _result = _reply.createTypedArrayList(User.CREATOR);
            } finally {
                _reply.recycle();
                _data.recycle();
            }
            return _result;
        }
    }
}
複製代碼

再進行分析以前,先了解幾個概念:

  1. IInterface : 從註釋中的說明看出,聲明(自動生成或者手動建立)AIDL 性質的接口必須繼承這個接口,這個接口只有一個 IBinder asBinder() 方法,實現它的類表明它可以進程跨進程傳輸( Binder 本地對象)或者持有可以進程跨進程傳輸的對象的引用(Binder 代理對象)。
  2. IUserManager : 它一樣是一個接口,它繼承了 IInterface 類,並聲明瞭 Server 承諾給 Client 的能力
  3. IBinder : 它也是一個接口,實現這個接口的對象就具備了跨進程傳輸的能力,在跨進程數據流經驅動的時候,驅動會識別IBinder類型的數據,從而自動完成不一樣進程Binder本地對象以及Binder代理對象的轉換。
  4. Binder : 表明 Binder 本地對象,BinderProxy 類是它的內部類,是 Server 端 Binder 對象的本地代理,它們都繼承了 IBinder 接口,所以都能跨進程進行傳輸,Binder 驅動在跨進程傳輸的時候會將這兩個對象自動進行轉換。
  5. UserManagerImpl : 它繼承了 Binder 並實現了 IInterface 接口,說明它是 Server 端的 Binder 本地對象,並擁有 Server 承諾給 Client 的能力。

先從 MainActivity 中綁定服務後的回調方法着手:

private ServiceConnection mConn = new ServiceConnection() {
    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
        mUserManager = UserManagerImpl.asInterface(service);
        try {
            //註冊遠程服務死亡通知
            service.linkToDeath(mDeathRecipient, 0);
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onServiceDisconnected(ComponentName name) {
        mUserManager = null;
    }
};
複製代碼

onServiceConnected 的參數中,第一個是 Service 組件的名字,表示哪一個服務被啓動了,重點是類型爲 IBinder 的第二個參數,在 Service.java 中的 onBind 方法中,已經把 Server 端的本地對象 UserManagerNative 實例返回給 Binder 驅動了:

private UserManagerNative mUserManagerNative = new UserManagerNative();

@Override
public IBinder onBind(Intent intent) {
    return mUserManagerNative;
}
複製代碼

所以,當該服務被綁定的時候,Binder 驅動會爲根據該服務所在的進程決定 是返回本地對象仍是代理對象給客戶端,當 Service 與 MainActivity 位於同一個進程當中的時候,onServiceConnected 返回 Binder 本地對象——即 UserManagerNative 對象給客戶端;當 Service 運行在不一樣進程中的時候,返回的是 BinderProxy 對象。

接着,在將這個 IBinder 對象傳給 UserManagerImpl 的 asInterface 方法並返回 IUserManager 接口,asInterface 方法實現以下:

/**
 * 根據 Binder 本地對象或者代理對象返回 IUserManager 接口
*/
public static IUserManager asInterface(android.os.IBinder obj) {
    if ((obj == null)) {
        return null;
    }
    //查找本地對象
    android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
    if (((iin != null) && (iin instanceof IUserManager))) {
        return ((IUserManager) iin);
    }
    return new UserManagerImpl.Proxy(obj);
}
複製代碼

首先,會根據 DESCRIPTOR 調用 IBinder 對象的 queryLocalInterface 方法,那麼就得看 IBinder 的實現類怎麼處理這個方法了:

在 Binder 類中的實現:

public @Nullable IInterface queryLocalInterface(@NonNull String descriptor) {
    //判斷 mDescriptor 跟參數 DESCRIPTOR 相同,返回 mOwner
    if (mDescriptor != null && mDescriptor.equals(descriptor)) {
        return mOwner;
    }
    return null;
}
複製代碼

那麼這個 mOwner 和 mDescriptor 又是何時被賦值的呢?答案在 Binder 的子類 UserManagerImpl 的構造方法裏面,:

public UserManagerImpl() {
    //將 UserManagerImpl 和 DESCRIPTOR 注入到父類(Binder)
    this.attachInterface(this, DESCRIPTOR);
}
複製代碼

在 Binder$BinderProxy 類中的實現:

BinderProxy 並非 Binder 本地對象,而是 Binder 的本地代理,所以 queryLocalInterface 返回的是 null:

public IInterface queryLocalInterface(String descriptor) {
    return null;
}
複製代碼

綜上兩點能夠看出,若是 obj.queryLocalInterface(DESCRIPTOR) 方法存在返回值而且是 IUserManager 類型的對象,那麼它就是 Binder 本地對象,將它直接返回給 Client 調用;不然,使用 UserManagerImpl$Proxy 類將其進行包裝後再返回,Proxy 類也實現了 IUserManager 接口,所以,在 Client 眼中,它也具備 Server 承諾給 Client 的能力,那麼,通過包裝後的對象怎麼和 Server 進行交互呢?

首先,它會把 BinderProxy 對象保存下來:

Proxy(android.os.IBinder remote) {
    mRemote = remote;
}
複製代碼

而後,實現 IUserManager 的方法:

@Override
public void addUser(User user) 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 (user != null) {
            _data.writeInt(1);
            //將 user 對象的值寫入 _data
            user.writeToParcel(_data, 0);
        } else {
            _data.writeInt(0);
        }
        //經過 transact 跟 Server 交互
        mRemote.transact(UserManagerImpl.TRANSACTION_addUser, _data, _reply, 0);
        _reply.readException();
    } finally {
        _reply.recycle();
        _data.recycle();
    }
}

@Override
public List<User> getUserList() throws android.os.RemoteException {
    android.os.Parcel _data = android.os.Parcel.obtain();
    android.os.Parcel _reply = android.os.Parcel.obtain();
    List<User> _result;
    try {
        _data.writeInterfaceToken(DESCRIPTOR);
        //經過 transact 跟 Server 交互
        mRemote.transact(UserManagerImpl.TRANSACTION_getUserList, _data, _reply, 0);
        _reply.readException();
        //獲取 Server 的返回值並進程轉換
        _result = _reply.createTypedArrayList(User.CREATOR);
    } finally {
        _reply.recycle();
        _data.recycle();
    }
    return _result;
}
複製代碼

能夠看到,無論什麼方法,都是是將服務端的方法代號、處理過的參數和接收返回值的對象等經過 mRemote.transact 方法 Server 進行交互,mRemote 是 BinderProxy 類型,在 BinderProxy 類中,最終調用的是 transactNative 方法:

public native boolean transactNative(int code, Parcel data, Parcel reply, int flags) throws RemoteException;
複製代碼

它的最終實如今 Native 層進行,Binder 驅動會經過 ioctl 系統調用喚醒 Server 進程,並調用 Server 本地對象的 onTransact 函數:

@Override
public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException {
    switch (code) {
        case INTERFACE_TRANSACTION: {
            reply.writeString(DESCRIPTOR);
            return true;
        }
        case TRANSACTION_addUser: {
            data.enforceInterface(DESCRIPTOR);
            User arg0;
            if ((0 != data.readInt())) {
                //取出客戶端傳遞過來的數據
                arg0 = User.CREATOR.createFromParcel(data);
            } else {
                arg0 = null;
            }
            //調用 Binder 本地對象
            this.addUser(arg0);
            reply.writeNoException();
            return true;
        }
        case TRANSACTION_getUserList: {
            data.enforceInterface(DESCRIPTOR);
            //調用 Binder 本地對象
            List<User> result = this.getUserList();
            reply.writeNoException();
            //將結果返回給客戶端
            reply.writeTypedList(result);
            return true;
        }
        default:
            break;
    }
    return super.onTransact(code, data, reply, flags);
}
複製代碼

在 Server 進程中,onTransact 會根據 Client 傳過來的方法代號決定調用哪一個方法,獲得結果後又會經過 Binder 驅動返回給 Client。

總結

回溯到 onServiceConnected 回調方法,待服務鏈接成功後,Client 就須要跟 Server 進行交互了,若是 Server 跟 Client 在同一個進程中,Client 能夠直接調用 Server 的本地對象 ,當它們不在同一個進程中的時候,Binder 驅動會自動將 Server 的本地對象轉換成 BinderProxy 代理對象,通過一層包裝以後,返回一個新的代理對象給 Client。這樣,整個 IPC 的過程就完成了。

參考文章

寫給 Android 應用工程師的 Binder 原理剖析

Binder學習指南

文章中的代碼已經上傳至個人 Github,若是你對文章內容有疑問或者有不一樣的意見,歡迎留言,咱們一同探討。

相關文章
相關標籤/搜索