2

我一直在阅读我能找到的所有内容,试图找出 Android BINDER IPC 机制背后的软件架构。据我了解,BINDER 位于内核空间中,并临时为用户空间应用程序分配共享内存,通过该内存可以在进程之间中继消息。

我开始失去控制的是实际实施的工作方式 - 特别是与包裹相关的。

我在网上查找并找到了由 Android 提供的任意服务的实现,例如 Network/Wifi/Notificaiton/Battery 等( Docs)。从我的阅读中我了解到,用户空间程序不应该实例化服务类本身,而应该获取对服务类的引用Context.getSystemService(Context.X)。因此,我认为这是一种间接的方式,即 Android已经运行了该服务,或者至少有资源在需要时启动它。实施基本上是这样安排的:

电池类

BatteryManager.setBatteryState(){
    Parcel parcelLocal = Parcel.obtain();
    parcelLocal.writeInterfaceToken("android.power.BatteryManager");
    parcelLocal.writeInt(1/0); //Depending on requested state
    BinderObject.transact      //Send the data using BINDER
    CheckForExceptions();      //Upon return, check for exceptions 
    ReadResponse();            //If none, read the response from the target
    DoAppropriateAction();     //Whatever we need to do after setting the state
    parcelLocal.recycle();     //Return the parcel resource
}

起初看起来很简单:当用户执行以下操作时:

BatteryMonitor bMonitor = Context.getSystemService(Context.POWER_SERVICE);
bMonitor.setBatteryStatus(1); 

然后user's实例会使用 BINDER 机制与system's实际的服务控制器进行通信(哪个是同一个类的实例?)。但是,上面显示的代码是系统电池监控服务的实现,那么究竟是谁在接收 BINDER 数据呢?

TL;DR:如果这一切都非常混乱,很可能是因为我试图将一千行代码压缩成 10 行,总结是:当用户打算控制硬件状态时 - 例如网络/Wifi /Location/Notifcations(触摸屏)—— Android 中实际发生了什么,谁真正控制这些抽象服务相关的硬件?

注意:以上代码完全是虚构的,仅用于显示一般结构。

4

1 回答 1

1

大多数系统服务在system_server进程中作为线程运行。在启动时,它们会传递一个呼叫邀请(请参阅 call to addService()in SystemServer.javaservicemanager,然后可以将邀请分发给正在呼叫的应用程序getSystemService

一旦事情进展顺利,您可以将整个设置视为一种客户端-服务器架构,其中您的应用程序是客户端(远程或代理端),服务器(本地或存根端)是您正在谈论的系统服务至。客户端和服务器通过称为 binder 的进程间通信 (IPC) 子系统进行通信。绑定器有不同的部分:框架组件执行包的编组和解组,而内核驱动程序执行与 ioctl 调用之间的实际内存复制,并在进程和线程级别跟踪谁被邀请调用。

应用程序通过代理与活页夹交互。例如,当您使用 时LocationManagerService,您会得到一个android.location.ILocationManager. Proxy 类中的方法之一是getLastLocation()

...
@Override public android.location.Location getLastLocation(android.location.LocationRequest request, java.lang.String packageName) throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
android.location.Location _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
if ((request!=null)) {
_data.writeInt(1);
request.writeToParcel(_data, 0);
}
else {
_data.writeInt(0);
}
_data.writeString(packageName);
mRemote.transact(Stub.TRANSACTION_getLastLocation, _data, _reply, 0);
_reply.readException();
if ((0!=_reply.readInt())) {
_result = android.location.Location.CREATOR.createFromParcel(_reply);
}
else {
_result = null;
}
}
finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
...

在这里,您可以看到事务代码TRANSACTION_getLastLocation与任何必要的数据一起写入接口,并读取结果。在存根端,有一个onTransact()方法在服务的进程空间中运行,它根据事务代码处理所有传入的事务:

...
case TRANSACTION_getLastLocation:
{
data.enforceInterface(DESCRIPTOR);
android.location.LocationRequest _arg0;
if ((0!=data.readInt())) {
_arg0 = android.location.LocationRequest.CREATOR.createFromParcel(data);
}
else {
_arg0 = null;
}
java.lang.String _arg1;
_arg1 = data.readString();
android.location.Location _result = this.getLastLocation(_arg0, _arg1);
reply.writeNoException();
if ((_result!=null)) {
reply.writeInt(1);
_result.writeToParcel(reply, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
}
else {
reply.writeInt(0);
}
return true;
}
...

简而言之,该system_service进程代表调用者进行操作。这允许它对硬件或其他系统资源执行通常具有特权的操作。安全性基于 1) 具有调用邀请的应用程序(从service_managervia获得getSystemService)和 2) 通过服务本身实施的任何检查,例如检查ACCESS_COARSE_LOCATIONACCESS_FINE_LOCATIONLocationManagerService(在清单中声明并在安装时由最终用户)。

更新:在定位服务的情况下,这些硬件操作需要从 GPS 硬件获取实际的 NMEA 数据。目前实现这一点的方式是通过GpsLocationProvider通过 JNI 与本机代码接口的类。本机代码 ( com_android_server_location_GpsLocationProvider.cpp) 是打开硬件设备的地方(通过hw_module_t结构中保存的抽象层),进行位置回调(例如,location_callback())等。所有这些都在system_server具有特权 UID 的进程空间内运行system。您可以通过运行支持定位的应用程序、GpsLocationProvider在 logcat 中查找标签并确认记录的 PID 是system_server. 例如:

$ adb logcat | grep -i gps
...
D/GpsLocationProvider(  731): Reset GPS properties, previous size = 8
...

$ adb shell ps | grep system_server
system    731   441   1094884 89232 ffffffff b74d1d05 S system_server
$

最后,我强烈推荐视频教程Deep Dive Into Android IPC/Binder Framework来了解更多相关信息。演讲的幻灯片可以在这里找到。

于 2015-06-22T20:27:00.677 回答