0%

IPC 机制(五):Binder 连接池

1. 最常用的进程间通信方式

  • AIDL 是最常用的 IPC 方式,是日常开发中涉及进程间通信时的首选

2. 典型的 AIDL 的使用流程

  1. 创建一个 Service 和一个 AIDL 接口
  2. 创建一个类继承 AIDL 接口中的 Stub 类并实现 Stub 中的抽象方法,在 Service 的 onBind() 方法中返回这个类的对象
  3. 客户端绑定服务端 Service,建立连接后即可访问远程服务端方法

3. 多个业务模块都需要使用 AIDL 的场景下的工作机制

  • 客户端

    • 每个业务模块创建自己的 AIDL 接口并实现此接口
    • 此时不同业务模块之间不能耦合,所有实现细节要单独开来
    • 向服务端提供自己的唯一标识和其对应的 Binder 对象
  • 服务端

    • 只需要一个 Service 即可,服务端提供一个 queryBinder 接口
    • 这个接口能够根据业务模块的特征来返回相应的 Binder 对象给它们
    • 不同的业务模块拿到所需的 Binder 对象后就可以进行远程方法调用

4. Binder 连接池的主要作用

  • 将每个业务模块的 Binder 请求统一转发到远程 Service 中去执行
  • 避免了重复创建 Service 的过程(Service 是四大组件之一,本身就是一种系统资源),可以极大提高 AIDL 的开发效率

5. Binder 连接池的工作原理

Binder 连接池的工作原理

