ActivityManagerService(简称AMS)是Android三大核心的功能之一(其他两个是View,WindowManagerService),它的代码庞大(约2万行),逻辑纷繁,主要负责系统中四大组件的启动、切换、调度及应用程序进程的管理和调度等工作。对于这样庞大复杂的代码,我们应该从它的功能角度出发,分析它的每个功能对应的代码逻辑,逐个突破。
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 {
......
}
......
}
成员变量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
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<>();
}
包括Launcher、RecentTask,Keyguad,,除此之外的其他 Task 则都放入
mFocusStack 中管理,mStacks以键值的方式保存了所有
的ActivityStack,用来查询所需要的
ActivityStack,其中的键是StackId。
ActivityThread和AMS通信模型
ActivityManagerService运行在system_server进程中的,它是一个继承于ActivityManagerNative的Binder本地对象,提供具体的服务, ActivityManagerProxy对象是ActivityManagerService在普通应用进程的一个Binder代理对象,应用进程通过ActivityManagerProxy对象远程调用ActivityManagerService提供的功能。
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处理快慢的影响。