一、概况
ActivityManagerService(AMS)是Android中最核心的服务,主要负责系统中四大组件的启动、切换、调度及应用程序的管理和调度等工作。
AMS通信结构如下图所示:
从图中可以看出:
1、AMS继承自ActivityManagerNative(AMN),并实现了Watchdog.Monitor和BatteryStatsImpl.BatteryCallback接口。
2、AMN继承Java的Binder类,同时实现了IActivityManager接口,即AMN将作为Binder通信的服务端为用户提供支持。
3、在ActivityManagerNative类中定义了内部类ActivityManagerProxy,该类同样实现了IActivityManager接口,将作为客户端使用的服务端代理。
4、其它进程将使用ActivityManager来使用AMS的服务。ActivityManager通过AMN提供的getDefault接口得到ActivityManagerProxy,然后再以Binder通信的方式调用AMS的接口。
对AMS的基本情况有一个大概的了解后,我们一起来分析一下AMS的启动过程。
由于AMS启动涉及的内容比较多,我们将分段进行分析。
二、createSystemContext
在进入到AMS相关的流程前,我们需要先了解一下相关的准备工作。
我们已经知道了,zygote创建出的第一个java进程是SystemServer。
在SystemServer的run函数中,在启动AMS之前,调用了createSystemContext函数。
其代码如下所示:
.............
//SystemServer在启动任何服务之前,就调用了createSystemContext
//创建出的Context保存在mSystemContext中
// Initialize the system context.
createSystemContext();
// Create the system service manager.
//SystemServiceManager负责启动所有的系统服务,使用的Context就是mSystemContext
mSystemServiceManager = new SystemServiceManager(mSystemContext);
.............
我们跟进一下createSystemContext:
private void createSystemContext() {
//调用ActivityThread的systemMain函数,其中会创建出系统对应的Context对象
ActivityThread activityThread = ActivityThread.systemMain();
//取出上面函数创建的Context对象,保存在mSystemContext中
mSystemContext = activityThread.getSystemContext();
//设置系统主题
mSystemContext.setTheme(DEFAULT_SYSTEM_THEME);
}
以上函数中,最重要的就是ActivityThread.systemMain了,我们分析一下该函数。
1、ActivityThread.systemMain
public static ActivityThread systemMain() {
// The system process on low-memory devices do not get to use hardware
// accelerated drawing, since this can add too much overhead to the
// process.
if (!ActivityManager.isHighEndGfx()) {
//虽然写着ActivityManager,但和AMS没有任何关系
//就是利用系统属性和配置信息进行判断
//关闭硬件渲染功能
ThreadedRenderer.disable(true);
} else {
ThreadedRenderer.enableForegroundTrimming();
}
//创建ActivityThread
ActivityThread thread = new ActivityThread();
//调用attach函数,参数为true
thread.attach(true);
return thread;
}
从上面的代码可以看出,ActivityThread的systemMain函数中,除了进行是否开启硬件渲染的判断外,主要作用是:
创建出ActivityThread对象,然后调用该对象的attach函数。
ActivityThread的构造函数比较简单:
ActivityThread() {
mResourcesManager = ResourcesManager.getInstance();
}
比较关键的是它的成员变量:
..........
//定义了AMS与应用通信的接口
final ApplicationThread mAppThread = new ApplicationThread();
//拥有自己的looper,说明ActivityThread确实可以代表事件处理线程
final Looper mLooper = Looper.myLooper();
//H继承Handler,ActivityThread中大量事件处理依赖此Handler
final H mH = new H();
//用于保存该进程的ActivityRecord
final ArrayMap<IBinder, ActivityClientRecord> mActivities = new ArrayMap<>()
..........
//用于保存进程中的Service
final ArrayMap<IBinder, Service> mServices = new ArrayMap<>();
...........
//用于保存进程中的Application
final ArrayList<Application> mAllApplications = new ArrayList<Application>();
...........
我们需要知道的是,ActivityThread是Android Framework中一个非常重要的类,它代表一个应用进程的主线程,其职责就是调度及执行在该线程中运行的四大组件。
在Android中,应用进程指那些运行APK的进程,它们由zygote fork出来,其中运行着独立的dalvik虚拟机。
与应用进程相对的就是系统进程,例如zygote和SystemServer。
注意到此处的ActivityThread创建于SystemServer进程中。
由于SystemServer中也运行着一些系统APK,例如framework-res.apk、SettingsProvider.apk等,因此也可以认为SystemServer是一个特殊的应用进程。
对于上面提到的ActivityThread的成员变量,其用途基本上可以从名称中得知,这里仅说明一下ApplicationThread。
AMS负责管理和调度进程,因此AMS需要通过Binder机制和应用进程通信。
为此,Android提供了一个IApplicationThread接口,该接口定义了AMS和应用进程之间的交互函数。
如上图所示,ActivityThread作为应用进程的主线程代表,在其中持有ApplicationThread。ApplicationThread继承ApplicationThreadNative。
当AMS与应用进程通信时,ApplicationThread将作为Binder通信的服务端。
AMS与应用进程通信时,通过ApplicationThreadNative获取应用进程对应的ApplicationThreadProxy对象。
通过ApplicationThreadProxy对象,将调用信息通过Binder传递到ActivityThread中的ApplicationThread。
这个调用过程,今后还会遇到,碰到的时候再详细分析。
2、ActivityThread.attach
我们看看ActivityThread的attach函数:
//此时,我们传入的参数为true,表示该ActivityThread是系统进程的ActivityThread
private void attach(boolean system) {
//创建出的ActivityThread保存在类的静态变量sCurrentActivityThread
//AMS中的大量操作将会依赖于这个ActivityThread
sCurrentActivityThread = this;
mSystemThread = system;
if (!system) {
//应用进程的处理流程
..........
} else {
//系统进程的处理流程,该情况只在SystemServer中处理
// Don't set application object here -- if the system crashes,
// we can't display an alert, we just want to die die die.
//设置DDMS(Dalvik Debug Monitor Service)中看到的SystemServer进程的名称为“system_process”
android.ddm.DdmHandleAppName.setAppName("system_process",
UserHandle.myUserId());
try {
//创建ActivityThread中的重要成员:Instrumentation、Application和Context
mInstrumentation = new Instrumentation();
ContextImpl context = ContextImpl.createAppContext(
this, getSystemContext().mPackageInfo);
mInitialApplication = context.mPackageInfo.makeApplication(true, null);
mInitialApplication.onCreate();
} catch (Exception e) {
throw new RuntimeException(
"Unable to instantiate Application():" + e.toString(), e);
}
}
//以下系统进程和非系统进程均会执行
................
//注册Configuration变化的回调通知
ViewRootImpl.addConfigCallback(new ComponentCallbacks2() {
@Override
public void onConfigurationChanged(Configuration newConfig) {
//当系统配置发生变化时(例如系统语言发生变化),回调该接口
...............
}
.............
});
}
从上面的代码可以看出,对于系统进程而言,ActivityThread的attach函数最重要的工作就是创建了Instrumentation、Application和Context。
2.1 Instrumentation
Instrumentation是Android中的一个工具类,当该类被启用时,它将优先于应用中其它的类被初始化。
此时,系统先创建它,再通过它创建其它组件。
此外,系统和应用组件之间的交互也将通过Instrumentation来传递。
因此,Instrumentation就能监控系统和组件的交互情况了。
实际使用时,可以创建该类的派生类进行相应的操作。
这个类在介绍启动Activity的过程时还会碰到,此处不作展开。
2.2 Context
Context是Android中的一个抽象类,用于维护应用运行环境的全局信息。
通过Context可以访问应用的资源和类,甚至进行系统级的操作,例如启动Activity、发送广播等。
ActivityThread的attach函数中,通过下面的代码创建出系统应用对应的Context:
.......
//ContextImpl是Context的实现类
ContextImpl context = ContextImpl.createAppContext(
this, getSystemContext().mPackageInfo);
.......
2.2.1 getSystemContext
我们先看看ActivityThread中getSystemContext的内容:
public ContextImpl getSystemContext() {
synchronized (this) {
if (mSystemContext == null) {
//调用ContextImpl的静态函数createSystemContext
mSystemContext = ContextImpl.createSystemContext(this);
}
return mSystemContext;
}
}
进入ContextImpl的createSystemContext函数:
static ContextImpl createSystemContext(ActivityThread mainThread) {
//创建LoadedApk类,代表一个加载到系统中的APK
//注意此时的LoadedApk只是一个空壳
//PKMS还没有启动,估无法得到有效的ApplicationInfo
LoadedApk packageInfo = new LoadedApk(mainThread);
//调用ContextImpl的构造函数
ContextImpl context = new ContextImpl(null, mainThread,
packageInfo, null, null, 0, null, null, Display.INVALID_DISPLAY);
//初始化资源信息
context.mResources.updateConfiguration(context.mResourcesManager.getConfiguration(),
context.mResourcesManager.getDisplayMetrics());
return context;
}
可以看出createSystemContext的内容就是创建一个LoadedApk,然后初始化一个ContextImpl对象。
似乎没有什么特别的,那么为什么函数名被叫做create “System” Context?
为了回答这个问题,就要看看LoadedApk的构造函数了:
LoadedApk(ActivityThread activityThread) {
mActivityThread = activityThread;
mApplicationInfo = new ApplicationInfo();
//packageName为"android"
mApplicationInfo.packageName = "android";
mPackageName = "android";
//下面许多参数为null
................
}
注意到createSystemContext函数中,创建的LoadApk对应packageName为”android”,也就是framwork-res.apk。
由于该APK仅供SystemServer进程使用,因此创建的Context被定义为System Context。
现在该LoadedApk还没有得到framwork-res.apk实际的信息。
当PKMS启动,完成对应的解析后,AMS将重新设置这个LoadedApk。
2.2.2 ContextImpl.createAppContext
static ContextImpl createAppContext(ActivityThread mainThread, LoadedApk packageInfo) {
if (packageInfo == null) throw new IllegalArgumentException("packageInfo");
return new ContextImpl(null, mainThread,
packageInfo, null, null, 0, null, null, Display.INVALID_DISPLAY);
}
相对而言,createAppContext的内容就比较简单了,就是利用ActivityThread和LoadedApk构造出ContextImpl。
ContextImpl的构造函数主要是完成一些变量的初始化,建立起ContextImpl与ActivityThread、LoadedApk、ContentResolver之间的关系。
代码简单但是冗长,此处不做展开。
2.3 Application
Android中Application类用于保存应用的全局状态。
我们经常使用的Activity和Service均必须和具体的Application绑定在一起。
通过上图的继承关系,每个具体的Activity和Service均被加入到Android运行环境中。
在ActivityThread中,针对系统进程,通过下面的代码创建了初始的Application:
..............
//调用LoadedApk的makeApplication函数
mInitialApplication = context.mPackageInfo.makeApplication(true, null);
//启动Application
mInitialApplication.onCreate();
..............
我们看一下LoadedApk.makeApplication:
public Application makeApplication(boolean forceDefaultAppClass,
Instrumentation instrumentation) {
if (mApplication != null) {
return mApplication;
}
.............
Application app = null;
String appClass = mApplicationInfo.className;
if (forceDefaultAppClass || (appClass == null)) {
//系统进程中,对应下面的appClass
appClass = "android.app.Application";
}
try {
java.lang.ClassLoader cl = getClassLoader();
if (!mPackageName.equals("android")) {
............
}
ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
//实际上最后通过反射创建出Application
app = mActivityThread.mInstrumentation.newApplication(
cl, appClass, appContext);
appContext.setOuterContext(app);
} catch (Exception e) {
..........
}
//一个进程支持多个Application,mAllApplications用于保存该进程中的Application对象
mActivityThread.mAllApplications.add(app);
mApplication = app;
..............
}
从上面的代码不难看出,这部分主要是创建framework-res.apk对应的Application,然后调用它的onCreate函数,完成启动。
总结
至此,createSystemContext函数介绍完毕。
当SystemServer调用createSystemContext完毕后:
1、得到了一个ActivityThread对象,它代表当前进程 (此时为系统进程) 的主线程;
2、得到了一个Context对象,对于SystemServer而言,它包含的Application运行环境与framework-res.apk有关。
在继续分析AMS之前,我们先停下来思考一下,为什么在启动所有的服务前,SystemServer先要调用createSystemContext?
个人觉得《深入理解Android》对这个问题,解释的比较好,大致意思如下:
Android努力构筑了一个自己的运行环境。
在这个环境中,进程的概念被模糊化了。组件的运行及它们之间的交互均在该环境中实现。
createSystemContext函数就是为SystemServer进程搭建一个和应用进程一样的Android运行环境。
Android运行环境是构建在进程之上的,应用程序一般只和Android运行环境交互。
基于同样的道理,SystemServer进程希望它内部运行的应用,
也通过Android运行环境交互,因此才调用了createSystemContext函数。
创建Android运行环境时,
由于SystemServer的特殊性,调用了ActivityThread.systemMain函数;
对于普通的应用程序,将在自己的主线程中调用ActivityThread.main函数。
上图表示了进程的Android运行环境涉及的主要类之间的关系。
其中的核心类是ContextImpl,通过它可以得到ContentResolver、系统资源、应用信息等。
三、AMS初始化
创建完Android运行环境后,SystemServer调用startBootstrapServices,其中就创建并启动了AMS:
private void startBootstrapServices() {
Installer installer = mSystemServiceManager.startService(Installer.class);
// Activity manager runs the show.
//启动AMS,然后获取AMS保存到变量中
mActivityManagerService = mSystemServiceManager.startService(
ActivityManagerService.Lifecycle.class).getService()