AMS处理的逻辑多而复杂,因此AMS并不是“孤军奋战”,而是有一些类和它“共同奋战”,这些类会帮助AMS完成相关逻辑,AMS和这些“共同奋战”的类就被称为AMS家族。Android 7.0Android 8.0对于AMS相关部分的处理有较大的区别,为了更好地理解AMS家族,这里将分别介绍Android 7.0Android 8.0AMS家族。

Android 7.0的AMS家族

ActivityManager是一个和AMS相关联的类,它主要对运行中的Activity进行管理,这些管理工作并不是由ActivityManager来处理的,而是交由AMS来处理的。一般而言,ActivityManager 中的方法是会通过ActivityManagerNative(下面简称AMN)的getDefault方法来得到ActivityManagerProxy(下面简称 AMP ),通过 AMP 就可以和AMN进行通信,而AMN是一个抽象类,它将功能交由它的子类AMS来处理,因此,AMP就是AMS的代理类。AMS作为系统服务,很多API是不会暴露给ActivityManager的,因此ActivityManager不算是AMS家族的一份子。为了讲解AMS家族,这里以Android 7.0Activity启动过程来举例,在Activity的启动过程中会调用InstrumentationexecStartActivity方法,如下所示

Android进阶解密:探访AMS家族_java

execStartActivity方法中会调用AMNgetDefault方法来获取 AMS 的代理类 AMP ,接着调用了 AMP startActivity方法。下面先来查看AMNgetDefault方法做了什么,如下所示:

Android进阶解密:探访AMS家族_java_02

getDefault方法中调用了gDefaultget方法,接着往下看,gDefault是一个Singleton。在注释1处得到名为“activity”的Service引用,也就是IBinder类型的AMS的引用。然后在注释2处将它封装成AMP类型对象,并将它保存到 gDefault 中,此后调用 AMN getDefault方法就会直接获得AMS的代理对象AMP。注释2处的asInterface方法如下所示:

Android进阶解密:探访AMS家族_java_03

android.app.IActivityManager注释1处的descriptor值,注释1处的代码主要用来查询本地进程是否IActivityManager接口的实现。如果有,则返回;如果没有,就在注释2处将IBinder类型的AMS引用封装成AMPAMP的构造方法如下所示:

Android进阶解密:探访AMS家族_java_04

在 AMP 的构造方法中,将 AMS 的引用赋值给变量mRemote,这样在AMP中就可以使用AMS了。其中IActivityManager是一个接口,AMNAMP都有这个接口,用于实现代理模式以及 Binder 通信。再回到InstrumentationexecStartActivity方法,来查看AMPstartActivity方法,AMPAMN的内部类,代码如下所示:

Android进阶解密:探访AMS家族_java_05

首先将传入的参数写入Parcel类型的data中。在注释1处,通过IBinder类型对mRemoteAMS的引用)向服务器端的 AMS 发送一个进程间通信请求,类型则为START_ACTIVITY_TRANSACTION。那么服务器端AMS就会从Binder线程池中读取客户端发来的数据,最终会调用AMNonTransact方法,如下所示:

onTransact方法中会调用AMSstartActivity方法,如下所示:

startActivity方法最后会返回startActivityAsUser方法,如下所示:

startActivityAsUser方法最后会返回ActivityStarterstartActivityMayWait方法,这一调用过程已经脱离了本节要介绍的AMS家族的范畴,因此这里不做赘述了,具体的调用过程,则可以查看 4.1.2 节的内容。在Activity的启动过程中提到AMPAMNAMS,它们共同组成了AMS家族的主要部分,如图1所示。

1  Android 7.0 AMS家族

AMPAMN的内部类,都实现了IActivityManager接口,这样它们就可以实现代理模式,具体来讲就是远程代理:AMPAMN是运行在两个进程中的,AMPClient端,AMN则是Server端,而Server端中具体的功能都是由AMN的子类AMS来实现的。因此AMP就是AMSClient端的代理类。AMN又实现了Binder类,这样AMPAMS就可以通过Binder来进行进程间通信。ActivityManager通过AMNgetDefault方法得到AMP,通过 AMP 我们就可以和AMS进行通信。除ActivityManager以外,有些想要与AMS进行通信的类也需要通过AMP,如图2所示。

Android进阶解密:探访AMS家族_java_06

2  AMPAMS进行通信

从图2看出,除ActivityManager外, ContextImpl如果想要和AMS进行通信也需要先经过AMP

Android 8.0的AMS家族

Android 8.0AMS家族与Android 7.0有一些区别,为了更好地理解这些区别,我们仍旧以Activity启动过程来举例,只不过现在系统版本是Android 8.0,在Activity的启动过程中会调用InstrumentationexecStartActivity方法,如下所示:

Android进阶解密:探访AMS家族_java_07

ActivityManagergetService方法,如下所示:

Android进阶解密:探访AMS家族_java_08

IActivityManagerSingleton 一个Singleton类,getService方法调用了get方法。在注释1处得到名为“activity”的Service引用,也就是IBinder类型的AMS的引用。接着,我们可在注释2处将它转换成IActivityManager类型的对象。注意,这段代码采用AIDLIActivityManager.java类是由AIDL工具在编译时自动生成,IActivityManager.aidl的文件路径为frameworks/base/core/java/android/app/IActivityManager.aidl。要实现进程间通信,服务器端(也就是AMS)只需要继承IActivityManager.Stub类并实现相应的方法就可以了。采用AIDL后就不需要使用AMS的代理类AMP了,因此Android 8.0去掉了AMP,代替它的是IActivityManager,它是AMS在本地的代理。让我们再一次回到 Instrumentation execStartActivity方法,在注释1处实际上调用的是AMSexecStartActivity方法。剩下的调用过程就不再介绍了,我们来查看Android 8.0AMS家族,如图3所示。

Android进阶解密:探访AMS家族_java_09

3  Android 8.0 AMS家族

对比图3和图1,可以发现Android 8.0 AMS家族要简单得多,ActivityManager 的 getService 方法会得到 IActivityManager。正因如此,AMS只需要继承IActivityManager.Stub类,就可以方便地和ActivityManager实现进程间通信了。

————

本文节选自Android进阶解密一书。作为“Android进阶系列”的第二部,本书是继畅销书《Android进阶之光》之后,刘望舒的又一力作!本书基于Android 8.0,将系统源码和应用开发结合讲解,帮助读者融会贯通,破解Android应用开发进阶秘密。阅读原文将带你抢先一睹这本由安卓名家何红辉、徐宜生 、何俊林、潘辰星、周泰良、杨强、Tamic及安卓巴士技术社区联袂力荐的烫手新书。