Android Binder 原理解析

Android Binder 原理解析

  • 一.跨进程通信
    • 1.进程隔离
    • 2.用户空间/内核空间
    • 3.系统调用/内核态/用户态
    • 4.内核模块/驱动
  • 二.为何使用Binder
  • 三.Binder通信原理
  • 四.Binder实现
    • 1.IBinder/IInterface
    • 2.Binder/BinderProxy
      • (1)Binder
      • (2)BinderProxy
    • 3.AIDL/Stub/Proxy
      • (1)AIDL
      • (2)Stub
        • i.attachInterface()
        • ii.asInterface(IBinder)
        • iii.asBinder()
        • iv.onTransact()
      • (3)Proxy
        • i.asBinder()
        • ii.功能接口方法
  • 五.总结

一.跨进程通信

跨进程通信(IPC)是指,不同进程间不能互相直接访问,那么操作系统是如何做到的呢?

1.进程隔离

进程隔离是操作系统为了保护进程之间不互相干扰而设计的,避免进程A写入进程B的情况发生,其实现使用了虚拟地址空间,两个进程虚拟地址不同,就可以防止A进程写入数据岛B进程。

也就是说,操作系统的不同进程之间,数据不共享,在每个进程看来,自己都独享了整个系统空间,完全不知道其他进程的存在,因此一个进程想要与另一个进程进行通信,需要某种系统机制才能完成。

2.用户空间/内核空间

Linux Kernel是操作系统的核心,独立于普通的应用程序,可以访问受保护的内存空间,也有访问底层硬件设备的所有权限。

对于Kernel这么一个高安全级别的东西,显然是不容许其它的应用程序随便调用或访问的,所以需要对Kernel提供一定的保护机制,这个保护机制用来告诉那些应用程序,你只可以访问某些许可的资源,不许可的资源是不能被访问的,于是操作系统就把Kernel和上层的应用程序抽像的隔离开,分别称之为Kernel Space和User Space,即内核空间和用户空间。

3.系统调用/内核态/用户态

虽然从逻辑上抽离出用户空间和内核空间,但是不可避免的是,总有那么一些用户空间需要访问内核的资源:比如应用程序访问文件、网络是很常见的事情,怎么办呢?

用户空间访问内核空间的唯一方式就是系统调用,通过这个统一入口,所有的资源访问都是在内核的控制下执行,以免导致用户程序对系统资源的越权访问,从而保障了系统的安全和稳定。

当一个进程执行系统调用,陷入内核代码中执行时,我们就称进程处于内核态,此时处理器处于特权级最高的内核代码中执行。当进程在执行用户自己的代码时,则称其处于用户态,此时处理器在特权级最低的用户代码中运行。处理器在特权等级高的时候才能执行那些特权CPU指令。

4.内核模块/驱动

通过系统调用,用户空间可以访问内核空间,那么如果一个用户空间想与另外一个用户空间进行通信怎么办呢?

很自然想到的是让操作系统内核添加支持,传统的Linux通信机制,比如Socket、管道等都是内核支持的,但是Binder并不是Linux内核的一部分,那它是怎么做到访问内核空间的呢?

Linux的动态可加载内核模块机制解决了这个问题:模块是具有独立功能的程序,它可以被单独编译,但不能独立运行,它在运行时被链接到内核作为内核的一部分运行在内核空间。这样,Android系统可以通过添加一个运行在内核空间的内核模块,用户进程之间通过这个模块作为桥梁,就可以完成通信了。

在Android系统中,这个运行在内核空间,负责各个用户进程之间通信的内核模块叫做Binder驱动(驱动就是操作硬件的接口)。
Android Binder 原理解析_第1张图片

二.为何使用Binder

Android使用的Linux系统内核,拥有着非常多的跨进程通信机制,比如管道、Socket等,为什么还需要单独搞一个Binder出来呢?主要有两点,性能和安全。

  1. Binder相对于传统的Socket方式,更加高效

  2. 比如Socket通信ip地址是客户端手动填入的,都可以进行伪造,而Binder机制从协议本身就支持对通信双方做身份校检,因而大大提升了安全性

三.Binder通信原理

下面我们来看看Binder是如何实现跨进程通信的。

Android系统中有许多的服务,比如Clipboard剪切板服务、ActivityManagerService服务、Vibrator针对服务等等,这些服务都是独立的进程,通常我们的客户端程序想要使用这些系统服务,会通过ServiceManager获取对应的接口对象进行访问,这时就需要跨进程通信,也就是需要借助Binder了,那Binder的通信流程是怎样的呢?

