IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> Android进阶解密读书笔记(六)——理解ActivityManagerService -> 正文阅读

[移动开发]Android进阶解密读书笔记(六)——理解ActivityManagerService

Android 7.0 和 Android 8.0 对于 AMS 相关部分处理有较大的区别

Android 7.0 的 AMS 家族

主要有三个类

  • ActivityManager

    ActivityManager 是一个和 AMS 相关联的类,它主要对运行中的 Activity 进行管理,这些管理工作并不是由 ActivityManager 来处理的,而是交由 AMS 来处理的

  • ActivityManagerNative(AMN)

    AMN 是一个抽象类,它将功能交由它的子类 AMS 来处理,这个类是一个Binder通信类

  • ActivityManagerProxy(AMP)

    ActivityManager 中的方法会通过 ActivityManagerNative(AMN)的 getDefault 方法来得到 ActivityManagerProxy

    AMP 是 AMN 的内部类,它们都实现了 IActivityManager 接口,这样它们就可以实现代理模式,具体来讲是远程代理:AMP 和 AMN 是运行在两个进程中的,AMP 是 Client 端,AMN 是 Server 端,而Server 端中具体的功能都是由 AMN 的子类 AMS 来实现的,因此,AMP 就是 AMS 在 Client 端的代理类

以 Android 7.0 的 Activity 启动过程来举例,在 Activity 的启动过程中会调用 Instrumentation 的 execStartActivity 方法

/*frameworks/base/core/java/android/app/Instrumentation.java*/
public ActivityResult execStartActivity(Context who, IBinder contextThread, IBinder token, Activity target, Intent intent, int requestCode, Bundle options){
    ...
    //调用 AMN 的 getDefault 来获取 AMS 的代理类 AMP,接着调用 AMP 的 startActivity 方法
    int result = ActivityManagerNative.getDefault().startActivity(...);
    ...
}

/*ActivityManagerNative.java*/
static public IActivityManager getDefault(){
    return gDefault.get();
}

private static final Singleton<IActivityManager> getDefault = new Singleton<IActivityManager>(){
    protected IActivityManager create(){
        //得到名为 "activity" 的 Service 引用,也就是 IBinder 类型的 AMS 的引用
        IBinder b = ServiceManager.getService("activity");
        ...
        //将该 Service 引用封装成 AMP 类型对象,并将它保存到 gDefault 中,此后调用 AMN 的 getDefault 方法就会直接获得 AMS 的代理对象 AMP
        IActivityManager am = asInterface(b);
    }
}

static public IActivityManager asInterface(IBinder obj){
    if(obj == null){
        return null;
    }
    //descriptor 值为 android.app.IActivityManager; 该处代码主要用来查询本地进程是否有 IActivityManager 接口实现,如果有则返回
    IActivityManager in = (IActivityManager) obj.queryLocalInterface(descriptor);
    if(in != null){
        return in;
    }
    //如果没有就将IBinder类型的 AMS 引用封装成 AMP 
    return new ActivityManagerProxy(obj);
}

class ActivityManagerProxy implements IActivityManager{
    //在构造方法中将 AMS 的引用赋值给变量 mRemote,这样在 AMP 中就可以使用 AMS 了
    public ActivityManagerProxy(IBinder remote){
        mReomte = remote;
    }
}

//再回到 Instrumentation 的 execStartActivity 方法,来看看 AMP 的 startActivity 方法。AMP 是 AMN 的内部类
/*ActivityManagerNative.java*/
public int startActivity(...) throws RemoteException{
    ...
    //将传入的参数写入到 Parcel 类型的 data 中
    data.writeInt(requestCode);
    data.writeInt(startFlags);
    ...
    //通过 IBinder 类型对象 mRemote (AMS的引用) 向服务器端的 AMS 发送一个 START_ACTIVITY_TRANSACTION 类型的进程间通信请求。那么服务器端 AMS 就会从 Binder 线程池中读取客户端发来的数据,最终调用 AMN 的 onTransact 方法
    mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0);
}

@Override
public boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException{
    switch(code){
            case START_ACTIVITY_TRANSACTION:
                ...
                int result = startActivity(aap, callingPackage, intetn, resolvedType, resultTo, resultWho, requestCode, startFlags, profilerInfo, options);
                reply.writeNoException();
                reply.writeInt(result);
                return true;
    }
}

