ActivityManagerService解析(一)AMS相关类简介

    ActivityManagerService(简称AMS)是Android三大核心的功能之一(其他两个是View,WindowManagerService),它的代码庞大(约2万行),逻辑纷繁,主要负责系统中四大组件的启动、切换、调度及应用程序进程的管理和调度等工作。对于这样庞大复杂的代码,我们应该从它的功能角度出发,分析它的每个功能对应的代码逻辑,逐个突破。

   ActivityManagerService是运行在SystemServer进程中众多服务中的一个(如:PackageManagerService,WindowManagerService等),这些服务分别运行在不同的线程中。其他进程需要通过binder机制来和ActivityManagerService跨进程通信,一个应用进程在和ActivityManagerService交互的过程中,还涉及到
ActivityThread,ApplicationThread等类的交互,下面将简单介绍这个几个类的相关概念,已经他们之间的交互模型。
(一)ActivityThread和ApplicationThread
    ActivityThread类代表的就是Android应用程序进程中的主线程,注意它代表主线程而不是说它就是一个Thread线程类,因为系统在创建完一个新应用程序进程后,会在这个进程的主线程中调用ActivityThread类的main函数来初始化这个进程,在这个main函数里会执行一个loop的循环使当前主线程进入消息循环,所以我们称Android应用程序进程的入口函数是ActivityThread类的main函数,也就是说一个ActivityThread类对应于一个应用程序进程。

public final class ActivityThread {
    
    ......

    final ApplicationThread mAppThread = new ApplicationThread();
    final Looper mLooper = Looper.myLooper();
    final H mH = new H();
    final ArrayMap<IBinder, ActivityClientRecord> mActivities = new ArrayMap<>();
    ......
    final ArrayMap<IBinder, Service> mServices = new ArrayMap<>();
    ......
    Application mInitialApplication;
    final ArrayList<Application> mAllApplications
            = new ArrayList<Application>();
    ......
    final ArrayMap<IBinder, ProviderClientRecord> mLocalProviders
        = new ArrayMap<IBinder, ProviderClientRecord>();
    ......
    private class ApplicationThread extends ApplicationThreadNative {
        ......
        
    }
    ......
}
  ActivityThread中有几个重要的实例变量简要说明一下,成员变量mActivities包含了当前进程中所有的Activity组件信息,注意集合中不是简单的保存Activity实例,而是将每个Activity实例对应的相关数据封装成一个ActivityClientRecord保存起来,内部保存了很多Activity相关的数据,其中当然也有其对应的Activity实例。同样的,mServices保存的是当前进程中所有的Service组件信息,不过就是直接存放的当前Service的信息,没有封装。mLocalProviders保存的是当前进程中所有的ContentProvider组件信息。这些集合都有一个IBinder类型的Key,其作用也就是显而易见的,即为了 进行IPC 调用,这个IBinder类型的Key也作为一个唯一标识使用,通过这个Key可以在AMS中找到其对应的组件信息记录。
    mAppThread是ApplicationThread类型的变量,它是ActivityThread的内部类,也是一个Binder类型的对象,也就是说可以作为服务端实现跨进程通信。那么,在应用进程中的ActivityThread通过Binder机制和系统进程中的AMS通信时,使用的就是ApplicationThread对象来作为应用进程的服务端,接收AMS的指令并将指令发送给ActivityThread执行,所以它ActivityThread
与AMS跨进程通信的桥梁。因为ApplicationThread对象会被Binder线程调用,而ActivityThread是运行在主线程中的,所以ApplicationThread会通过mH对象发送消息给主线处理。

(二)ActivityManagerService
    ActivityManagerService继承自ActivityManagerNative类,它是一个Binder本地对象,即可实现跨进程通信,也就是说它可以作为服务端提供具体的服务,接收其他进程中的ActivityManagerProxy的请求。
public class ActivityManagerService extends ActivityManagerNative
        implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
    ......
    final ActivityStackSupervisor mStackSupervisor;
    ......
    final ProcessMap<ProcessRecord> mProcessNames = new ProcessMap<ProcessRecord>();
    ......
    final SparseArray<ProcessRecord> mPidsSelfLocked = new SparseArray<ProcessRecord>();
}


    ActivityManagerService中有几个重要的数据结构,分别用来保存进程( Process )、四大组件(如 Activity )和任务( Task )等。
    (1)进程数据类 ProcessRecord
    一 个APK文件运行时会对应 一 个进程, 当然, 多个APK文件也可以运行在同 一 个进程中。ProcessRecord 正是记录 一 个进程中的相关信息, 该类中内部变量可分为三个部分,主要信息包括:该进程对应的APK文件的内部信息,该进程的内存状态信息,以及该进程中包含的所有Activity、Provider、Service等组件信息
