深入Android架构(从线程到AIDL)_03 IPC的IBinder接口

发布于:2025-02-11 ⋅ 阅读:(31) ⋅ 点赞:(0)

目录

4、 IPC的IBinder接口 -- 定义与实现

IBinder接口的定義

IBinder接口的實現類

Java层的Binder基类定义​编辑

Binder基类的主要函数

Java层的BinderProxy基类定义


4、 IPC的IBinder接口 -- 定义与实现

IBinder接口的定義
  • 大家都知道,当两个类都在同一个进程里执行时,两者之间的沟通,只要采取一般的函数调用(Function Call)就行了,既快速又方便。一旦两个类分别在不同的进程里执行时,两者之间的沟通,就不能采取一般的函数调用途径了。只好采取IPC沟通途径
  • Android框架的IPC沟通仰赖单一的IBinder接口。此时Client端调用IBinder接口的transact()函数,透过IPC机制而调用到远方(Remote)的onTransact()函数。
  • 在Android的源代码里, Java层的IBinder接口是定义于IBinder.java代码文档里。 此程序文件如下:
// IBinder.java
// .......
public interface IBinder {
    // ..........
    public boolean transact(int code, Parcel data, Parcel reply, int flags)
        throws RemoteException;
    // ...........
}
  • IBinder接口定义了一些函数,可以让Client程序可以进行跨进程的調用(当然也能支持同进程的短程調用)。其中,最主要的一个函数就是: transact()函数。于此,以图形来表达IBinder接口与transact()函数之间的关系。如下述的UML图:
IBinder接口的實現類
  • 基于这个IBinder.java定义档,我们就可以开发类别来实作(Implement)它,然后提供给其它App来調用了。在Android的框架里,也撰写了Binder基类和BinderProxy类别来实作 IBinder接口。

IBinder实作类之例: Binder和BinderProxy类

Java层的Binder基类定义
  • Binder基类的很重要目的是支持跨进程調用Service,也就是让远程的Client可以跨进程調用某个Service。
  • Binder基类定义于Binder.java档案里:
    // Binder.java
    // …….
    public class Binder implements IBinder {
        // ..........
        private int mObject;
        public Binder() {
            init();
            // ...........
        }
    
        public final boolean transact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
            // ................
            boolean r = onTransact(code, data, reply, flags);
            return r;
        }
    
        private boolean execTransact(int code, int dataObj, int replyObj, int flags) {
            Parcel data = Parcel.obtain(dataObj);
            Parcel reply = Parcel.obtain(replyObj);
            boolean res;
            res = onTransact(code, data, reply, flags);
            // ............
            return res;
        }
    
        protected boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
         }
    
        private native final void init();
    }

Binder基类的主要函数
  • transact()函数

        --- 用来实作IBinder的transact()函数接口。

  • execTransact()函数

        --- 其角色与transact()函数是相同的,只是这是用来让C/C++本地程序来調用的。

  • onTransact()函数

        --- 这是一个抽象函数,让应用子类来覆写(Override)的。上述的transact()和execTransact()                两者都是調用onTransact()函数来实现反向調用(IoC, Inversion of Control)的。

  • init()函数

        --- 这是一个本地(Native)函数,让JNI模块来实现这个函数。 Binder()构造函数(Constructor)                会調用这个init()本地函数。

UML图形表示

  • Binder就是EIT造形里的<E>
  • 这个IBinder接口是Binder(即<E>)提供给Client的接口,简称为<CI>。
  • onTransact()就是EIT造形里的<I>
  • 这是标准的EIT造形,其<I>是支持<基类/子类>之间IoC调用的接口。
  • Init()是EIT造形的另一种特殊接口,其支持<从Java到本地C>之间的调用接口。

  • 当Binder的子类别诞生对象时,会調用到Binder()构造函数。此时, Binder()会調用到init()本地函数。
Java层的BinderProxy基类定义

  • 这个BinderProxy类也定义在Binder.java档案里,如下:
// Binder.java
// ………
final class BinderProxy implements IBinder {
    private int mObject;
    // ..........
    BinderProxy() {
        // .........
    }

    public native boolean transact(int code, Parcel data, Parcel reply,int flags) throws RemoteException;
    private int mObject;
}
  • 当我们看到类别名称是 XXXProxy时,就自然会联想到它是摆在Client进程里,担任Service端的分身(Proxy)。
  • 由于跨进程沟通时,并不是从Java层直接沟通的,而是透过底层的Binder Driver驱动来沟通的,所以Client端的Java类别(如Activity)必须透过BinderProxy分身的IBinder接口,转而調用JNI本地模块来衔接到底层Binder Driver驱动服务,进而調用到正在另一个进程里执行的Service。
  • 当Client透过IBinder接口而調用到BinderProxy的transact()函数,就調用到其 JNI本地模块的transact()函数,就能进而衔接到底层Binder Driver驱动服务了。
  • 在上图里,从JNI本地模块拉了一条红色虚线,表示这并非直接的通信途径。也就是,
    实际上是透过底层Binder Driver驱动才調用到BBinder的IBinder接口。如下图:

网站公告

今日签到

点亮在社区的每一天
去签到