某学姐

Android Female Developer,Technology Fan,Reader。

AIDL过程

2020-02-08 | Comments

基于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.StubIActivityManager.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端AMPServer端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端AMPServer端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的类继承关系:
service-manager
图2为Java层AMS的类继承关系:
activity-manager-service

很容易看到,两者基本上一样.
我们可以理解成: 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代码实现.

本文原文发自 某学姐, 转载请保留出处, 谢谢.

Comments