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!");
}
}
说明:
- onTransact运行在服务端Binder线程池,code参数用于区分方法,data参数存储对应方法参数,reply用于写入返回值;
- Binder类提供类监听Binder对象是否存活的方法 linkToDeath/unlinkToDeath
- 自己实现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.总结
- 请求远程方法client线程会被挂起,远程方法可能是耗时方法,所以建议在子线程发起请求;
- 服务端方法运行在服务端Binder线程池,可以执行耗时任务;
- AIDL方式中,Client调用Service的方法,是同步吗?异步吗?
oneway关键字修饰的方法,在多进程场景下,Client端的请求是异步调用,返回值是void,其他场景下(非oneway方式调用,或者同一进程中的oneway方式调用)可以理解为同步调用。
- 采用BindPool方案,无需一个AIDL文件对应一个Service。