//在 onTransact 方法中会调用 AMS 的 startActivity 方法
/*ActivityManagerService.java*/
public final int startActivity(IApplicationThread caller, ....){
    return startActivityAsUser(...);
}

//该方法中最后会调用到 ActivityStarter 的 startActivityMayWait 方法
public final int startActivityAsUser(...,int userId){
    ...
    return mActivityStarter.startActivityMayWait(...);
}

Android 8.0 的 AMS 家族

同样以 Activity 启动过程来举例,Android 8.0,在 Activity 的启动过程中会调用 Instrumentation 的 execStartActivity 方法

/*frameworks/base/core/java/android/app/Instrumentation.java*/
public ActivityResult execStartActivity(Context who, ...){
    ...
    int result = ActivityManager.getService().startActivity(...);
    ...
}

/* ActivityManager 的 getService 方法
* ActivityManager.java
*/
public static IActivityManager getService(){
    return IActivityManagerSingleton.get();
}

private static final Singleton<IActivityManager> IActivityManagerSingleton = new Singleton<IActivityManager>(){
    @Override
    protected IActivityManager create(){
        //得到名为 "activity" 的 Service 引用(Context.ACTIVITY_SERVICE的值为“activity”),也就是 IBinder 类型的 AMS 的引用
        final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
        // 将它转换成 IActivityManager 类型的对象,
        final IActivityManager am = IActivityManager.Stub.asInterface(b);
    }
}

IActivityManager.java 类是由 AIDL 工具在编译时自动生成的,IActivityManager.aidl 的文件路径为 framework/base/core/java/android/app/IActivityManager.aidl。要实现进程间通信,服务器端也就是AMS只需要继承 IActivityManager.Stub 类并实现相应的方法就可以了。采用 AIDL 后就不需要使用 AMS 的代理类 AMP 了

AMS 的启动过程

AMS 的启动是在 SystemServer 进程中启动的,我们从 SystemServer 的 main 方法

/*framworks/base/services/java/com/android/server/SystemServer.java*/
public static void main(String[] args){
    new SystemServer().run();
}

private void run(){
    try{
        ...
        //创建消息Looper
        Looper.prepareMainLooper();
        //加载动态库 libandroid_servers.so
        System.loadLibrary("android_servers");
        //创建 SystemServiceManager,它会对系统的服务进行创建、启动和生命周期管理
        mSystemServiceManager = new SystemServiceManager(mSystemContext);
        ...
        //启动引导服务。用 SystemServiceManager 启动 AMS、PowerManagerService、PackageManagerService等服务
        startBootstrapServices();    
        //启动核心服务。启动 DropBoxManagerService、BatteryService、UsageStatusService 和 WebViewUpdateService
        startCoreServices();
        //启动其他服务。启动 CameraService、AlarmManagerService、VrManagerService等服务
        startOtherServices();
    }
}

//接下来我们主要查看引导服务,AMS是如何启动的。也就是 startBootstrapServices()方法
private void startBootstrapServices(){
    ...
    traceBeginAndSlog("StartActivityManager");
    //调用 SystemServiceManager 的 startService 方法
    mActivityManagerService = mSystemServiceManager.startService(ActivityManagerService.Lifecycle.class).getService();
    mActivityManagerService.setSystemServiceManager(mSystemServiceManager);
    mActivityManagerService.setInstaller(installer);
    traceEnd();
    ...
}

/*SystemServiceManager.java*/
public void startService(final SystemService service){
    //将 service 对象添加到 ArrayList 类型的 mServices 中来完成注册
    mServices.add(service);
    //调用 service 的 onStart 方法来启动 service 对象
    service.onStart();
}

/** 这个 service 对象具体指的是什么呢?
* ActivityManagerService.Lifecycle.class 是 AMS 的内部类
* ActivityManagerService.java
*/
public static final class Lifecycle extends SystemService{
    private final ActivityManagerService mService;
    public Lifecycle(Context context){
        super(context);
        //在 Lifecycle 的构造方法中创建 AMS 实例
        mService = new ActivityManagerService(context);
    }
    
    @Override
    public void onStart(){
        //当调用 SystemService 类型的 service 的 onStart 方法时,实际上是调用了该处 AMS 的 start 方法
        mService.start()
    }
    
    //返回 AMS 实例,调用该方法实际上得到的就是 AMS 实例
    public ActivityManagerService getService(){
        return mService;
    }
}

AMS 与应用程序进程