我们把每一个服务端称为Server端,访问他的客户端称为Client端,存储Server端信息的ServiceManager称为SM,假设Client端想要访问一个叫做Test的Server端,调用其A对象的add方法,其过程如下:

  1. 首先,当Server端进程初始化时,要向SM中注册自己的信息,类似于一个map的结构:我叫Test,有一个A对象,其中有一个add方法

  2. Client端想要访问时,先向SM端查询,是否有一个叫Test的Server端,我要请求里面的A对象,此时是有的,并要将"A对象"返回

  3. 上面说过,进程间通信时,数据会流经内核控件中的Binder驱动,此时驱动会对要传递的数据做一些手脚:如果是同一个进程要获取对象,则返回对象本身接口(不需要做跨进程通信);如果是不同进程要获取对象,则将返回一个和A对象看似一样的AProxy代理对象,这个代理对象也有add方法,其方法只是包装参数,回调给Binder驱动;此处Android的设计是使用代理模式。

  4. Client端拿到这个和A"一样"的AProxy对象,无需关注其是否为代理对象,照常调用add方法传递参数

  5. 如上所述,代理对象AProxy内部的add方法会直接交给Binder驱动处理

  6. Binder驱动拿到数据,并知道AProxy对应的真实Server端其实是Test的A对象(数据流经时Binder驱动会记录每个Server端及其对象的信息),于是乎,调用Test端的A对象的add方法,并将参数传递即可

  7. Test端将add方法的返回结果返回给Binder驱动,Binder驱动再返回给对应的Client端的调用处,即可完成一次跨进程通信

综上我们可以发现:

  • Binder机制使用代理模式,在Server端的对象是实际对象,其他各个进程端所持有的都是Proxy代理对象,由代理对象和Binder驱动完成数据传递

  • Proxy和实际对象具有同样的接口来实现数据通信,而不用关注其实现细节,因此让我们觉得Binder对象可以直接进行跨进程调用,其实是个数据中转的过程

初次之外,SM也是一个单独的进程,其与各个Server端的注册通信,也是通过同样的Binder跨进程机制完成的,Binder驱动也会对这个过程动手脚,也就是说,SM存放的各个Server端的对象,也都是Proxy代理对象。

一句话总结Binder机制就是:Client进程持有了Server端对象的代理;代理对象系统Binder驱动完成了跨进程通信。
Android Binder 原理解析_第2张图片

四.Binder实现

知道了Binder通信的原理和流程,下面我们来看看java层是如何支持Binder的吧。

1.IBinder/IInterface

Java层提供了IBinder、IInterface两个接口

  • IBinder:提供了Binder跨进程通信的基础方法,如transact()方法用来传递数据;如queryLocalInterface()方法用来获取实际功能对象

  • IInterface:提供了Binder通信对象的基本类型,我们Server端所提供的功能对象都要实现该接口,其asBinder()方法可以获取对应的Binder对象,也是可以用来传输Binder对象的类型标识

2.Binder/BinderProxy

(1)Binder

我们要实现一个Server端的提供服务的对象,首先要实现IBinder接口,对Server端来说,其提供服务的对象都是实际的Binder对象(也叫本地对象)而不是代理对象,而Binder类就是实现了部分Server端本地对象的处理逻辑的类,也就是说Binder类就是Server端本地对象的基类,我们来看看它实现了哪些处理逻辑:

public class Binder implements IBinder {
  private IInterface mOwner;
  private String mDescriptor;
  
  public void attachInterface(IInterface owner, String descriptor) {
    mOwner = owner;
    mDescriptor = descriptor;
  }
  
  @Override
  public IInterface queryLocalInterface(String descriptor) {
    if (mDescriptor.equals(descriptor)) {
      return mOwner;
    }
    return null;
  }
  
  @Override
  public final boolean transact(int code, Parcel data, Parcel reply,
                                int flags) throws RemoteException {
    if (data != null) {
      data.setDataPosition(0);
    }
    boolean r = onTransact(code, data, reply, flags);
    if (reply != null) {
      reply.setDataPosition(0);
    }
    return r;
  }
  
