2.关于进程间通信(下):再说Binder

android系统进程间通信的底层原理就是Binder机制。
参考aidl文件生成的java代码,可以知道Binder机制涉及到两个重要的类。

1. IInterface接口

所有可以在Binder传输的接口都需要继承IInterface接口。

package android.os;

public interface IInterface {
    IBinder asBinder();
}

说明:
asBinder方法就是返回Binder对象;
aidl文件生成的java代码中,此方法返回的是Stub对象,Stub对象继承自Binder类。

比如自定义AIDL文件,生成的java代码结构,其实现了IInterface接口

package android.os;

public interface IAidlInterface extends android.os.IInterface
{
  /** Default implementation for IAidlInterface. */
  public static class Default implements com.ubtech.demoaidl.IAidlInterface
  {
  	...
  }

  /** Local-side IPC implementation stub class. */
  public static abstract class Stub extends android.os.Binder implements com.ubtech.demoaidl.IAidlInterface
  {
  	...
  	// 有跨进程才会用到Proxy
  	private static class Proxy implements com.ubtech.demoaidl.IAidlInterface
    {
	    private android.os.IBinder mRemote;
	    ...
    }
  }

  /**
   * Demonstrates some basic types that you can use as parameters
   * and return values in AIDL.
   */
  public int add(int i, int j) throws android.os.RemoteException;
  public void join(android.os.IBinder iBinder, java.lang.String name) throws android.os.RemoteException;
  public void leave() throws android.os.RemoteException;
  public void registerCallback(com.ubtech.demoaidl.INotifyCallback callback) throws android.os.RemoteException;
  public void unregisterCallback(com.ubtech.demoaidl.INotifyCallback callback) throws android.os.RemoteException;
  
}

2. Binder类 (IBinder接口的实现类)

在这里插入图片描述
Binder实现了IBinder接口,是IPC的核心对象。
AM与AMS,WM与WMS等都是通过Binder方式进行连接的;
当bindService的时候,service会返回一个包含了服务端业务调用的Binder对象。

public class Binder implements IBinder {
    public Binder() {
        throw new RuntimeException("Stub!");
    }

    public static final native int getCallingPid();

    public static final native int getCallingUid();

    @RecentlyNonNull
    public static final UserHandle getCallingUserHandle() {
        throw new RuntimeException("Stub!");
    }

    public static final native long clearCallingIdentity();

    public static final native void restoreCallingIdentity(long var0);

    public static final native void flushPendingCommands();

    public static final void joinThreadPool() {
        throw new RuntimeException("Stub!");
    }

    public void attachInterface(@RecentlyNullable IInterface owner, @RecentlyNullable String descriptor) {
        throw new RuntimeException("Stub!");
    }

    @RecentlyNullable
    public String getInterfaceDescriptor() {
        throw new RuntimeException("Stub!");
    }

    public boolean pingBinder() {
        throw new RuntimeException("Stub!");
    }

    public boolean isBinderAlive() {
        throw new RuntimeException("Stub!");
    }

    @RecentlyNullable
    public IInterface queryLocalInterface(@RecentlyNonNull String descriptor) {
        throw new RuntimeException("Stub!");
    }

    protected boolean onTransact(int code, @RecentlyNonNull Parcel data, @RecentlyNullable Parcel reply, int flags) throws RemoteException {
        throw new RuntimeException("Stub!");
    }

    public void dump(@RecentlyNonNull FileDescriptor fd, @RecentlyNullable String[] args) {
        throw new RuntimeException("Stub!");
    }

    public void dumpAsync(@RecentlyNonNull FileDescriptor fd, @RecentlyNullable String[] args) {
        throw new RuntimeException("Stub!");
    }

    protected void dump(@RecentlyNonNull FileDescriptor fd, @RecentlyNonNull PrintWriter fout, @RecentlyNullable String[] args) {
        throw new RuntimeException("Stub!");
    }

    public final boolean transact(int code, @RecentlyNonNull Parcel data, @RecentlyNullable Parcel reply, int flags) throws RemoteException {
        throw new RuntimeException("Stub!");
    }

    public void linkToDeath(@RecentlyNonNull DeathRecipient recipient, int flags) {
        throw new RuntimeException("Stub!");
    }

    public boolean unlinkToDeath(@RecentlyNonNull DeathRecipient recipient, int flags) {
        throw new RuntimeException("Stub!");
    }
}

说明:

  1. onTransact运行在服务端Binder线程池,code参数用于区分方法,data参数存储对应方法参数,reply用于写入返回值;
  2. Binder类提供类监听Binder对象是否存活的方法 linkToDeath/unlinkToDeath
  3. 自己实现Binder,可以参考AIDL形式,需要暴露asInterface接口,用于返回AIDL接口类型对象
    (Stub或者Stub#Proxy, 如果bindService不涉及跨进程,则返回Stub,onTransact方法也就不会调用了;
    涉及到跨进程,client调用proxy内的方法,会通过transact来方送RPC请求,client端线程挂起,server端onTransact方法被调用,直到方法返回,client端线程继续执行,并返回reply数据)
public interface IBinder {
	...
	public boolean isBinderAlive();
	
	public void linkToDeath(@NonNull DeathRecipient recipient, int flags)
        throws RemoteException;
       
	public boolean unlinkToDeath(@NonNull DeathRecipient recipient, int flags);
    ...
    // 监听Binder对象是否正常的接口
    public interface DeathRecipient {
        public void binderDied();
    }
}

3.总结

  1. 请求远程方法client线程会被挂起,远程方法可能是耗时方法,所以建议在子线程发起请求;
  2. 服务端方法运行在服务端Binder线程池,可以执行耗时任务;
  3. AIDL方式中,Client调用Service的方法,是同步吗?异步吗?

    oneway关键字修饰的方法,在多进程场景下,Client端的请求是异步调用,返回值是void,其他场景下(非oneway方式调用,或者同一进程中的oneway方式调用)可以理解为同步调用。

  4. 采用BindPool方案,无需一个AIDL文件对应一个Service。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值