在第二章系统启动中将到了 Zygote 的 java 框架层中,会创建一个 Server 端的 Socket,这个 Socket 用来等待 AMS 请求 Zygote 来创建新的应用程序进程。

要启动一个应用程序,首先要保证这个应用程序所需要的程序进程已经存在。在启动应用程序时 AMS 会检查这个应用程序需要的进程是否存在,不存在就会请求 Zygote 进程创建需要的应用程序进程

这里以 Service 的启动过程为例,来分析 AMS 与应用程序进程的关系。Service 在启动过程中会调用 ActiveServices 的 bringUpServiceLocked 方法

/*frameworks/base/services/core/java/com/android/server/am/ActiveServices.java*/
private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg, boolean whileRestarting, boolean permissionsReviewRequired) throws TransactionTooLargeException{
    ...
    //得到 ServiceRecord 的 processName 的值并赋值给 procName,processName 用来描述 Service 想要在哪个进程运行,默认是当前进程,我们可以在 AndroidManifest文件中设置 android:process 属性来开启一个新进程运行 Service
    final String procName = r.processName;
    ...
    //查询是否存在一个与 Service 对应的 ProcessRecord 类型的对象 app
    ProcessRecord app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false);
    //判断用来运行 Service 的应用进程是否存在
    if(app != null && app.thread != null){
        //启动 Service
        realStartServiceLocked(r, app, execInFg);
    }
    
    //如果用来运行 Service 的应用程序进程不存在
    if(app == null && !permissionReviewRequired){
        //使用 startProcessLocked() 方法创建对应的应用程序进程
        if((app = mAm.startProcessLocked(procName, r.appInfo, true, intentFlags, hostingType, r.name, false, isolated, false)) == null)
    }
}

AMS 与应用程序进程的关系主要有以下两点:

  • 启动应用程序时 AMS 会检查这个应用程序需要的应用程序进程是否存在

  • 如果需要的应用程序不存在,AMS 就会请求 Zygote 进程创建需要的应用程序进程

AMS 重要的数据结构

ActivityRecord

ActivityRecord 内部记录了 Activity 的所有信息,因此用来描述一个 Activity,它是在启动 Activity 时被创建的,具体是在 ActivityStarter 的 startActivity 方法中被创建的

ActivityRecord 的部分重要的成员变量如下表所示

名称类型说明
serviceActivityManagerServiceAMS 的引用
infoActivityInfoActivity中代码和AndroidManifest设置的节点信息,比如 launchMode
launchedFromPackageString启动 Activity 的包名
taskAffinityStringActivity 希望归属的栈
taskTaskRecordActivityRecord 所在的 TaskRecord
appProcessRecordActivityRecord 所在的应用程序进程
stateActivityState当前 Activity 的状态
iconintActivity 的图标资源标识符
themeintActivity 的主题资源标识符

TaskRecord

TaskRecord 用来描述一个 Activity 任务栈,内部存储了任务栈的所有信息,其中含有 ActivityStack,也就是当前 Activity 任务栈所归属的 ActivityStack

名称类型说明
taskIdint任务栈的唯一标识符
affinityString任务栈的倾向性
intentIntent启动这个任务栈的Intent
mActivitiesArrayList<ActivityRecord>按照历史顺序排列的 Activity 记录
mStackActivityStack当前归属的 ActivityStack
mServiceActivityManagerServiceAMS的引用

ActivityStack 是一个管理类,用来管理系统所有 Activity,其内部维护了 Activity 的所有状态、特殊状态的 Activity 以及和 Activity 相关的列表等数据。ActivityStack 是由 ActivityStackSupervisor 来进行管理的

taskAffinity

我们可以在 AndroidManifest.xml 中设置 android:taskAffinity,用来指定 Activity 希望归属的栈,在默认情况下,同一个应用程序的所有的 Activity 都有着相投的 taskAffinity

taskAffinity 在下面两种情况时会产生效果:

  1. taskAffinity 与 FLAG_ACTIVITY_NEW_TASK 或者 singleTask 配合。如果新启动 Activity 的 taskAffinity 和栈的 taskAffinity 相同则加入到该栈中;如果不同,就会创建新栈

  2. taskAffinity 与 allowTaskReparenting 配合。如果 allowTaskReparenting 为 true,说明 Activity 具有转移的能力

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2021-11-11 12:49:24  更:2021-11-11 12:50:24 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 3:43:38-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码