  protected boolean onTransact(int code, Parcel data, Parcel reply,
                               int flags) throws RemoteException {
    if (code == INTERFACE_TRANSACTION) {
      reply.writeString(getInterfaceDescriptor());
      return true;
    } else if (code == DUMP_TRANSACTION) {
      ...
      return true;
    } else if (code == SHELL_COMMAND_TRANSACTION) {
      ...
      return true;
    }
    return false;
  }
}
  1. queryLocalInterface()方法里面判断,如果descriptor,也就是IInterface(服务对象)的类名相同的话,就会返回owner,而这个owner和descriptor是服务对象初始化时通过attachInterface()方法传递进来的,也就是说,如果调用服务对象本身的该方法,拿到的就是实际的服务对象本身(本地对象),因为是同一个进程不需要进行跨进程通信

  2. transact()方法,将要传递的数据,包括参数以及要调用的方法(一个int协议值)通过序列化Parcel的方式,传递并调用onTransact()方法

  3. onTransact()方法就是Server端的Binder本地对象要处理的入口方法,其会根据方法的协议int值,决定调用本地对象的哪个方法

(2)BinderProxy

Server端的Binder对象有了,下面来看看Client端的Binder对象,上面说过了,Client端拿到的Binder对象是一个代理对象BinderProxy,由Binder驱动生成并返回,我们就来看看这个类是如何进行跨进程通信的。

final class BinderProxy implements IBinder {
  
  	@Override
		public IInterface queryLocalInterface(String descriptor) {
        return null;
    }

  	@Override
    public boolean transact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
        ...
        try {
            return transactNative(code, data, reply, flags);
        } finally {
            if (tracingEnabled) {
                Trace.traceEnd(Trace.TRACE_TAG_ALWAYS);
            }
        }
    }
  
    public native boolean transactNative(int code, Parcel data, Parcel reply,
              int flags) throws RemoteException;
}

我们可以看到,BinderProxy也实现了IBinder接口,说明其可以和Binder对象一样进行跨进程通信。

  1. queryLocalInterface()方法,这里由于是本地Binder对象的代理类,所以并不是本地对象,所以这里返回null,需要通过转换为IInterface对象拿到可以调用的接口对象(后面会说)

  2. transact()方法,直接将数据打包,调用一个native方法transactNative(),这个native方法其实就是将数据传入到了Binder驱动,由Binder驱动通过对应信息,调用对应的Server端

3.AIDL/Stub/Proxy

以上是java层提供的用于跨进程通信的接口,以及Server端本地Binder对象基类和Client端代理Binder对象的实现,那么我们具体的功能接口如何实现呢?

(1)AIDL

我们通常定义一组功能,是通过定义一个接口以及里面的一些方法来实现,Android也给我们这样一套功能来定义跨进程通信的功能接口,即AIDL(Android Interface Definition Language)文件,在该文件里,可以像定义普通接口一样定义我们的接口

// TestBinderAIDL.aidl
package com.binder;

// Declare any non-default types here with import statements
import com.binder.TestClientBinderAIDL;

interface TestBinderAIDL {

    void test(String text);

    void passIBinder(android.os.IBinder iBinder);

    void passClientBinder(TestClientBinderAIDL clientBinder);
}

我们可以发现,定义方式和普通接口定义方式基本一致,对于参数类型:

  1. 支持基本类型,包括String等

  2. 支持IBinder类型,因为IBinder是可以跨进程通信的

  3. 其他类型,只有可以被序列化(Parcel),或者可以转换为IBinder的IInterface类型才可,而且需要在头部import进来才可以使用

当定义完AIDL文件,进行编译后,会在AIDL文件所在包名,对应的源代码包中,生成我们想要的功能类
Android Binder 原理解析_第3张图片
类中包含了Server端Binder类基类Stub、客户端代理类Proxy以及相互转换等实现

public interface TestBinderAIDL extends android.os.IInterface {
    /**
     * Local-side IPC implementation stub class.
     */
    public static abstract class Stub extends android.os.Binder implements com.binder.TestBinderAIDL {
        private static final java.lang.String DESCRIPTOR = "com.binder.TestBinderAIDL";

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

        /**
         * Cast an IBinder object into an com.binder.TestBinderAIDL interface,
         * generating a proxy if needed.
         */
        public static com.binder.TestBinderAIDL asInterface(android.os.IBinder obj) {
            if ((obj == null)) {
                return null;
            }
            android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
            if (((iin != null) && (iin instanceof com.binder.TestBinderAIDL))) {
                return ((com.binder.TestBinderAIDL) iin);
            }
            return new com.binder.TestBinderAIDL.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 {
            switch (code) {
                case INTERFACE_TRANSACTION: {
                    reply.writeString(DESCRIPTOR);
                    return true;
                }
                case TRANSACTION_test: {
                    data.enforceInterface(DESCRIPTOR);
                    java.lang.String _arg0;
                    _arg0 = data.readString();
                    this.test(_arg0);
                    reply.writeNoException();
                    return true;
                }
                case TRANSACTION_passIBinder: {
                    data.enforceInterface(DESCRIPTOR);
                    android.os.IBinder _arg0;
                    _arg0 = data.readStrongBinder();
                    this.passIBinder(_arg0);
                    reply.writeNoException();
                    return true;
                }
                case TRANSACTION_passClientBinder: {
                    data.enforceInterface(DESCRIPTOR);
                    com.binder.TestClientBinderAIDL _arg0;
                    _arg0 = com.binder.TestClientBinderAIDL.Stub.asInterface(data.readStrongBinder());
                    this.passClientBinder(_arg0);
                    reply.writeNoException();
                    return true;
                }
            }
            return super.onTransact(code, data, reply, flags);
        }

        private static class Proxy implements com.binder.TestBinderAIDL {
            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 test(java.lang.String text) 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.writeString(text);
                    mRemote.transact(Stub.TRANSACTION_test, _data, _reply, 0);
                    _reply.readException();
                } finally {
                    _reply.recycle();
                    _data.recycle();
                }
            }