final class ProcessRecord {
    ......
    final ApplicationInfo info; //进程中第一个APK包信息 
    ......
    final String processName;
    ......
    // List of packages running in the process
    final ArrayMap<String, ProcessStats.ProcessStateHolder> pkgList = new ArrayMap<>();
    ......
    IApplicationThread thread;
    ......
    int pid;
    ......
    final ArraySet<BroadcastRecord> curReceivers = new ArraySet<BroadcastRecord>();
    ......
    // all activities running in the process
    final ArrayList<ActivityRecord> activities = new ArrayList<>();
    // all ServiceRecord running in this process
    final ArraySet<ServiceRecord> services = new ArraySet<>();
    ......
    final ArrayMap<String, ContentProviderRecord> pubProviders = new ArrayMap<>();
}
(2)TaskRecord
     我们可以把一个应用程序想象成为了完成某一件事(当然也可以包括多件事),比如发邮件程序,

在Android中,

每一件事可以被看作是一个Task,一个Task又可以被细分成多个子步骤,每个子步骤可以被看作是一个Activity。这个Activity 既可以是本程序进程中的Activity,也可以是其他程序进程中的的Activity,这种基于组件的设计,弱化了进程的概念,

通过重用Activity可以节省一定的开销,同时为用户提供一致的界面和用户体验。比如,你在自己的程序中想发邮件,你就可以定义一个具有"send"动作的Intent,并且传入一些数据,如对方邮箱地址、邮件内容等,然后就会有系统的Activity被打开,发送完邮件,点击返回仍然还是会回到你的应用程序当中,这让用户看起来好像刚才那个编写邮件的Activity就是你的应用程序当中的一部分。所以说,即使有很多个Activity分别都是来自于不同应用程序的,Android系统仍然可以将它们无缝地结合到一起,之所以能实现这一点,就是因为这些Activity都是存在于一个相同的任务(Task)当中的。

   Task中有一个ActivityRecord的集合mActivities,它 是以Stack的方式来管理其中的Activity,所以,具有相同Task的Activity会放在同一个集合中(也叫回退栈),  先启动的Activity成为栈底成员,最后启动的Activity将作为栈顶成员显示在界面上。当有多个Task时,Android系统只支持一个处于前台的Task,其余的Task均处于后台,这些后台Task内部Activity保持顺序不变,用户可以一次将整个Task挪到后台或置为前台。比如,当用户在Home界面上点击了一个应用的图标时,这个应用的任务就会被转移到前台。如果这个应用目前并没有任何一个任务的话(说明这个应用最近没有被启动过),系统就会去创建一个新的任务,并且将该应用的主Activity放入到返回栈当中。如果用户一直地按Back键,这样返回栈中的Activity会一个个地被移除,直到最终返回到主屏幕。当返回栈中所有的Activity都被移除掉的时候,对应的任务也就不存在了。用过Android手机的读者应该知道,长按Home键,系统会弹出近期Task列表,使用户能快速在多个Task间切换。

final class TaskRecord extends ConfigurationContainer implements TaskWindowContainerListener {
    
    ......
    final int taskId;       // Unique identifier for this task.
    String affinity;        // The affinity name for this task, or null; may change identity.
    ......
    /** List of all activities in the task arranged in history order */
    final ArrayList<ActivityRecord> mActivities;

    /** Current stack. Setter must always be used to update the value. */
    private ActivityStack mStack;//当前任务的管理者
    
    ......
}
    TaskRecord 的affinity属性是第一次创建这个task时指定的值,可以把他当作这个Task的名字,Activity所在的Task可以通过AndroidManifest.xml中<Activity>标签中的android:taskAffinity="xxx"来指定,通常不去主动设置一个Activity的taskAffinity属性,那么taskAffinity的值缺省使用包名。所以,同一个应用中所有的Activity的taskAffinity属性值默认都是相同的,都是包名,所以在应用中使用FLAG_ACTIVITY_NEW_TASK标志去启动一个本应用中的一个Activity,也不会创建一个新的task,除非这个Activity 额外指定了不同的taskAffinity属性值。
    (3)ActivityRecord
     AMS 中使用 ActivityRecord数据类来保存每个 Activity 的相关信息,该数据类中的变量主要包含两部分,一是配置信息:该Activity组件相关的XML中配置信息 , 比如 , 属于哪个Package , 所在的进程名称、任务名、组件类名、logo、主题,等等,这些 信息 基本上是固定的;二是运行状态信息:比如idle、stop、fishing等,这些变量 一般为boolean类型,这些状态值与应用程序中所说的onCreate、onPause、onStart等生命周期 状态有所不同。

