作为Android 主要的IPC方式Binder, 其实现了IBinder接口,通过代理模式,parcelable序列化反序列操作,实现了RPC,即跨进程调用
首先Binder 实现了IBinder接口,故先来看看IBinder接口,IBinder代码只有四十行功能比较清晰。
public interface IBinder {
//IBinder协议传输码, 用来获得网络状态
int DUMP_TRANSACTION = 1598311760;
//第一次传输回调传输码
int FIRST_CALL_TRANSACTION = 1;
//IBinder协议传输码,用于 transact(int, Parcel, Parcel, int),oneway意味着caller返回很快,不会等待结果
int FLAG_ONEWAY = 1;
//Binder协议传输码,用于查询事务的接收方以获得其规范接口描述符。
int INTERFACE_TRANSACTION = 1598968902;
//上一次传输回调传输码
int LAST_CALL_TRANSACTION = 16777215;
//IBinder协议传输码,异步调用app
int LIKE_TRANSACTION = 1598835019;
//IBinder协议传输码,pingBinder()的传输码
int PING_TRANSACTION = 1599098439;
//IBinder协议传输码,向对象发送一个tweet
int TWEET_TRANSACTION = 1599362900;
@Nullable
//获取接口描述
String getInterfaceDescriptor() throws RemoteException;
//检查对象是否存在
boolean pingBinder();
//检查进程的Binder是否活着
boolean isBinderAlive();
//尝试检索一个Binder的本地接口
@Nullable
IInterface queryLocalInterface(@NonNull String var1);
//获得对象的状态
void dump(@NonNull FileDescriptor var1, @Nullable String[] var2) throws RemoteException;
//异步的获得对象的状态
void dumpAsync(@NonNull FileDescriptor var1, @Nullable String[] var2) throws RemoteException;
//对对象执行泛型操作
boolean transact(int var1, @NonNull Parcel var2, @Nullable Parcel var3, int var4) throws RemoteException;
//注册Binder死亡监听
void linkToDeath(@NonNull IBinder.DeathRecipient var1, int var2) throws RemoteException;
//移除Binder死亡监听
boolean unlinkToDeath(@NonNull IBinder.DeathRecipient var1, int var2);
//Binder死亡监听回调接口
public interface DeathRecipient {
void binderDied();
}
}
//使用Holder允许在引导映像中静态初始化绑定器,是为了避免一些初始化排序可能的问题。
private static class NoImagePreloadHolder {
public static final NativeAllocationRegistry sRegistry = new NativeAllocationRegistry(
Binder.class.getClassLoader(), getNativeFinalizer(), NATIVE_ALLOCATION_SIZE);
}
FIND_POTENTIAL_LEAKS 用于设置FLAG是否检查可能的内存泄露
CHECK_PARCEL_SIZE 用于设置FLAG是否检查Parcel 大小
LOG_RUNTIME_EXCEPTION 用于设置FLAG是否检查运行异常
sDumpDisabled 控制dump是否可被调用
sTransactionTracker 全局进程transaction tracker
pintBinder 默认返回true
isBinderAlive 默认返回true
onTransact
transact()的回调函数,对传输对象进行序列化操作
protected boolean onTransact(int code, @NonNull Parcel data, @Nullable Parcel reply,
int flags) throws RemoteException {
//data对象是序列化Parcel类携带数据,reply对象是序列化类返回给调用者的结果
//往返回值中写入接口描述字段
if (code == INTERFACE_TRANSACTION) {
reply.writeString(getInterfaceDescriptor());
return true;
} else if (code == DUMP_TRANSACTION) {
ParcelFileDescriptor fd = data.readFileDescriptor();
String[] args = data.readStringArray();
if (fd != null) {
try {
dump(fd.getFileDescriptor(), args);
} finally {
IoUtils.closeQuietly(fd);
}
}
// Write the StrictMode header.
if (reply != null) {
reply.writeNoException();
} else {
StrictMode.clearGatheredViolations();
}
return true;
} else if (code == SHELL_COMMAND_TRANSACTION) {
ParcelFileDescriptor in = data.readFileDescriptor();
ParcelFileDescriptor out = data.readFileDescriptor();
ParcelFileDescriptor err = data.readFileDescriptor();
String[] args = data.readStringArray();
ShellCallback shellCallback = ShellCallback.CREATOR.createFromParcel(data);
ResultReceiver resultReceiver = ResultReceiver.CREATOR.createFromParcel(data);
try {
if (out != null) {
shellCommand(in != null ? in.getFileDescriptor() : null,
out.getFileDescriptor(),
err != null ? err.getFileDescriptor() : out.getFileDescriptor(),
args, shellCallback, resultReceiver);
}
} finally {
IoUtils.closeQuietly(in);
IoUtils.closeQuietly(out);
IoUtils.closeQuietly(err);
// Write the StrictMode header.
if (reply != null) {
reply.writeNoException();
} else {
StrictMode.clearGatheredViolations();
}
}
return true;
}
return false;
}
transact() 默认的实现传递parcel对象并调用onTransact。在客户端,transact会调用Binder 代理类实现IPC,跨进程调用
public final boolean transact(int code, @NonNull Parcel data, @Nullable Parcel reply,
int flags) throws RemoteException {
if (false) Log.v("Binder", "Transact: " + code + " to " + this);
if (data != null) {
data.setDataPosition(0);
}
boolean r = onTransact(code, data, reply, flags);
if (reply != null) {
reply.setDataPosition(0);
}
return r;
}
客户端中的BinderProxy的transact() 中调用native函数 transactNative进行传值
public boolean transact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
Binder.checkParcel(this, code, data, "Unreasonably large binder buffer");
if (mWarnOnBlocking && ((flags & FLAG_ONEWAY) == 0)) {
// For now, avoid spamming the log by disabling after we've logged
// about this interface at least once
mWarnOnBlocking = false;
Log.w(Binder.TAG, "Outgoing transactions from this process must be FLAG_ONEWAY",
new Throwable());
}
final boolean tracingEnabled = Binder.isTracingEnabled();
if (tracingEnabled) {
final Throwable tr = new Throwable();
Binder.getTransactionTracker().addTrace(tr);
StackTraceElement stackTraceElement = tr.getStackTrace()[1];
Trace.traceBegin(Trace.TRACE_TAG_ALWAYS,
stackTraceElement.getClassName() + "." + stackTraceElement.getMethodName());
}
try {
return transactNative(code, data, reply, flags);
} finally {
if (tracingEnabled) {
Trace.traceEnd(Trace.TRACE_TAG_ALWAYS);
}
}
}