            @Override
            public void passIBinder(android.os.IBinder iBinder) 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.writeStrongBinder(iBinder);
                    mRemote.transact(Stub.TRANSACTION_passIBinder, _data, _reply, 0);
                    _reply.readException();
                } finally {
                    _reply.recycle();
                    _data.recycle();
                }
            }

            @Override
            public void passClientBinder(com.binder.TestClientBinderAIDL clientBinder) 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.writeStrongBinder((((clientBinder != null)) ? (clientBinder.asBinder()) : (null)));
                    mRemote.transact(Stub.TRANSACTION_passClientBinder, _data, _reply, 0);
                    _reply.readException();
                } finally {
                    _reply.recycle();
                    _data.recycle();
                }
            }
        }

        static final int TRANSACTION_test = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
        static final int TRANSACTION_passIBinder = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
        static final int TRANSACTION_passClientBinder = (android.os.IBinder.FIRST_CALL_TRANSACTION + 2);
    }

    public void test(java.lang.String text) throws android.os.RemoteException;

    public void passIBinder(android.os.IBinder iBinder) throws android.os.RemoteException;

    public void passClientBinder(com.binder.TestClientBinderAIDL clientBinder) throws android.os.RemoteException;
}

(2)Stub

我们先来看看Server端Binder类基类Stub类干了些什么

首先我们要注意到,我们的功能接口TestBinderAIDL类,实现了IInterface接口,也就是说该接口有了可以跨进程传递的标识,并且可以通过asBinder()方法转换为IBinder对象

public static abstract class Stub extends android.os.Binder implements com.binder.TestBinderAIDL {
        private static final java.lang.String DESCRIPTOR = "com.binder.TestBinderAIDL";
  
			  static final int TRANSACTION_test = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
        static final int TRANSACTION_passIBinder = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
        static final int TRANSACTION_passClientBinder = (android.os.IBinder.FIRST_CALL_TRANSACTION + 2);

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

        /**
         * Cast an IBinder object into an com.binder.TestBinderAIDL interface,
         * generating a proxy if needed.
         */
        public static com.binder.TestBinderAIDL asInterface(android.os.IBinder obj) {
            if ((obj == null)) {
                return null;
            }
            android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
            if (((iin != null) && (iin instanceof com.binder.TestBinderAIDL))) {
                return ((com.binder.TestBinderAIDL) iin);
            }
            return new com.binder.TestBinderAIDL.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 {
            switch (code) {
                case INTERFACE_TRANSACTION: {
                    reply.writeString(DESCRIPTOR);
                    return true;
                }
                case TRANSACTION_test: {
                    data.enforceInterface(DESCRIPTOR);
                    java.lang.String _arg0;
                    _arg0 = data.readString();
                    this.test(_arg0);
                    reply.writeNoException();
                    return true;
                }
                case TRANSACTION_passIBinder: {
                    data.enforceInterface(DESCRIPTOR);
                    android.os.IBinder _arg0;
                    _arg0 = data.readStrongBinder();
                    this.passIBinder(_arg0);
                    reply.writeNoException();
                    return true;
                }
                case TRANSACTION_passClientBinder: {
                    data.enforceInterface(DESCRIPTOR);
                    com.binder.TestClientBinderAIDL _arg0;
                    _arg0 = com.binder.TestClientBinderAIDL.Stub.asInterface(data.readStrongBinder());
                    this.passClientBinder(_arg0);
                    reply.writeNoException();
                    return true;
                }
            }
            return super.onTransact(code, data, reply, flags);
        }
}

i.attachInterface()

在构造方法时,调用了之前说过的attachInterface()方法,传入的IInterface是this本身,因为Stub本身就是一个IInterface功能接口;传入的descriptor就是我们定义的接口的完整类名。那么这有什么用呢?我们接着往下看

ii.asInterface(IBinder)

该方法是一个Stub类提供的静态方法,使用过AIDL的人应该都比较熟悉:在我们客户端中,以bindService()为例,会在ServiceConnection的onServiceConnected()方法中拿到Service传递来的IBinder对象,然后需要通过对应AIDL的Stub类的该静态方法转换,才能拿到具体的功能接口类进行调用,比如这里的功能接口就是com.binder.TestBinderAIDL类。

private val conn = object : ServiceConnection {
  override fun onServiceDisconnected(name: ComponentName?) {
    ...
  }
  override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
      remoteBinder = TestBinderAIDL.Stub.asInterface(service)
  }
}