final class ActivityRecord extends ConfigurationContainer implements AppWindowContainerListener {
    ......
    final ActivityManagerService service; // owner
    final IApplicationToken.Stub appToken; token用来和wms交互
    final ActivityInfo info; // all about me
    final ApplicationInfo appInfo; // information about activity's app
    ......
    final Intent intent;    // the original intent that generated us
    final ComponentName realActivity;  // the intent component, or target of an alias.
    final String resolvedType; // as per original caller;
    final String packageName; // the package implementing intent's component
    final String processName; // process where this component wants to run
    final String taskAffinity; // as per ActivityInfo.taskAffinity
    ......
    int mActivityType;
    ......
    private int logo;               // resource identifier of activity's logo.
    private int theme;              // resource identifier of activity's theme.
    private TaskRecord task;
    ......
    ProcessRecord app;      // if non-null, hosting application
    ActivityState state;    // current state we are in
    ......
}
    (4)ActivityStack    
    对于多个Task的组织及管理方式,Android设计了一个ActivityStack类来负责上述工作,ActivityStack用mTaskHistory这个ArrayList保存所有属于该ActivityStack的TaskRecord实例(这个集合叫做任务栈)。另外ActivityStack有三种类型:mHomeStack,mFocusedStack及mLastFocusedStack,在ActivityStack中用mStackId 来标识。
class ActivityStack<T extends StackWindowController> extends ConfigurationContainer
        implements StackWindowListener {
    ...... 
    private final ArrayList<TaskRecord> mTaskHistory = new ArrayList<>(); 
    ......
    final int mStackId;
    ......
    /** Run all ActivityStacks through this */
    protected final ActivityStackSupervisor mStackSupervisor;
}
提示: Android 在4.4版本之前的的栈结构与现在的不同,请看下面4.4之前的代码结构
public class ActivityStack {
    ......
    final boolean mMainStack;
    ......
    final ArrayList<ActivityRecord> mHistory = new ArrayList<ActivityRecord>();
    
}
    
class TaskRecord extends ThumbnailHolder {
    ......
    int numActivities;    
    ......
}

   在Android 在4.4版本之前,ActivityStack类型只有一个:mMainStack,并且 ActivityStack用mHistory这个ArrayList保存所有的ActivityRecord,令人大跌眼镜的是,该mHistory保存了系统中所有Task的ActivityRecord,而不是针对某个Task进行保存。这种实现方式有优点亦有缺点,优点是:少了TaskRecord一级的管理,直接以ActivityRecord为管理单元,这种做法能降低管理方面的开销;缺点是:弱化了Task的概念,结构不够清晰。虽然栈结构变化,但是设计理念还是不变的。

    (5)ActivityStackSupervisor
     在 Android4.4 以后,并不采用原先的 mHistory 来管理所有的ActivityRecord ,而是按层次进行管理,这其中就引入了一个新的类:ActivityStackSupervisor,用来管理所有的 ActivityStack(之前只有一个mMainStack,由AMS来管理的 )。

public class ActivityStackSupervisor extends ConfigurationContainer implements DisplayListener {
    ......
    final ActivityManagerService mService;
    ......
    WindowManagerService mWindowManager;
    DisplayManager mDisplayManager;
    ......
    ActivityStack mHomeStack;
    ActivityStack mFocusedStack;
    private ActivityStack mLastFocusedStack;
    ......
    /** Mapping from (ActivityStack/TaskStack).mStackId to their current state */
    SparseArray<ActivityStack> mStacks = new SparseArray<>();
}
  mHomeStack 中只保存了 Launcher APP中相关的Task,包括Launcher、RecentTask,Keyguad,,除此之外的其他 Task 则都放入 mFocusStack 中管理,mStacks以键值的方式保存了所有 的ActivityStack,用来查询所需要的 ActivityStack,其中的键是StackId。
    (三)ActivityThread和AMS通信模型
    ActivityManagerService运行在system_server进程中的,它是一个继承于ActivityManagerNative的Binder本地对象,提供具体的服务, ActivityManagerProxy对象是ActivityManagerService在普通应用进程的一个Binder代理对象,应用进程通过ActivityManagerProxy对象远程调用ActivityManagerService提供的功能。
    ApplicationThread对象运行在普通应用进程中的,它是一个继承自 ApplicationThreadNative的Binder本地对象,提供具体的服务,ApplicationThreadProxy对象是ApplicationThread对象在system_server进程中的Binder代理对象,ActivityManagerService通过ApplicationThreadProxy对象调用ApplicationThread提供的功能,而 ApplicationThread又会将请求发送给ActivityThread来做具体的事情
    应用程序进程的ActivityThread和系统进程中的AMS通信模型如下图

    这样的设计在安卓系统中很通用,有一点需要额外留意的,大部分App调用到system_server端的接口是非ONEWAY的,也就是同步调用,应用需要等待system_server执行完成。大部分system_server调用到App端的接口是ONEWAY的,也就是异步调用,system_server的服务不需要等待应用完成操作。这样的设计保证了system_server不会收到App处理快慢的影响。




  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值