6. Binder 连接池的代码实现 Demo

  • 提供两个 AIDL 接口,模拟多个业务模块都要使用 AIDL 的场景

    1
    2
    3
    4
    5
    // ISecurityCenter 接口提供加解密功能
    interface ISecurityCerter {
    String encrypt(String content);
    String decrypt(String password);
    }
    1
    2
    3
    4
    // ICompute 接口提供计算加法的功能
    interface ICompute {
    int add(int a, int b);
    }
  • 上面两个业务模块 AIDL 接口的实现

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    public class SecurityCenterImpl extends ISecurityCenter.Stub {
    private static final char SECRET_CODE = '^';

    @Override
    public String encrypt(String content) throws RemoteException {
    char[] chars = content.toCharArray();
    for (int i = 0; i < chars.length; i++) {
    chars[i] ^= SECRET_CODE;
    }
    return new String(chars);
    }

    @Override
    public String decrypt(String password) throws RemoteException {
    return encrypt(password);
    }
    }
    1
    2
    3
    4
    5
    6
    public class ComputeImpl extends ICompute.Stub {
    @Override
    public int add() throws RemoteException {
    return a + b;
    }
    }
  • 为 Binder 连接池创建 AIDL 接口 IBinderPool.aidl

    1
    2
    3
    4
    5
    6
    7
    /**
    * @Param binderCode, the unique token of specific Binder<br/>
    * @return specific Binder who's token is binderCode.
    */
    interface IBinderPool {
    IBinder queryBinder(int binderCode);
    }
  • 为 Binder 连接池创建远程 Service 并实现 IBinderPool

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    public class BinderPoolService extends Service {
    private static final String TAG = "BinderPoolService";
    private Binder mBinderPool = new BinderPool.BinderPoolImpl();

    @Override
    public void onCreate() {
    super.onCreate();
    }

    @Override
    public IBinder onBind(Intent intent) {
    Log.d(TAG, "onBind");
    return mBinderPool;
    }

    @Override
    public void onDestroy() {
    super.onDestroy();
    }
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    @Override
    public IBinder queryBinder(int binderCode) throws RemoteException {
    IBinder binder = null;
    switch (binderCode) {
    case BINDER_SECURITY_CENTER:
    binder = new SecurityCenterImpl();
    break;
    case BINDER_COMPUTE:
    binder = new ComputeImpl();
    break;
    default:
    break;
    }
    return binder;
    }
  • Binder 连接池的具体实现

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    public class BinderPool {
    private static final String TAG = "BinderPool";
    public static final int BINDER_NONE = -1;
    public static final int BINDER_COMPUTE = 0;
    public static final int BINDER_SECURITY_CENTER = 1;

    private Context mContext;
    private IBinderPool mBinderPool;
    private static volatile BinderPool sInstance;
    private CountDownLatch mConnectBinderPoolCountDownLatch;

    private BinderPool(Context context) {
    mContext = context.getApplicationContext();
    connectBinderPoolService();
    }

    // BinderPool 是一个单例实现,因此在同一个进程中只会初始化一次
    public static BinderPool getInstance(Context context) {
    if (sInstance == null) {
    synchronized (BinderPool.class) {
    if (sInstance == null) {
    sInstance = new BinderPool(context);
    }
    }
    }
    return sInstance;
    }

    private synchronized void connectBinderPoolService() {
    mConnectBinderPoolCountDownLatch = new CountDownLatch(1);
    Intent service = new Intent(mContext, BinderPoolService.class);
    mContext.bindService(service, mBinderPoolConnection, Context.BIND_AUTO_CREATE);
    try {
    mConnectBinderPoolCountDownLatch.await();
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    }

    /**
    * query binder by binderCode from binder pool
    * @Param binderCode
    * the unique token of binder
    * @Param binder who's token is binderCode<br>
    * return null when not found or BinderPoolService died.
    */
    public IBinder queryBinder(int binderCode) {
    IBinder binder = null;
    try {
    if (mBinderPool != null) {
    binder = mBinderPool.queryBinder(binderCode);
    }
    } catch (RemoteException e) {
    e.printStackTrace();
    }
    return binder;
    }

    private ServiceConnection mBinderPoolConnection = new ServiceConnection() {
    @Override
    public void onServiceDisconnected(ComponentName name) {
    // ignored.
    }

    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
    mBinderPool = IBinderPool.Stub.asInterface(service);
    try {
    mBinderPool.asBinder().linkToDeath(mBinderPoolDeathRecipient, 0);
    } catch (RemoteException e) {
    e.printStackTrace();
    }
    // 通过 CountDownLatch 将 bindeService() 异步操作转换成同步操作
    mConnectBinderPoolCountDownLatch.countDown();
    }
    };

    // 断线重连
    private IBInder.DeathRecipient mBinderPoolDeathRecipient = new IBinder.DeathRecipient() {
    @Override
    public void binderDied() {
    Log.w(TAG, "binder died.");
    mBinderPool.asBinder().unlinkToDeath(mBinderPoolDeathRecipient, 0);
    mBinderPool = null;
    connectBinderPoolService();
    }
    };

    public static class BinderPoolImpl extends IBinderPool.Stub {
    public BinderPoolImpl() {
    super();
    }

    @Override
    public IBinder queryBinder(int binderCode) throws RemoteException {
    IBinder binder = null;
    switch (binderCode) {
    case BINDER_SECURITY_CENTER:
    binder = new SecurityCenterImpl();
    break;
    case BINDER_COMPUTE:
    binder = new ComputeImpl();
    break;
    default:
    break;
    }
    return binder;
    }
    }
    }
  • 验证效果,新创建一个 Activity,在线程中执行如下操作

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    private void doWork() {
    BinderPool binderPool = BinderPool.getInstance(BinderPoolActivity.this);
    IBinder securityBinder = binderPool.queryBinder(BinderPool.BINDER_SECURITY_CENTER);
    mSecurityCenter = (ISecurityCenter) SecurityCenterImpl.asInterface(securityBinder);
    Log.d(TAG, "visit ISecurityCenter");
    String msg = "Hello world-Android";
    System.out.println("content:" + msg);
    try {
    String password = mSecurityCenter.encrypt(msg);
    System.out.println("encrypt:" + password);
    System.out.println("decrypt:" + mSecurityCenter.decrypt(password));
    } catch (RemoteException e) {
    e.printStackTrace();
    }

    Log.d(TAG, "visit ICompute");
    IBinder computeBinder = binderPool.queryBinder(BinderPool.BINDER_COMPUTE);
    try {
    System.out.println("3+5=" + mCompute.add(3, 5));
    } catch (RemoteException e) {
    e.printStackTrace();
    }
    }
-------------------- 本文结束感谢您的阅读 --------------------