基于Android 10.0的源码剖析, 站在Luoshengyang/Innost/Gityuan肩膀上.
本文以startService为切入点分析aidl原理.
0.文件结构
frameworks/base/core/java/android/app/IActivityManager.aidl
frameworks/base/core/java/android/os/Binder.java
frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
frameworks/base/core/jni/android_util_Binder.cpp
frameworks/native/libs/binder/IPCThreadState.cpp
frameworks/native/libs/binder/Binder.cpp
1.时序图
TODO
2.入口函数
真正的startService是由AMS负责启动的.
客户端需要先和ServiceManager进程进行Binder通信拿到AMP,然后和AMS进程进行Binder通信启动服务.
转化成代码就是:
// 拿到BinderProxy对象
final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
// 拿到AMP对象
final IActivityManager am = IActivityManager.Stub.asInterface(b);
// AMP.startService
am.startService(...);
关于ServiceManager.getService
过程, Service获取过程 这篇文章已经分析.
本文主要分析:
// 拿到AMP对象
final IActivityManager am = IActivityManager.Stub.asInterface(b);
// AMP.startService
am.startService(...);
而这部分用到了aidl机制,我们先从aidl文件入手.
3.IActivityManager.aidl
[ -> frameworks/base/core/java/android/app/IActivityManager.aidl ]
interface IActivityManager {
...
ComponentName startService(in IApplicationThread caller,
in Intent service, in String resolvedType,
boolean requireForeground, in String callingPackage,
int userId);
...
}
4.IActivityManager.java
我们还原IActivityManager.aidl编译成Java文件后的产物.
public interface IActivityManager extends android.os.IInterface
{
/** Local-side IPC implementation stub class. */
public static abstract class Stub extends android.os.Binder
implements android.app.IActivityManager
{
private static final java.lang.String DESCRIPTOR = "android.app.IActivityManager";
/** Construct the stub at attach it to the interface. */
public Stub()
{
this.attachInterface(this, DESCRIPTOR);
}
// Cast an IBinder object into an android.app.IActivityManager interface,
// generating a proxy if needed.
public static android.app.IActivityManager asInterface(android.os.IBinder obj)
{
if ((obj==null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin!=null)&&(iin instanceof android.app.IActivityManager))) {
return ((android.app.IActivityManager)iin);
}
return new android.app.IActivityManager.Stub.Proxy(obj);
}
@Override public android.os.IBinder asBinder()
{
return this;
}
@Override public boolean onTransact(int code,
android.os.Parcel data, android.os.Parcel reply,
int flags) throws android.os.RemoteException
{
java.lang.String descriptor = DESCRIPTOR;
switch (code)
{
case INTERFACE_TRANSACTION:
{
reply.writeString(descriptor);
return true;
}
case TRANSACTION_startService:
{
data.enforceInterface(descriptor);
IApplicationThread _arg0 = (IApplicationThread) data.readStrongBinder();
Intent _arg1 = (Intent) data.readParcelable();
java.lang.String _arg2 = data.readString();
boolean _arg3 = (0!=data.readInt());
java.lang.String _arg4 = data.readString();
int _arg5 = data.readInt();
android.content.ComponentName _result = this.startService(_arg0, _arg1,
_arg2, _arg3, _arg4, _arg5);
reply.writeNoException();
if ((_result!=null)) {
reply.writeInt(1);
_result.writeToParcel(reply,
android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
} else {
reply.writeInt(0);
}
return true;
}
default:
{
return super.onTransact(code, data, reply, flags);
}
}
}
private static class Proxy implements android.app.IActivityManager
{
private android.os.IBinder mRemote;
Proxy(android.os.IBinder remote)
{
mRemote = remote;
}
@Override public android.os.IBinder asBinder()
{
return mRemote;
}
public java.lang.String getInterfaceDescriptor()
{
return DESCRIPTOR;
}
@Override
public android.content.ComponentName startService(
in IApplicationThread caller, in Intent service,
java.lang.String resolvedType, boolean requireForeground,
java.lang.String callingPackage, int userId)
throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
android.content.ComponentName _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeStrongBinder(caller);
_data.writeParcelable(service);
_data.writeString(resolvedType);
_data.writeInt(((requireForeground)?(1):(0)));
_data.writeString(callingPackage);
_data.writeInt(userId);
mRemote.transact(Stub.TRANSACTION_startService, _data, _reply, 0);
_reply.readException();
if ((0!=_reply.readInt())) {
_result = android.content.ComponentName.CREATOR.createFromParcel(_reply);
} else {
_result = null;
}
} finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
}
static final int TRANSACTION_startService = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
}
public android.content.ComponentName startService(
in IApplicationThread caller, in Intent service,
java.lang.String resolvedType, boolean requireForeground,
java.lang.String callingPackage, int userId)
throws android.os.RemoteException;
}
可以看到类IActivityManager生成了2个子类: IActivityManager.Stub
和IActivityManager.Stub.Proxy
5.IActivityManager.Stub.asInterface
final IActivityManager am = IActivityManager.Stub.asInterface(b)
等价于new android.app.IActivityManager.Stub.Proxy(obj)
再分析AMP.startService, AMP即IActivityManager.Stub.Proxy.
6.AMP.startService
即IActivityManager.Stub.Proxy#startService. 剩下的工作其实就是Client端AMP
和Server端AMS
怎么进行Binder通信来启动服务的?
作为App开发者, 我们已知有如下调用关系:
AMP.startService() -> mRemote.transact() ->
IActivityManager.Stub.onTransact() -> IActivityManager.startService()
我们根据IActivityManager.java的代码可知: AMP.startService() -> mRemote.transact()
和IActivityManager.Stub.onTransact() -> IActivityManager.startService()
这里主要搞清楚的就是: mRemote.transact() -> IActivityManager.Stub.onTransact()
这个过程的具体原理.
之前已经分析过mRemote是BinderProxy(handle)对象. 且有如下调用链:
BinderProxy.transact -> BinderProxy.transactNative -> android_os_BinderProxy_transact ->
BpBinder.transact -> IPCThreadState.transact -> IPCThreadState.writeTransactionData ->
IPCThreadState.waitForResponse
在介绍Client端AMP
和Server端AMS
进行Binder通信的具体细节之前,我们先回顾一下 Service注册过程–Java服务 Binder通信过程:
- (1) BC_TRANSACTION过程 (源线程 -> Binder驱动)
- (2) BR_TRANSACTION_COMPLETE过程 (Binder驱动 -> 源线程)
- (3) BR_TRANSACTION过程 (Binder驱动 -> SM进程)
- (4) BC_REPLY过程 (SM进程 -> Binder驱动)
- (5) BR_TRANSACTION_COMPLETE过程 (Binder驱动 -> SM进程)
- (6) BR_REPLY过程 (Binder驱动 -> 源线程)
AMP.startService的Binder通信过程(看下文分析):
- (1) BC_TRANSACTION过程 (源线程 -> Binder驱动)
- (2) BR_TRANSACTION_COMPLETE过程 (Binder驱动 -> 源线程)
- (3) BR_TRANSACTION过程 (Binder驱动 -> AMS进程)
- (4) BC_REPLY过程 (AMS进程 -> Binder驱动)
- (5) BR_TRANSACTION_COMPLETE过程 (Binder驱动 -> AMS进程)
- (6) BR_REPLY过程 (Binder驱动 -> 源线程)
所有步骤都是一样的. 从代码角度来说, 只有步骤3存在一点点不同.
6.1 IPCThreadState
[ -> frameworks/native/libs/binder/IPCThreadState.cpp ]
6.1.1 waitForResponse
步骤(3)BR_TRANSACTION过程 (Binder驱动 -> AMS进程)
主要是AMS进程被唤醒并执行todo队列任务. cmd为BR_TRANSACTION, 这个过程会走到executeCommand.
status_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult)
{
uint32_t cmd;
int32_t err;
while (1) {
// 和Binder驱动交互,执行Binder读写操作
if ((err=talkWithDriver()) < NO_ERROR) break;
cmd = (uint32_t)mIn.readInt32();
switch (cmd) {
case BR_TRANSACTION_COMPLETE: ...
case BR_DEAD_REPLY: ...
case BR_FAILED_REPLY: ...
case BR_ACQUIRE_RESULT: ...
case BR_REPLY: ...
default:
err = executeCommand(cmd);
break;
}
}
return err;
}
6.1.2 executeCommand
status_t IPCThreadState::executeCommand(int32_t cmd)
{
BBinder* obj;
RefBase::weakref_type* refs;
status_t result = NO_ERROR;
switch ((uint32_t)cmd) {
...
case BR_TRANSACTION:
{
binder_transaction_data& tr = tr_secctx.transaction_data;
Parcel reply;
status_t error;
if (tr.target.ptr) {
if (reinterpret_cast<RefBase::weakref_type*>(
tr.target.ptr)->attemptIncStrong(this)) {
// BBinder.transact
error = reinterpret_cast<BBinder*>(tr.cookie)->
transact(tr.code, buffer, &reply, tr.flags);
reinterpret_cast<BBinder*>(tr.cookie)->decStrong(this);
} else {
error = UNKNOWN_TRANSACTION;
}
} else {
error = the_context_object->transact(tr.code,
buffer, &reply, tr.flags);
}
if ((tr.flags & TF_ONE_WAY) == 0) {
LOG_ONEWAY("Sending reply to %d!", mCallingPid);
if (error < NO_ERROR) reply.setError(error);
// 同步通信, 发送结果
sendReply(reply, 0);
} else {
LOG_ONEWAY("NOT sending reply to %d!", mCallingPid);
}
break;
}
...
}
return result;
}
6.2 BBinder
6.2.1 transact
[ -> frameworks/native/libs/binder/Binder.cpp ]
// code为TRANSACTION_startService
status_t BBinder::transact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
data.setDataPosition(0);
switch (code) { // TRANSACTION_startService
case PING_TRANSACTION:
reply->writeInt32(pingBinder());
break;
default:
err = onTransact(code, data, reply, flags);
break;
}
return err;
}
6.2.2 onTransact
[ -> frameworks/base/core/jni/android_util_Binder.cpp ]
class JavaBBinder : public BBinder
{
status_t onTransact(uint32_t code, const Parcel& data,
Parcel* reply, uint32_t flags = 0) override
{
JNIEnv* env = javavm_to_jnienv(mVM);
// Binder.execTransact
jboolean res = env->CallBooleanMethod(mObject, gBinderOffsets.mExecTransact,
code, reinterpret_cast<jlong>(&data), reinterpret_cast<jlong>(reply), flags);
if (code == SYSPROPS_TRANSACTION) {
BBinder::onTransact(code, data, reply, flags);
}
return res != JNI_FALSE ? NO_ERROR : UNKNOWN_TRANSACTION;
}
}
6.3 Binder
6.3.1 execTransact
[ -> frameworks/base/core/java/android/os/Binder.java ]
private boolean execTransact(int code, long dataObj, long replyObj, int flags) {
return execTransactInternal(code, dataObj, replyObj, flags, callingUid);
}
private boolean execTransactInternal(int code, long dataObj, long replyObj,
int flags, int callingUid) {
Parcel data = Parcel.obtain(dataObj);
Parcel reply = Parcel.obtain(replyObj);
res = onTransact(code, data, reply, flags);
reply.recycle();
data.recycle();
return res;
}
6.3.2 onTransact
[ -> IActivityManager.java ]
public interface IActivityManager extends android.os.IInterface
{
/** Local-side IPC implementation stub class. */
public static abstract class Stub extends android.os.Binder
{
@Override public boolean onTransact(int code,
android.os.Parcel data, android.os.Parcel reply,
int flags) throws android.os.RemoteException
{
java.lang.String descriptor = DESCRIPTOR;
switch (code)
{
case TRANSACTION_startService:
{
data.enforceInterface(descriptor);
IApplicationThread _arg0 = (IApplicationThread) data.readStrongBinder();
Intent _arg1 = (Intent) data.readParcelable();
java.lang.String _arg2 = data.readString();
boolean _arg3 = (0!=data.readInt());
java.lang.String _arg4 = data.readString();
int _arg5 = data.readInt();
// IActivityManager.startService
android.content.ComponentName _result = this.startService(_arg0, _arg1,
_arg2, _arg3, _arg4, _arg5);
reply.writeNoException();
if ((_result!=null)) {
reply.writeInt(1);
_result.writeToParcel(reply,
android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
} else {
reply.writeInt(0);
}
return true;
}
}
}
}
}
接下来再看一下AIDL的类继承关系.
6.4 AIDL类继承关系
图1为Java层ServiceManager的类继承关系:
图2为Java层AMS的类继承关系:
很容易看到,两者基本上一样.
我们可以理解成: Android中的Java服务没必要每次都重复手写IXXXManager/XXXManagerNative/XXXManagerProxy
这样的3个类. 可以通过AIDL-Android接口定义语言
编译后自动生成对等的IXXXManager/Stub/Proxy
这样3个类.
而且我们通过这个也可以知道,最终走到了ActivityManagerService.startService, 从而真正启动服务.
6.5 IPCThreadState.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);
}
从BC_REPLY开始,剩下的流程和Service注册过程–Java服务 Binder通信过程差不多.
7.总结
Client调用Java服务 和 Client向ServiceManager进程注册或获取服务 这两个Binder通信过程差不多.
不同的是SM服务这一过程全部由Java代码实现; 而Android系统由于Java服务众多且便于自定义Java服务, 采用AIDL - Android接口定义语言经编译后自动生成相关Java代码实现.