再来看asInterface()方法,内部会直接调用IBinder对象queryLocalInterface()方法,传入的descriptor就是接口类名,这时,正如前面所说的,如果这个IBinder对象是Server端的本地Binder对象,那么这里会返回Binder本身,那么asInterface()返回的就是Binder本身,也就是所需要的功能接口;如果IBinder对象是代理对象BinderProxy,那么就会返回null,asInterface()方法返回的就是一个Proxy类对象(下面会讲),而Proxy类也实现了功能接口,所以在客户端看来,无需关注是什么类型,只要知道是功能接口类型,可以调用就行了,这也是代理模式带来的好处!

iii.asBinder()

Stub类由于是Server端的本地Binder对象,所以asBinder()方法返回this自身即可。

iv.onTransact()

该方法是Server端处理调用请求的入口,具体应该调用哪个方法,由协商好的int值来决定,比如这里有三个方法,分别就有三个不同的int值,客户端调用时会根据不同的方法传不同的值,而Server端在该方法里,只需要根据不同值调用不同方法即可,具体的方法实现,我们在Server端里创建一个子类实现接口方法即可,异常简单。

不过这里我们可以发现,数据的传递都是要通过Parcel序列化,包括基本类型、Parcelable类型、IBinder类型、IInterface类型(实际上是通过asBinder()转换为IBinder类型),所以上面说过,我们定义的AIDL接口都要满足这些条件。

(3)Proxy

下面再来看看Proxy类

首先要注意到,这个类也实现了功能接口(代理模式),也是一个IInterface类型

private static class Proxy implements com.binder.TestBinderAIDL {
  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 test(java.lang.String text) 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.writeString(text);
      mRemote.transact(Stub.TRANSACTION_test, _data, _reply, 0);
      _reply.readException();
    } finally {
      _reply.recycle();
      _data.recycle();
    }
  }

  @Override
  public void passIBinder(android.os.IBinder iBinder) 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.writeStrongBinder(iBinder);
      mRemote.transact(Stub.TRANSACTION_passIBinder, _data, _reply, 0);
      _reply.readException();
    } finally {
      _reply.recycle();
      _data.recycle();
    }
  }

  @Override
  public void passClientBinder(com.binder.TestClientBinderAIDL clientBinder) 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.writeStrongBinder((((clientBinder != null)) ? (clientBinder.asBinder()) : (null)));
      mRemote.transact(Stub.TRANSACTION_passClientBinder, _data, _reply, 0);
      _reply.readException();
    } finally {
      _reply.recycle();
      _data.recycle();
    }
  }
}

i.asBinder()

因为是代理模式,所以构造Porxy(asInterface()方法中)时,会传入一个真实的IBinder对象作为被代理对象,因此asBinder()方法返回的应该是这个被代理的IBinder对象,毕竟他才是真正的IBinder对象。

ii.功能接口方法

Proxy由于是代理类,所以也实现了功能接口相关的方法,而其具体实现,则是调用被代理对象的transact()方法,将参数传入即可,当然除了参数,要传入上述说的方法协议值,指定要调用哪个方法。

至此,AIDL的运作流程和使用已经分析完了
Android Binder 原理解析_第4张图片

五.总结

  1. Server端的Binder对象不需要跨进程通信,可以直接拿到(同一个进程)进行调用

  2. Client端拿到的Binder对象是BinderProxy对象,通过Proxy类转换为功能接口类型,调用方法最终回调到Server端Binder对象上的指定对象

  3. 定义的AIDL接口,参数类型要满足基本类型、可序列化类型或者IBinder(包括IInterface)类型即可

  4. 我们平时使用的ClipboardManager、SensorManager、ActivityManagerService等系统服务,其实都是上述这样跨进程通信的

你可能感兴趣的:(原理解析,android相关)