咱们知道 Binder 驱动主要用于跨进程的通讯, 它的身影出如今 Androrid 系统方方面面, 是 Android 系统框架中很是重要, 又很是难懂以搞懂的一部分
关于 Binder 驱动, 之前看别人分享文章的时候, 不少都会在前面写上 "关于 Binder 驱动相关的知识, 我有些难如下笔", 今天产生整理这篇文章的时候, 笔者突然之间感受, 前辈们说的真是太有道理了, 突然之间, 我也有些难如下笔, 由于它覆盖面太过于庞大了, 牵扯到了 应用开发层, Java 应用框架层, 运行时库层, HAL 层, 以及 Linux 内核层, 想要将之阐述清楚, 可真是否是一篇文章可以搞定的, 不过这里仍是尝试写一写
java
本文主要从如下几个方面阐述android
熟悉 Android 开发的咱们都知道, 在 Android 项目中进行跨进程通讯可使用 AIDL 接口定义语言, 快捷生成相应的代码进行跨进程通讯, 这里为了弄清楚代码生成背后故事, 咱们手动实现一下缓存
/**
* 定义一个服务的提供的功能接口
*
* @author Sharry <a href="SharryChooCHN@Gmail.com">Contact me.</a>
* @version 1.0
* @since 2018/9/29 16:29
*/
public interface IRemoteService extends IInterface {
/*
跨进程提供服务的接口描述
*/
String DESCRIPTOR = IRemoteService.class.getName();
/*
跨进程提供服务的接口中 getServiceName 这个方法 Transaction id.
*/
int TRANSACTION_getServiceName = (IBinder.FIRST_CALL_TRANSACTION + 0);
String getServiceName() throws RemoteException;
}
复制代码
/**
* 接口 IRemoteService 在服务端的实现类
* {@link #mBinder } 这个对象是让 IRemoteService 拥有跨进程提供数据能力的 Binder 本地实现类
*
* @author Sharry <a href="SharryChooCHN@Gmail.com">Contact me.</a>
* @version 1.0
* @since 2018/9/29 17:48
*/
public class RemoteServiceImpl implements IRemoteService {
private IBinder mBinder;
public RemoteServiceImpl(IBinder binder) {
this.mBinder = binder;
}
@Override
public String getServiceName() {
return "This this RemoteService support function.";
}
@Override
public IBinder asBinder() {
return mBinder;
}
}
/**
* Service 端 Binder 实体对象实现类
* 其向外提供的功能接口为 {@link IRemoteService}
*
* @author Sharry <a href="SharryChooCHN@Gmail.com">Contact me.</a>
* @version 1.0
* @since 2018/9/28 20:50
*/
public class RemoteServiceBinder extends Binder {
/*
持有其对应接口实现类的引用
*/
private IRemoteService mImpl;
public RemoteServiceBinder() {
mImpl = new RemoteServiceImpl(this);
// 调用了 attachInterface 以后, 父类 Binder 将会持有当前 IInterface 接口的描述
// 在 onTransact 中 会自动处理 INTERFACE_TRANSACTION 类型的事务
// 在 queryLocalInterface 中能够找到本地接口
this.attachInterface(mImpl, mImpl.DESCRIPTOR);
}
@Override
protected boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
switch (code) {
// 调用了 attachInterface 以后, 父类会处理该类型的 code.
// case INTERFACE_TRANSACTION: {
// reply.writeString(DESCRIPTOR);
// return true;
// }
case IRemoteService.TRANSACTION_getServiceName: {
data.enforceInterface(mImpl.DESCRIPTOR);
reply.writeNoException();
reply.writeString(mImpl.getServiceName());
return true;
}
default:
return super.onTransact(code, data, reply, flags);
}
}
}
复制代码
好的, 能够看到这里定义了两个类, 它们分别是bash
能够发现 RemoteServiceImpl 与 RemoteServiceBinder 内部是相互持有对方引用的框架
/**
* 接口 IRemoteService 在客户端的代理实现类
* {@link #mBinderProxy } 这个对象即 BinderProxy {@link android.os.Binder#BinderProxy} 实例的引用
*
* @author Sharry <a href="SharryChooCHN@Gmail.com">Contact me.</a>
* @version 1.0
* @since 2018/9/29 16:36
*/
public class RemoteServiceProxyImpl implements IRemoteService {
private IBinder mBinderProxy;
public RemoteServiceProxyImpl(IBinder binder) {
mBinderProxy = binder;
}
@Override
public String getServiceName() throws RemoteException {
String result = null;
Parcel data = Parcel.obtain();
Parcel replay = Parcel.obtain();
try {
// 1. 写入调用方法所对应接口的描述
data.writeInterfaceToken(DESCRIPTOR);
// 2. 向 Service 端发起 invocation 请求
mBinderProxy.transact(IRemoteService.TRANSACTION_getServiceName, data, replay, 0);
// 3. 读取 Service 端扔出来的异常信息
replay.readException();
// 4. 读取异常结果
result = replay.readString();
} finally {
replay.recycle();
data.recycle();
}
return result;
}
@Override
public IBinder asBinder() {
return mBinderProxy;
}
}
复制代码
好的, 能够看到这里咱们也建立了一个 IRemoteService 的实现类 RemoteServiceProxyImpl 从名字咱们就能够知道它是 IRemoteService 接口的代理实现类, 相同的它内部也持有一个 IBinder 对象, 不过这里咱们没有本身建立这个 IBinder 的实现类, **那这个 IBinder 实现类是谁呢? **, 其实咱们无需为代理接口对象建立其特定的 BinderProxy 实现类, 由于系统给咱们提供了, 这个 IBinder 的实现类实际上是 android.os.BinderProxy: IBinderide
/**
* 用于将一个 Binder 对象转为对应的接口
*
* @author Sharry <a href="SharryChooCHN@Gmail.com">Contact me.</a>
* @version 1.0
* @since 2018/9/29 16:35
*/
public class RemoteServiceUtils {
/**
* Cast an IBinder object into an com.frank.aidldemo.IServiceInteraction interface,
* generating a proxy if needed.
*/
public static IRemoteService asInterface(IBinder obj) {
if (null == obj) {
return null;
}
// 若想获取 Service 端 RemoteServiceImpl 对象, 须要在 Binder 本地对象构建时, 调用 attachInterface
IInterface iin = obj.queryLocalInterface(IRemoteService.DESCRIPTOR);
if (null != iin && iin instanceof IRemoteService) {
return ((IRemoteService) iin);
}
return new RemoteServiceProxyImpl(obj);
}
}
复制代码
Binder(android.os.Binder: IBinder) 是 Binder 本地对象 Java 层的实现, 在 Server 端实例化, 对应咱们上面的 RemoteServiceBinder, 它的做用是在 onTransact 中接收 Client 端经过 Binder 驱动传来的 IPC 请求, 并将请求结果经过 Binder 驱动返回给 Client 端函数
接下来咱们就看看如何实例化一个 Binder 实体对象工具
使用过 Service 的都知道, 在 onBind 中会 new 一个咱们实现好的 Binder 对象ui
public class RemoteService extends Service {
public IBinder onBind(Intent intent) {
return new RemoteServiceBinder();
}
}
复制代码
这个样子咱们就建立了一个 Binder 本地对象, 咱们看看他的构造方法this
public class Binder implements IBinder {
private final long mObject;//
/**
* Binder.constructor
*/
public Binder() {
// 调用了 getNativeBBinderHolder 方法, 获取一个 Native 层的 BBinderHolder 对象句柄值
mObject = getNativeBBinderHolder();
......
}
private static native long getNativeBBinderHolder();
}
复制代码
能够看见 Binder 中主要调用了 native 方法, 获取了一个句柄值, 固然这个 mObject 句柄值也很是重要, 由于 Binder 类内部不少方法都是由它代理实现的
// frameworks/base/core/jni/android_util_Binder.cpp
static jlong android_os_Binder_getNativeBBinderHolder(JNIEnv* env, jobject clazz)
{
// new 了一个 JavaBBinderHolder 这个对象
JavaBBinderHolder* jbh = new JavaBBinderHolder();
return (jlong) jbh;
}
复制代码
很是简单的实现 new 了一个 JavaBBinderHolder 这个对象, 而后将它的句柄返回给 Java 中 Binder 对象的 mObject 属性, 接下来咱们看看这个 JavaBBinderHolder 的构造函数中作了哪些操做
// frameworks/base/core/jni/android_util_Binder.cpp
class JavaBBinderHolder
{
public:
// 获取 JavaBBinder 对象
sp<JavaBBinder> get(JNIEnv* env, jobject obj)
{
AutoMutex _l(mLock);
// 尝试将 mBinder 这个若指针升级为强指针
sp<JavaBBinder> b = mBinder.promote();
// 升级失败则从新建立 JavaBBinder 对象
if (b == NULL) {
b = new JavaBBinder(env, obj);
mBinder = b;
}
// 返回一个 JavaBinder
return b;
}
private:
Mutex mLock; // 互斥锁
wp<JavaBBinder> mBinder; // 一个 JavaBBinder 的弱指针
};
复制代码
能够看到 JavaBBinderHolder 顾名思义果然持有了一个 JavaBBinder 的对象, 而且能够经过 get 方法获取到, 结下来看看这个 JavaBinder
// frameworks/base/core/jni/android_util_Binder.cpp
class JavaBBinder : public BBinder
{
public:
// 构造函数
JavaBBinder(JNIEnv* env, jobject /* Java Binder */ object)
: mVM(jnienv_to_javavm(env)), mObject(env->NewGlobalRef(object))
{
......
}
// 获取咱们 Java 中实例化的 Binder 对象
jobject object() const
{
return mObject;
}
protected:
// Native 层 JavaBBinder 的 onTransact 函数
virtual status_t onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0)
{
// 将 JavaVM convert2 JNIEnv
JNIEnv* env = javavm_to_jnienv(mVM);
// 回调 java 中 Binder 对象的 execTransact 方法
jboolean res = env->CallBooleanMethod(mObject, gBinderOffsets.mExecTransact,
code, reinterpret_cast<jlong>(&data), reinterpret_cast<jlong>(reply), flags);
// ......
if (code == SYSPROPS_TRANSACTION) {
// 回调父类的 onTransact 函数
BBinder::onTransact(code, data, reply, flags);
}
return res != JNI_FALSE ? NO_ERROR : UNKNOWN_TRANSACTION;
}
private:
JavaVM* const mVM; // JavaVM 指针对象, 用于转为 JNIEnv*
jobject const mObject; // Java 中的 Binder 对象, 即咱们在 Java 中建立的实例
};
复制代码
看到 JavaBBinder 的实现, 一切就变得很明了了
如此一来, Binder 驱动发送的 IPC 请求, 就能够经过 JavaBBinder 的 onTransact 函数回溯到 Java 的 Binder 方法中了
BinderProxy(android.os.BinderProxy: IBinder) 是 Binder 代理对象 Java 层代理对象, 实现了 IBinder 接口, 它在 Client 进程实例化, 它的做用是让 Client 端调用 transact 方法经过 Binder 驱动向 Server 端发起 IPC 请求, 并等待 Server 端返回的结果, 接下来咱们就看看它实例化的过程
/**
* BinderProxy.getInstance 是私有化的
*/
private static BinderProxy getInstance(long nativeData, long iBinder) {
BinderProxy result;
......
result = new BinderProxy(nativeData);
......
return result;
}
/**
* BinderProxy 的构造方法也是私有化的
*/
private BinderProxy(long nativeData) {
mNativeData = nativeData;
}
复制代码
能够看到 BinderProxy 这个 java 的 Class 两个获取实例的方式都是私有化的, 并且其构造方法的形参是一个 Native 指针的句柄值, 那么只有一种可能性, BinderProxy 这个对象是在 Native 层使用 JNI 实例化再返回 java 层的, 带着这个疑问咱们去探究一下
了解 Binder 驱动相关知识的小伙伴都知道, BinderProxy 通常能够经过两种方式来获取
咱们在 Client 进程, 经过调用 Context.bindService(), 启动一个远程的 Service, 这时候须要须要传入一个 ServiceConnection 参数对象, 在其 onServiceConnected 方法中会收到一个 IBinder 对象的回调, 这个对象即为 BinderProxy, 以下图
private val connect: ServiceConnection = object : ServiceConnection {
override fun onServiceDisconnected(name: ComponentName?) {
}
override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
// 这个 service 即一个 BinderProxy 的实例对象
}
}
复制代码
由于这里还会牵扯到 Service 的启动流程, 因此咱们使用方式二的思路往下解析
经过 ServiceManager 获取一个系统注册好的服务, Activity 启动流程中的 AMS 相信你们再熟悉不过了, 看看它是如何获取的
private static final Singleton<IActivityManager> IActivityManagerSingleton =
new Singleton<IActivityManager>() {
@Override
protected IActivityManager create() {
final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
final IActivityManager am = IActivityManager.Stub.asInterface(b);
return am;
}
};
复制代码
能够看到第二种方式是经过 ServiceManager.getService(Context.ACTIVITY_SERVICE) 获取的, 咱们继续往下剖析
/**
* ServiceManager.getService 获取服务的 IBinder 对象
*/
public static IBinder getService(String name) {
try {
// 尝试从缓存中获取
IBinder service = sCache.get(name);
if (service != null) {
return service;
} else {
// 关注一下这个地方
// 1. getIServiceManager() 获取 IServiceManager 服务提供对象
// 2. 调用 IServiceManager.getService(name) 获取服务
return Binder.allowBlocking(getIServiceManager().getService(name));
}
} catch (RemoteException e) {
Log.e(TAG, "error in getService", e);
}
return null;
}
复制代码
能够看到 ServiceManager 实际上是一个壳, 其方法的主要实现是经过 IServiceManager 实现的, 接下来咱们看看 getIServiceManager 是如何获取 IServiceManager 对象的
/**
* ServiceManager.getIServiceManager
*/
private static IServiceManager getIServiceManager() {
if (sServiceManager != null) {
return sServiceManager;
}
// 关注这里
// 1. 这里经过 BinderInternal.getContextObject() 这个方法获取到了 BinderProxy 对象
// 2. 经过 asInterface 将这个 BinderProxy 对象封装成了 ServiceManagerProxy
sServiceManager = ServiceManagerNative
.asInterface(Binder.allowBlocking(BinderInternal.getContextObject()));
return sServiceManager;
}
/**
* BinderInternal.getContextObject 这就是获取 BinderProxy 对象的关键
*/
public static final native IBinder getContextObject();
/**
* ServiceManagerNative.asInterface
*/
static public IServiceManager asInterface(IBinder obj)
{
if (obj == null) {
return null;
}
IServiceManager in =
(IServiceManager)obj.queryLocalInterface(descriptor);
if (in != null) {
return in;
}
// 将 IBinder 对象封装成 ServiceManagerProxy 对象, 这个对象是 IServiceManager 提供给 Client 端使用的实现类
return new ServiceManagerProxy(obj);
}
}
复制代码
咱们看到了一个很是重要的线索 BinderInternal.getContextObject() 这是一个很是关键的方法, 系统就是经过它获取了 IServiceManager 的 Binder 代理对象
至此 Java 层的旅程就告一段落了, 接下来附上一张 ServiceManager 在 java 层的关系依赖图
接下来咱们就要深刻到 Native 层去看看 BinderInternal.getContextObject() 的实现了
// frameworks/base/core/jni/android_util_Binder.cpp
static jobject android_os_BinderInternal_getContextObject(JNIEnv* env, jobject clazz)
{
// 调用了 ProcessState 的 getContextObject 获取一个句柄值为 NULL 的 IBinder 对象
sp<IBinder> b = ProcessState::self()->getContextObject(NULL);
// 调用 javaObjectForIBinder 返回一个 Java 中的 Binder 对象
return javaObjectForIBinder(env, b);
}
复制代码
能够看到 Native 层中的 getContextObject 中主要作了两步操做
// frameworks/base/core/jni/android_util_Binder.cpp
jobject javaObjectForIBinder(JNIEnv* env, const sp<IBinder>& val)
{
if (val == NULL) return NULL;
// 若为本地对象, 则返回 Java 中的 Binder 对象
// 很显然这个 val 为 BpBinder, 咱们关注下面的代码
if (val->checkSubclass(&gBinderOffsets)) {
jobject object = static_cast<JavaBBinder*>(val.get())->object();
return object;
}
// 互斥锁
AutoMutex _l(mProxyLock);
// 1. 判断是否已经为当前驱动建立了 BinderProxy 对象了
jobject object = (jobject)val->findObject(&gBinderProxyOffsets);
if (object != NULL) {
// 经过引用升级的方式, 判断这个 BinderProxy 对象是否有效
jobject res = jniGetReferent(env, object);
if (res != NULL) {
// 如有效则返回到 java 层
return res;
}
......
// 若无效则解除这个对象与 BpBinder 的关联
val->detachObject(&gBinderProxyOffsets);
......
}
// 2. 这里经过 JNI 的方式调用了 BinderProxy 的构造函数
object = env->NewObject(gBinderProxyOffsets.mClass, gBinderProxyOffsets.mConstructor);
if (object != NULL) {
// 3. 给 BinderProxy 中的 mObject 对象赋值, 值为 BpBinder 的句柄
// 如此一来 Java 中的 BinderProxy 就能够经过它找到 BpBinder 了
env->SetLongField(object, gBinderProxyOffsets.mObject, (jlong)val.get());
val->incStrong((void*)javaObjectForIBinder);
// 4. 将这个 BinderProxy 缓存到 BpBinder 中
jobject refObject = env->NewGlobalRef(
env->GetObjectField(object, gBinderProxyOffsets.mSelf));
val->attachObject(&gBinderProxyOffsets, refObject,
jnienv_to_javavm(env), proxy_cleanup);
......
}
return object;
}
复制代码
能够看到这个方法中作了以下几件事情
至此 Java 中的 BinderProxy 就在 Native 层建立出来了
好的分析到这里咱们知道了 Binder 实体对象与 代理对象的实例化过程, 而且也悄悄的解开了 Binder 驱动在应用框架层的面纱
好的, 至此 Binder 驱动的上篇就结束了, 下篇中会着重分析 Binder 运行时库和一次 Binder 通讯的流程