一、简介
对于 Android 系统,一般是从 java 层到 native 层,再到 kernel 驱动层,形成一个完整的软件架构。Android 系统中的 Binder IPC 通信机制的整体架构也是如此,Java 和 C++ 层都定义有同样功能的供应用程序使用的 Binder 接口。然而 Java 层中 Framework 层的 ServiceManager 类与 Native 层的功能并不完全对应,Framework 层的 ServiceManager 类的实现最终是通过 BinderProxy 传递给 Native 层来完成的。
ServiceManager:通过 getIServiceManager 方法获取的是 ServiceManagerProxy 对象,ServiceManager 的 addService 和 getService 实际工作都交由 ServiceManagerProxy的相应方法来处理。
ServiceManagerProxy:其成员变量 mRemote 指向 BinderProxy 对象,ServiceManagerProxy 的 addService 和 getService 方法最终是交由 mRemote 来完成。
ServiceManagerNative:其方法 asInterface() 返回的是 ServiceManagerProxy 对象,ServiceManager 便是借助 ServiceManagerNative 类来找到 ServiceManagerProxy。
Binder:其成员变量 mObject 和方法 execTransact() 用于 native 方法。
BinderInternal:内部有一个 GcWatcher 类,用于处理和调试与 Binder 相关的垃圾回收。
IBinder:接口中常量 FLAG_ONEWAY,客户端利用 Binder 跟服务端通信是阻塞式的,但如果设置了 FLAG_ONEWAY,这成为非阻塞的调用方式,客户端能立即返回,服务端采用回调方式来通知客户端完成情况。另外 IBinder 接口有一个内部接口 DeathDecipient(死亡通告)。
1、Stub与Proxy机制
在 Android 系统中,Binder 机制通过 Stub 和 Proxy 来实现跨进程通信(IPC)。Stub 和 Proxy 是 Binder IPC 的核心组件,它们分别代表服务端和客户端的接口。这种机制允许客户端远程调用服务端的方法,而无需知道底层的通信细节。
Stub(服务端)
Stub 是服务端的一个本地对象,它实现了服务端暴露给客户端的接口。当客户端想要调用服务端的方法时,它实际上是调用了 Stub 对象上的方法。Stub 对象内部会处理通信的细节,包括将方法调用转换为跨进程通信的请求,并将其发送到客户端进程。
Stub 通常是通过 aidl(Android Interface Definition Language)文件生成的。aidl文件定义了服务端暴露给客户端的接口,包括方法签名和参数类型等信息。编译 aidl 文件时,Android SDK 会生成相应的 Stub 类,这个类包含了服务端需要实现的方法。
Proxy(客户端)
Proxy 是客户端的一个本地对象,它代表了服务端对象。客户端通过Proxy来调用服务端的方法,而 Proxy 会将方法调用转换为跨进程通信的请求,并将其发送到服务端进程。
当客户端调用 Proxy 对象上的方法时,Binder 驱动会捕获这个调用,并将其转换为一个跨进程通信的请求。这个请求会被发送到服务端进程,由服务端的 Stub 对象接收并处理。处理完成后,服务端将结果发送回客户端进程,客户端通过 Proxy 对象接收并处理这个结果。
Proxy 也是通过 aidl 文件生成的。编译 aidl 文件时,Android SDK 会生成相应的 Proxy 类,这个类包含了客户端用来调用服务端方法的接口。
工作流程
- 服务端注册服务:服务端创建一个实现了特定接口的 Stub 对象,并将其注册到 Binder驱动程序中,使其可以被其他进程访问。
- 客户端获取代理:客户端通过
bindService()
方法或其他方式获取服务端 Stub 对象的 Proxy。- 客户端调用方法:客户端通过 Proxy 对象调用服务端的方法。这个调用实际上被转换为跨进程通信的请求,并被发送到服务端进程。
- 服务端处理请求:服务端的 Stub 对象接收到请求后,会将其分发到相应的线程进行处理。处理完成后,服务端将结果发送回客户端进程。
- 客户端接收结果:客户端通过 Proxy 对象接收并处理服务端返回的结果。
通过这种方式,Stub 和 Proxy 机制实现了客户端和服务端之间的透明通信,使得客户端可以像调用本地方法一样调用服务端的方法。
2、ServiceManager
ServiceManager 是 Binder 机制的大管家,管理着 android 系统的各种 Service。Service 向 ServiceManager 注册,当 Client 需要调用 Service 时,先通过 ServiceManager 查询到该 Service,Client 接着再与 Service 通信。这些 Service 有 Java 层也有 Native 层的。Native 层通过 BpServiceManager/BnServiceManager 实现的 Service 与 ServiceManager 的交互。
3、Client和Service通信机制
Binder 通信的实现同 Native 层类似,Java 层 AIDL 脚本依据 IServiceManager.aidl 生成 IServiceManager 接口类,包含子类 IServiceManager.Stub 和 IServiceManager.Stub.Proxy,两者都实现了 IServiceManager 接口,前者代表 Server 端,后者代表 Client 端。
public interface IServiceManager extends android.os.IInterface {
public static abstract class Stub extends android.os.Binder implements android.os.IServiceManager {
public static android.os.IServiceManager asInterface(android.os.IBinder obj) {
if (obj == null){
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (iin != null && iin instanceof IServiceManager){
return (IServiceManager)iin;
}
return new IServiceManager.Stub.Proxy(obj);
}
public boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException
{
String descriptor = DESCRIPTOR;
……
switch (code){
case TRANSACTION_getService: {
String _arg0;
_arg0 = data.readString();
data.enforceNoDataAvail();
IBinder _result = getService(_agr0);
reply.writeNoException();
reply.writeStrongBinder(_result);
break;
}
……
}
}
}
private static class Proxy implements IServiceManager {
private IBinder mRemote;
Proxy(IBinder remote) {
mRemote = remote;
}
@Override
public IBinder getService(String name) throws RemoteException {
Parcel _data = Parcel.obtain();
Parcel _reply = Parcel.obtain();
IBinder _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeString(name);
boolean _status = mRemote.transact(Stub.TRANSACTION_getService, _data, _reply, 0);
_reply.readException();
_result = _reply.readStrongBinder();
} finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
@Override
public IBinder checkService(String name) throws RemoteException {
Parcel _data = Parcel.obtain();
Parcel _reply = Parcel.obtain();
IBinder _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeString(name);
boolean _status = mRemote.transact(Stub.TRANSACTION_checkService, _data, _reply, 0);
_reply.readException();
_result = _reply.readStrongBinder();
} finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
}
}
ServiceManager
源码位置:/frameworks/base/core/java/android/os/ServiceManager.java
Java 层使用 ServiceManager 类实现 servicemanager 的 Client 端,通过getIServiceManager() 获取 servicemanager 的代理类,其中 BinderInternal.getContextObject() 通过 JNI 创建一个 BinderProxy 对象。
这里 BinderProxy 本来就是 Java 类,通过 JNI 创建目的是创建 BinderPrxoy 对象的同时,也创建一个 BpBinder 对象,BinderProxy 和 BpBinder 是一一对应的关系。同理,创建 Java 层 Binder 对象时,也会通过 Jni 创建一个 BBinder 对象。我们可以理解为 BinderProxy/Binder 封装了 BpBinder/BBinder,实际工作的是后者。
public final class ServiceManager {
private static IServiceManager sServiceManager;
private static IServiceManager getIServiceManager(){
if (sServiceManager != null){
return sServiceManager;
}
// 找到服务管理器
sServiceManager = ServiceManagerNative.asInterface(Binder.allowBlocing(BinderInternal.getContextObject()));
return sServiceManager;
}
// 返回对具有给定名称的服务的引用
public static IBinder getService(String name){
try {
IBinder service = sCache.get(name);
if (service != null){
return service;
} else {
return Binder.allowBlocking(rawGetServices(name));
}
} catch (RemoteException e){
Log.e(TAG, "error in getService", e);
}
return null;
}
private static IBinder rawGetService(String name) throws RemoteException {
final IBinder binder = getIServiceManager().getService(name);
……
return binder;
}
}
这里,获取到的 servicemanager 的代理类 IServiceManagerProxy(BinderProxy)。
ServiceManagerNative
源码位置:/frameworks/base/core/java/android/os/ServiceManagerNative.java
public final class ServiceManagerNative {
private ServiceManagerNative(){}
public static IServiceManager asInterface(IBinder obj){
if (obj == null){
return null;
}
// ServiceManager永远不是本地的
return new ServiceManagerProxy(obj);
}
// 当mRemote不再被使用时,该类应该被删除并替换为IServiceManager.Stub
class ServiceManagerProxy implements IServiceManager {
public ServiceManagerProxy(IBinder remote){
mRemote = remote;
// servicemanager实际的代理类
mServiceManager = IServiceManager.Stub.asInterface(remote);
}
public IBinder getService(String name) throws RemoteException {
// 与checkService相同(旧版本的servicemanager有这两种方法)。
return mServiceManager.checkService(name);
}
……
// 和mServiceManager一样,但被应用使用。
// 一旦这个可以删除,ServiceManagerProxy应该被完全删除
private IBinder mRemote;
private IServiceManager mServiceManager;
}
}
这样,我们使用 ServiceManager.addService()/getService() 等方法时,会走到 BinderProxy的 transact() -> transactNative()。
BinderProxy
源码位置:/frameworks/base/core/java/android/os/BinderProxy.java
public boolean transact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
……
try {
return transactNative(code, data, reply, flags);
} finally {
……
}
}
public native boolean transactNative(int code, Parcel data, Parecl reply, int flags) throws RemoteException;
最终通过 Jni 进入 Native 层,通过 BpBinder.transact() -> IPCThreadState.transact() -> writeTransactionData() -> waitForResponse() 进入 binder 驱动层,与 servicemanager 进程通信,等待返回结果。
这里的 servicemanager 的服务端,使用的是 Native 层的 BnServiceManager,并没有使用到Java 层的 IServiceManager.Stub。servicemanager 接收到请求后,执行相应的操作IPCThreadState::executeCommand() -> BBinder::transact() -> BnServiceManager::onTransact(),具体的实现方法在 ServiceManager.cpp 中,这里不详细开展了。
::android::status_t BnServiceManager::onTransact(uint32_t _aidl_code, const ::android::Parcel& _aidl_data, ::android::Parcel* _aidl_reply, uint32_t _aidl_flags){
::android::status_t _aidl_ret_status = ::android::OK;
switch(_aidl_code){
case BnServiceManager::TRANSACTION_getService:
::std::string in_name;
::android::sp<::android::IBinder> _aidl_return;
...
_aidl_ret_status = _aidl_data.readUtf8FromUtf16(&in_name);
...
::android::binder::Status _aidl_status(getService(in_name, &_aidl_return));
...
_aidl_ret_status = _aidl_reply->writeStrongBinder(_aidl_return);
break;
case BnServiceManager::TRANSACTION_checkService:
...
}
}
数据组装完毕后,回到 IPCThreadState::executeCommand(),执行 sendReply()。
IPCThreadState.cpp
源码位置:/system/libhwbinder/IPCThreadState.cpp
sendReply
status_t IPCThreadState::sendReply(const Parcel& reply, uint32_t flags){
status_t err;
status_t statusBuffer;
err = writeTransactionData(BC_REPLY, flags, -1, 0, reply, &statusBuffer);
if (err < NO_ERROR) return err;
return waitForResponse(nullptr, nullptr);
}
通过 Binder 驱动,将请求的结果返回给 Client 端,如下所示,返回的结果写入了 Parcel 中。
waitForResponse
status_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult){
……
while(1){
if ((err=talkWithDriver()) < NO_ERROR) break;
……
cmd = (uint32_t)mIn.readInt32();
switch(cmd){
……
case BR_REPLY:
binder_transaction_data tr;
err = mIn.read(&tr, sizeof(tr));
……
if(reply){
if((tr.flags & TF_STATUS_CODE) == 0){
reply->ipcSetDataReference(reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer), tr.data_size, reinterpret_cast<const binder_size_t*>(tr.data.ptr.offsets), tr.offsets_size/sizeof(binder_size_t), freeBuffer, this);
} else {
……
}
}else{
……
}
goto finish;
}
}
finish:
if (err != NO_ERROR){
……
}
return err;
}
接着进入 IServiceManager.Stub.Proxy 类的方法中,通过 Parcel.readStrongBinder() 获取到与 servicemanager 通信的结果。
总结:servicemanager 在管理 Java 层 Service 时,目前只使用了 IServiceManager.Stub.Proxy 作为代理类,并没有使用 IServiceManager.Stub 作为服务类,服务类使用的依然是 Native 层 BnServiceManager。
标签:IServiceManager,Java,Stub,Binder,reply,Android,data,服务端,客户端 From: https://blog.csdn.net/c19344881x/article/details/137217931