ActivityManagerService(以下简称AMS)是系统服务的一部分,它在SystemServer中被启动,主要负责四大组件状态管理与查询、进程创建与状态管理、Task切换与调度、cpu或mem等辅助状态监听等工作。它是系统核心服务,也是日常我们使用得最频繁的系统服务之一。
AMS是通过Binder机制在C/S端相互串联调用,就如上述所示那样,左半部分是service端,而有半部分主要是client端使用。
客户端使用AMS一般是通过调用ActivityManagerNative的getDefault()方法获取ActivityManagerProxy实例,进而与服务端AMS进行通信。
// frameworks/base/core/java/android/app/ActivityManagerNative.java
static public IActivityManager getDefault() {
return gDefault.get();
}
private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
protected IActivityManager create() {
IBinder b = ServiceManager.getService("activity");
IActivityManager am = asInterface(b);
return am;
}
};
static public IActivityManager asInterface(IBinder obj) {
if (obj == null) {
return null;
}
IActivityManager in =
(IActivityManager)obj.queryLocalInterface(descriptor);
if (in != null) {
return in;
}
return new ActivityManagerProxy(obj);
}
AMS继承自ActivityManagerNative类,它属于Binder服务端,也是业务处理的核心部分(如我们通过startActivity()启动一个Activity这个操作的核心部分都是由AMS来处理的)。下面我们就来介绍下AMS的启动过程。
AMS服务依附于Zygote启动的system_server进程中,这个进程的主要启动类是SystemServer。SystemServer的main方法如下:
// frameworks/base/services/java/com/android/server/SystemServer.java
public static void main(String[] args) {
new SystemServer().run();
}
可见,main方法只是起到过渡作用,在main方法中创建了SystemServer实例并调用了其run()方法来处理具体的逻辑。
// frameworks/base/services/java/com/android/server/SystemServer.java
private void run() {
//...
Looper.prepareMainLooper();
//加载native服务
System.loadLibrary("android_servers");
nativeInit();//启动native sensor service
//...
createSystemContext();
// Create the system service manager.
mSystemServiceManager = new SystemServiceManager(mSystemContext);
LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
// Start services.
try {
startBootstrapServices();
startCoreServices();
startOtherServices();
} catch (Throwable ex) {
throw ex;
}
//...
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
上述方法中,我们很容易的就看到SystemServer主线程使用了Handler机制,是基于消息驱动的。在进入实质轮询之前有关AMS的大概分为以下三个流程:
这三个流程我们将在下面分别介绍。
AMS启动环境包括上下文环境与服务管理者环境,在run()方法中分别对应SystemContext的创建和SystemServiceManager的创建。
// frameworks/base/services/java/com/android/server/SystemServer.java#run
// Initialize the system context.
createSystemContext();
// Create the system service manager.
mSystemServiceManager = new SystemServiceManager(mSystemContext);
LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
Context上下文环境在Android中随处可见,小到Activity、Service,大到此处的SystemServer,都需要有一个上下文执行环境,在这个环境中包含了当前进程所需要的资源等信息。而在SystemServer进程中这个上下文环境就是通过createSystemContext()方法创建的。
// frameworks/base/services/java/com/android/server/SystemServer.java
private void createSystemContext() {
ActivityThread activityThread = ActivityThread.systemMain();
mSystemContext = activityThread.getSystemContext();
mSystemContext.setTheme(android.R.style.Theme_DeviceDefault_Light_DarkActionBar);
}
在createSystemContext()中我们看到其调用了ActivityThread的静态方法systemMain()后从获取了系统上下文SystemContext,并设置当前上下文的theme主题。
普通的应用进程的启动是由Zygote运行ActivityThread的main()方法完成的,这个main()方法使用Handler机制处于消息轮询状态使得这个被创建的应用进程持续运转。但是对于系统进程SystemServer来说,它的启动并不走ActivityThread的main()方法,而是如createSystemContext()所示,调用systemMain()的方式绑定系统进程。systemMain()方法如下:
// frameworks/base/core/java/android/app/ActivityThread.java
public static ActivityThread systemMain() {
if (!ActivityManager.isHighEndGfx()) {
HardwareRenderer.disable(true);
} else {
HardwareRenderer.enableForegroundTrimming();
}
ActivityThread thread = new ActivityThread();//初始化资源管理者
thread.attach(true);//初始化Application、Context等
return thread;
}
可以看见,systemMain()方法创建了一个ActivityThread实例并调用其attach()方法绑定了这个进程,这一调用逻辑在main()中也有,不同的是systemMain()方法依附于系统进程,是系统专用方法。
// frameworks/base/core/java/android/app/ActivityThread.java
private void attach(boolean system) {
sCurrentActivityThread = this;
mSystemThread = system;
if (!system) {//普通应用进程
//...
} else {//系统进程
android.ddm.DdmHandleAppName.setAppName("system_process",
UserHandle.myUserId());//设置进程名
try {
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);
}
}
DropBox.setReporter(new DropBoxReporter());//dropbox日志输出
ViewRootImpl.addConfigCallback(new ComponentCallbacks2() {/**省略callback内部代码*/);
}
attach()方法在systemMain()和main()中都有调用,不同的是传入的参数,它标识了是否为系统进程调用,在systemMain()中这个参数传入的是true。在上述方法中,大致完成了以下工作:
标识当前线程及是否系统线程。sCurrentActivityThread标识了当前方法的调用线程,在本文中这个线程就是SystemServer主线程。
设置当前进程名为system_process。
创建Instrumentation方便之后系统组件初始化及监控组件与用户的交互。
创建SystemContext与AppContext上下文环境。
创建Application实例并调用其onCreate生命周期方法。
dropbox日志输出及ViewRootImpl配置变换监听。
其他的都比较好理解,代码里边也有体现,唯独SystemContext我们需要把它拎出来说下。SystemContext在ActivityThread是单实例存在,它通过getSystemContext()方法创建的。
// frameworks/base/core/java/android/app/ActivityThread.java
public ContextImpl getSystemContext() {
synchronized (this) {
if (mSystemContext == null) {
mSystemContext = ContextImpl.createSystemContext(this);
}
return mSystemContext;
}
}
在getSystemContext()方法中,这个系统上下文是通过ContextImpl的createSystemContext()创建的。这里需要了解的是ContextImpl可以创建整个android需要的大部分上下文环境,如SystemContext、AppContext、ActivityContext、DisplayContext、PackageContext等。这几个上下文中,SystemContext的上下文创建时比较特殊的一个。
// frameworks/base/core/java/android/app/ContextImpl.java
static ContextImpl createSystemContext(ActivityThread mainThread) {
LoadedApk packageInfo = new LoadedApk(mainThread);
ContextImpl context = new ContextImpl(null, mainThread,
packageInfo, null, null, false, null, null);
context.mResources.updateConfiguration(context.mResourcesManager.getConfiguration(),
context.mResourcesManager.getDisplayMetricsLocked(Display.DEFAULT_DISPLAY));
return context;
}
在createSystemContext()中首先会创建一个LoadedApk对象。顾名思义,LoadedApk表示了一个加载到内存中的apk,此处使用的是一个参数的LoadedApk构造,这个构造方法如下:
// frameworks/base/core/java/android/app/LoadedApk.java
LoadedApk(ActivityThread activityThread) {
mActivityThread = activityThread;
mApplicationInfo = new ApplicationInfo();
mApplicationInfo.packageName = "android";
mPackageName = "android";
//…
mClassLoader = ClassLoader.getSystemClassLoader();
mResources = Resources.getSystem();
}
创建的SystemContext中的LoadedApk对象(即mPackageInfo)指明了包名为android。这样我们的SystemContext就可以据此mPackageInfo访问其加载到内存的资源。当然了,为了使得LoadedApk的资源可用,还需要调用调用ContextImpl的installSystemApplicationInfo()方法,这个调用是在后续介绍的AMS类中。
这个被加载到SystemServer中的apk其实就是framework-res.apk。其源码路径是frameworks/base/core/res。这个路径下的Android.mk文件也验证了这一点。
// frameworks/base/core/res
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_NO_STANDARD_LIBRARIES := true
LOCAL_PACKAGE_NAME := framework-res
LOCAL_CERTIFICATE := platform
//…
LOCAL_EXPORT_PACKAGE_RESOURCES := true
//…
这个mk文件负责把当前路径下的文件打包成framework-res.apk,这个apk是使用了platform平台签名并且其资源可以被其他进程使用。
// frameworks/base/core/res/AndroidManifest.xml
当我们进入apk的清单文件中,我们可以看见其包名正是android,这也正是上面SystemContext中的LoadedApk所加载的资源。补充一下,application标签中的android:process="system"则标识了当前apk的进程名processName为system。
经此之后,SystemContext就算初步准备完成(后边需要调用installSystemApplicationInfo()才算完全ok)。
在SystemServer中需要启动诸多系统服务,如Installer、ActivityManagerService、DisplayManagerService、AlarmManagerService等等,这些服务相互影响、依赖,启动顺序也有先有后,为了方便管理这些服务的生命周期,故设计了SystemService基类,这些系统服务通过继承SystemService并以约定的方式启动起来,后期也统一由SystemServiceManager管理。
// frameworks/base/services/core/java/com/android/server/SystemService.java
public abstract class SystemService {
//...
private final Context mContext;
public SystemService(Context context) {
mContext = context;
}
//服务启动-当调用SystemServiceManager#startService时触发
public abstract void onStart();
//启动阶段回调
public void onBootPhase(int phase) {}
//多用户切换接口
public void onStartUser(int userHandle) {}
public void onSwitchUser(int userHandle) {}
public void onStopUser(int userHandle) {}
public void onCleanupUser(int userHandle) {}
在SystemService中包含了一些多用户切换的回调接口,以及启动过程的回调接口。如上所述的那样系统服务通过继承SystemService并添加到SystemService管理者中,这样,如果用户状态、启动状态等发生改变就可由SystemServiceManager通知这些继承了SystemService的服务。
正因此,SystemServiceManager必须在各项服务开始创建之前作为启动环境的一部分被启动起来。
// frameworks/base/services/java/com/android/server/SystemServer.java#run
// Create the system service manager.
mSystemServiceManager = new SystemServiceManager(mSystemContext);
LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
从以上代码来看,SystemServiceManager实例的创建并不复杂,仅仅需要把系统上下文传入就可,当然,为了进程内可以方便的访问这个系统服务管理者,在其创建后就将其添加到LocalServices中去了。LocalSevices中维护了一个静态的、以服务名-服务实例作为K-V结构的ArrayMap,这样在进程任何地方我们都可以通过LocalServices的getService()方法获取对应服务。
SystemServiceManager主要关键方法有startService()方法和startBootPhase()方法。下边我们分别对这两个方法进行简析。
startService():启动服务
// frameworks/base/services/core/java/com/android/server/SystemServiceManager.java
public
final String name = serviceClass.getName();
Slog.i(TAG, "Starting " + name);
// Create the service.用于判断SystemService是否是class的父类
if (!SystemService.class.isAssignableFrom(serviceClass)) {
throw new RuntimeException("Failed to create " + name
+ ": service must extend " + SystemService.class.getName());
}
final T service;
try {
Constructor<T> constructor = serviceClass.getConstructor(Context.class);
service = constructor.newInstance(mContext);
} catch/***/}// Register it.
mServices.add(service);
// Start it.
try {
service.onStart();
} catch (RuntimeException ex) {
throw new RuntimeException("Failed to start service " + name
+ ": onStart threw an exception", ex);
}
return service;
}
startService负责创建以及启动一个系统服务,这个方法需要传入一个SystemService的子类class。其内部大概分为三个环节:
创建服务。通过java反射将SystemContext作为构造参数以创建class对应服务。
注册服务。把创建好的服务添加到mServices中去,这样后续的这个SystemService的生命周期的触发就交由SystemServiceManager了。
调用服务的onStart()周期方法。onStart()是当前SystemService启动周期触发的方法。
startBootPhase():不同的启动阶段触发
// frameworks/base/services/core/java/com/android/server/SystemServiceManager.java
public void startBootPhase(final int phase) {
if (phase <= mCurrentPhase) {
throw new IllegalArgumentException("Next phase must be larger than previous");
}
mCurrentPhase = phase;//当前所处的启动阶段
final int serviceLen = mServices.size();
for (int i = 0; i < serviceLen; i++) {//分发所触发的启动阶段给各SystemService
final SystemService service = mServices.get(i);
try {
service.onBootPhase(mCurrentPhase);
} catch (Exception ex) {
//…
}
}
}
启动阶段一般分为以下几个阶段:
启动阶段
值
含义
调用时机
PHASE_WAIT_FOR_DEFAULT_DISPLAY
100
默认display即主屏设备准备完成
当DisplayManagerService构建完毕时,这时候主屏已经构建完成,如AMS已经可以着手Stack信息的构建等
PHASE_LOCK_SETTINGS_READY
480
锁屏设置服务启动完成
LockSetttingsService已经完成准备工作,这时候可以获取诸如锁屏密码等相关数据
PHASE_SYSTEM_SERVICES_READY
500
关键系统服务已经启动完成
大部分系统服务已经完成准备工作,此阶段紧随着锁屏启动阶段被调用
PHASE_ACTIVITY_MANAGER_READY
550
AMS服务已完成准备工作,可以向外提供服务
在AMS的systemReady()中被调用,用于告诉系统服务AMS准备完成,到此阶段后,诸如广播等就可以发送了
PHASE_THIRD_PARTY_APPS_CAN_START
600
第三方应用已经可以启动
在AMS的systemReady()中,当网络服务、存储服务、音频服务、systemui等准备完成后被调用,以告诉系统服务第三方应用可以启动了
PHASE_BOOT_COMPLETED
1000
开机启动完成
当任意Activity启动完成即onResume之后会通过completeResumeLocked()通知AMS当前处于ActivityIdle状态,这时AMS就会尝试在activityIdleInternalLocked()调用链中通知开机启动完成。显然开机启动完成发生在Launcher启动完成时
当SystemServer到了上述某一启动阶段时,可以通过SystemServiceManager的startBootPhase()方法通知各系统服务,各系统服务触发onBootPhase()以处理当前启动阶段的任务。
在SystemServer进程的系统运行环境初始化完毕之后,接下来就是各个系统服务的创建于初始化,这些系统服务分为了三类:
bootstrap类型-引导服务
core类型-核心服务
other类型-其他服务
我们的AMS的创建就是在startBootStrapServices()方法中完成的。
// frameworks/base/services/java/com/android/server/SystemServer.java
private void startBootstrapServices() {
mInstaller = mSystemServiceManager.startService(Installer.class);
//startService调用构造与其onStart方法,其最终调用了ActivityManagerService的start方法
mActivityManagerService = mSystemServiceManager.startService(
ActivityManagerService.Lifecycle.class).getService();
mActivityManagerService.setSystemServiceManager(mSystemServiceManager);//给AMS设置SSM
//...
}
与诸如Installer、PowerManagerService等系统服务不同的是,AMS因为binder通信的需要,其继承了ActivityManagerNative而非继承于SystemService。基于系统服务管理的需要,AMS.LifeCycle类就应运而生了。在上述代码中,SystemServiceManager通过startService()方法创建AMS.LifeCycle实例并调用其onStart()方法。
// frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
public static final class Lifecycle extends SystemService {
private final ActivityManagerService mService;
public Lifecycle(Context context) {
super(context);
mService = new ActivityManagerService(context);
}@Override
public void onStart() {
mService.start();
}
public ActivityManagerService getService() {
return mService;
}
}
在AMS.LifeCycle首先通过其构造方法创建了AMS实例,并通过onStart()回调调用了AMS的start()方法。且为了方便其它SystemService使用AMS,向外提供了getService()方法获取。另外我们需要注意的是AMS.LifeCycle并没有实现onBootPhase()方法。
到了此处,我们安卓中非常重要的组件管理者AMS也将登场。
// frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
public ActivityManagerService(Context systemContext) {
mContext = systemContext;//系统上下文
mFactoryTest = FactoryTest.getMode();//工程模式
mSystemThread = ActivityThread.currentActivityThread();//标记当前进程的ActivityThread,当前进程也为AMS需要管理的一部分。
Slog.i(TAG, "Memory class: " + ActivityManager.staticGetMemoryClass());mHandlerThread = new ServiceThread(TAG,
android.os.Process.THREAD_PRIORITY_FOREGROUND, false /*allowIo*/);
mHandlerThread.start();//AMS专用的线程,用于处理组件启动超时事件(ANR)、GC等
mHandler = new MainHandler(mHandlerThread.getLooper());
mFgBroadcastQueue = new BroadcastQueue(this, mHandler,
"foreground", BROADCAST_FG_TIMEOUT, false);
mBgBroadcastQueue = new BroadcastQueue(this, mHandler,
"background", BROADCAST_BG_TIMEOUT, true);
mBroadcastQueues[0] = mFgBroadcastQueue;
mBroadcastQueues[1] = mBgBroadcastQueue;//两者用于管理广播组件
mServices = new ActiveServices(this);//管理Service组件
mProviderMap = new ProviderMap(this);//管理ContentProvider组件
//创建/data/system 目录
File dataDir = Environment.getDataDirectory();
File systemDir = new File(dataDir, "system");
systemDir.mkdirs();
mBatteryStatsService = new BatteryStatsService(systemDir, mHandler);//电池状态统计服务的初始化
mBatteryStatsService.getActiveStatistics().readLocked();
mBatteryStatsService.getActiveStatistics().writeAsyncLocked();
mOnBattery = DEBUG_POWER ? true
: mBatteryStatsService.getActiveStatistics().getIsOnBattery();
mBatteryStatsService.getActiveStatistics().setCallback(this);
mProcessStats = new ProcessStatsService(this, new File(systemDir, "procstats"));//进程状态统计
mAppOpsService = new AppOpsService(new File(systemDir, "appops.xml"), mHandler);//app权限管理
mGrantFile = new AtomicFile(new File(systemDir, "urigrants.xml"));//uri授权文件
// User 0 is the first and only user that runs at boot.
mStartedUsers.put(0, new UserStartedState(new UserHandle(0), true));//添加user 0用户
mUserLru.add(Integer.valueOf(0));
updateStartedUserArrayLocked();
GL_ES_VERSION = SystemProperties.getInt("ro.opengles.version",
ConfigurationInfo.GL_ES_VERSION_UNDEFINED);//获取opengl版本号
mConfiguration.setToDefaults();//设置默认配置
mConfiguration.setLocale(Locale.getDefault());
mConfigurationSeq = mConfiguration.seq = 1;
mProcessCpuTracker.init();//cpu使用记录跟踪者初始化。
mCompatModePackages = new CompatModePackages(this, systemDir, mHandler);
mIntentFirewall = new IntentFirewall(new IntentFirewallInterface(), mHandler);//防火墙初始化
mStackSupervisor = new ActivityStackSupervisor(this);//Activity管理者
mTaskPersister = new TaskPersister(systemDir, mStackSupervisor);//Task持久化存储器
mProcessCpuThread = new Thread("CpuTracker") {/**cpu统计的执行*/};
mLockToAppRequest = new LockToAppRequestDialog(mContext, this);
Watchdog.getInstance().addMonitor(this);//监测AMS的运行状态,如死锁、阻塞等
Watchdog.getInstance().addThread(mHandler);
}
在AMS构造方法中进行的操作非常多,大概可以分为以下几类:
组件管理。Activity管理依赖ActivityStackSuoervisor、TaskPersister,Service管理依赖ActiveServices,广播的管理依赖BroadcastQueue,内容提供者管理依赖ProviderMap。
监测统计。ProcessCpuTracker用于跟踪各进程cpu,Watchdog监测AMS运行状态,还有诸如电池状态、进程状态、app权限状态、uri授权状态等管理与监测。
配置初始化。Configuration系统配置初始化,UserStartedState用户初始化等。
在AMS构造方法完成对各个实例的初始化之后,接下来就是AMS.LifeCycle的onStart()回调了。这个回调直接调用了AMS的start()方法,这个方法比之构造方法要简约的多,主要是负责AMS构建的扫尾工作。
// frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
private void start() {
Process.removeAllProcessGroups();//移除进程组
mProcessCpuThread.start();//启动cpu使用率线程
mBatteryStatsService.publish(mContext);//通过ServiceManager添加为实名binder
mAppOpsService.publish(mContext);//添加为实名binder
Slog.d("AppOps", "AppOpsService published");
LocalServices.addService(ActivityManagerInternal.class, new LocalService());//添加内部交互service,可通过LocalServices获取
}
上述电池统计服务与app权限管理服务继承自AIDL的Stub类(Binder子类)。其publish()方法内部则是通过ServiceManager把这两服务变为实名Binder服务,外界可通过服务名batterystats和appops访问。
AMS的方法调用链如下所示。
AMS的初始化过程依赖很多系统服务的构建,这也导致了上图所示的那样,在三类系统服务启动过程中AMS都有需要初始化的内容。这些初始化过程中有以下几个过程较为重要:
此过程在SystemServer完成对PowerManagerService的初始化后执行,主要对AMS所需要的电源管理组件的初始化操作。
// frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
public void initPowerManagement() {
mStackSupervisor.initPowerManagement();//电源锁,防止AMS启动时进入休眠
mBatteryStatsService.initPowerManagement();
}
上述代码段实质上分为两个部分:
当PackageManagerService完成初始化之后,接着就调用了AMS的setSystemProcess()方法,顾名思义,此方法把当前进程设置为系统进程。这个方法里边内容大致可分为三个部分阅读。
此方法内部首先将一些AMS辅助功能通过ServiceManager实名化为binder服务。
// frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java#setSystemProcess
public void setSystemProcess() {//启动AMS辅助服务,并标识system_process的进程记录
try {
ServiceManager.addService(Context.ACTIVITY_SERVICE, this, true);//把当前AMS注册为实名服务
ServiceManager.addService(ProcessStats.SERVICE_NAME, mProcessStats);//进程状态管理的binder实名化
ServiceManager.addService("meminfo", new MemBinder(this));//各进程内存状态的binder实名化
ServiceManager.addService("gfxinfo", new GraphicsBinder(this));//各进程UI性能状态的binder实名化
ServiceManager.addService("dbinfo", new DbBinder(this));//各进程数据库debug信息的binder实名化
if (MONITOR_CPU_USAGE) {
ServiceManager.addService("cpuinfo", new CpuBinder(this));//各进程cpu数据的binder实名化
}
ServiceManager.addService("permission", new PermissionController(this));
}
上述方法分段中,首先将AMS本身设为了binder服务,经此之后当前进程或其他应用进程就可通过getSystemService()或ActivityManagerNative访问这个AMS了。之后则添加了一些辅助binder服务如MemBinder、GraphicsBinder等,这些辅助服务依赖于AMS,利用了binder的dump功能完成对AMS中各个状态的监测。
上述的辅助服务基本上都实现了binder的dump()方法,当我们调用adb shell dumpsys命令时,实质上就是通过binder机制调用到这些binder服务的dump()方法。在dump()中开发者可以打印想要监测的内容。例如上述的MemBinder就在dump()方法中调用AMS.dumpApplicationMemoryUsage()打印了各个应用的内存使用情况。
其次,设置当前进程所使用到的系统包信息.这个系统包的包名是android,正如本章之前讨论LoadedApk所说的那样,在framework-res.apk这个系统apk加载完成之后,需要调用其installSystemApplicationInfo()完成初始化工作这部分工作就是在这里完成的。
// frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java#setSystemProcess
ApplicationInfo info = mContext.getPackageManager().getApplicationInfo(
"android", STOCK_PM_FLAGS);
//系统LoadedApk构造需要调用installSystemApplicationInfo方法,把正确的ApplicationInfo与classloader加进去
mSystemThread.installSystemApplicationInfo(info, getClass().getClassLoader());
最后,在setSystemProcess()方法完成了前两项任务之后,接下来就是将当前进程设置为系统进程并纳入AMS的进程管理。在AMS中进程管理是通过把每个进程标记为一个个ProcessRecord完成的。
// frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java#setSystemProcess
synchronized (this) {//标识当前进程
ProcessRecord app = newProcessRecordLocked(info, info.processName, false, 0);
app.persistent = true;//常驻系统
app.pid = MY_PID;//进程id
app.maxAdj = ProcessList.SYSTEM_ADJ;//优先级
app.makeActive(mSystemThread.getApplicationThread(), mProcessStats);
mProcessNames.put(app.processName, app.uid, app);//存放至map管理
synchronized (mPidsSelfLocked) {
mPidsSelfLocked.put(app.pid, app);//pid为key-ProcessRecord为value的映射关系
}
updateLruProcessLocked(app, false, null);//更新进程的lru关系,与lmk相关
updateOomAdjLocked();//更新进程优先级关系
}
} catch (PackageManager.NameNotFoundException e) {
throw new RuntimeException(
"Unable to find android system package", e);
}
在上述setSystemProcess()方法片段中,当前进程的ProcessRecord通过newProcessRecordLocked()方法创建,并接着修改了比较重要的几个属性及方法:
persistent:标识SystemServer进程为常驻内存类型的进程。一般情况下,系统应用可在清单文件的application标签中使用persistent属性将这个应用标识为常驻内存,这样如果应用crash,则可以不断重启。
pid:当前进程id,进程id可通过如下方式获取:
// frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
static final int MY_PID = Process.myPid();
maxAdj:当前进程的优先级。这个属性主要是安卓进程回收机制LMK的回收依据,maxAdj值范围-17~16,其值越小,越不容易被回收,正常情况下,前台进程的adj值为0。而此处的maxAdj值为SYSTEM_ADJ=-16,可以说已经非常低了。
makeAlive():激活当前进程。也就是将应用程序用于进程间binder通信的IApplicationThread绑定到ProcessRecord中,这样,我们就可以通过ProcessRecord来调度进程(ActivityThread)了。
在修改完这些属性之后,就把当前进程记录存入AMS全局变量mProcessNames和mPidsSelfLocked中并更新进程的LRU关系与oomAdj优先级关系。
在完成把当前SystemServer进程设置为系统进程后,接着在SystemServer的startOtherServices()对系统的内容提供者进程初始化操作,这个过程是通过AMS.installSystemProviders()方法完成的。
// frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
public final void installSystemProviders() {
List<ProviderInfo> providers;
synchronized (this) {
//要查询的目标进程 进程名:system,所属uid为system
ProcessRecord app = mProcessNames.get("system", Process.SYSTEM_UID);
providers = generateApplicationProvidersLocked(app);//使用PMS查询所有符合条件的内容提供者
if (providers != null) {//过滤掉非系统提供者
for (int i=providers.size()-1; i>=0; i--) {
ProviderInfo pi = (ProviderInfo)providers.get(i);
if ((pi.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) == 0) {
providers.remove(i);
}
}
}
}
if (providers != null) {//在client端使用ProviderClientRecord记录,通过AMSpublish内容提供者(在AMS中使用ContentProviderRecord记录)
mSystemThread.installSystemProviders(providers);
}
//初始化核心设置观察者
mCoreSettingsObserver = new CoreSettingsObserver(this);
}
在installSystemProviders()方法中,对内容提供者的操作过程如下:
在startOtherServices()中当WindowManagerService完成初始化创建后,需要把WMS设置给AMS。AMS中需要对Activity的管理,这里涉及到WMS也是必然。
// frameworks/base/services/java/com/android/server/SystemServer.java#startOtherServices
//WMS初始化
wm = WindowManagerService.main(context, inputManager,
mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL,
!mFirstBoot, mOnlyCore);
ServiceManager.addService(Context.WINDOW_SERVICE, wm);
ServiceManager.addService(Context.INPUT_SERVICE, inputManager);
//给AMS设置窗口管理者
mActivityManagerService.setWindowManager(wm);//主要是给ActivityStaskSupervisor设置主屏幕stack管理者
在上述代码中,我们可以看见WMS的初始化是通过其自身的main()方法完成的,并在初始化完成后被加入到ServiceManager实名binder服务中去(可以想象到的是WMS必然是Binder的子类)。然后,AMS通过调用setWindowManager()方法把自己同WMS关联起来。
在这个AMS.setWindowManager()方法中,除了把WMS保存作为成员变量外,重要的是把WMS设置给了Activity管理者ActivityStackSupervisor。
// frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
public void setWindowManager(WindowManagerService wm) {
mWindowManager = wm;
//把WMS设置给Activity管理者
mStackSupervisor.setWindowManager(wm);
}
ActivityStackSupervisor(以下简称为ASS)直观上的翻译就是ActivityStack管理者,AMS通过这个ASS管理着系统中所有的Activity。在此处的AMS初始化过程中ASS也通过setWindowManager()方法与WMS建立起了联系。当然,ASS.setWindowManager()方法不止于此,它还进行了一些其它的操作,我们先来看下方法内容。
// frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java
void setWindowManager(WindowManagerService wm) {
synchronized (mService) {
mWindowManager = wm;//保存WMS
mDisplayManager =
(DisplayManager)mService.mContext.getSystemService(Context.DISPLAY_SERVICE);
mDisplayManager.registerDisplayListener(this, null);//注册Display改变监听
//获取当前屏幕数并遍历这些Display
Display[] displays = mDisplayManager.getDisplays();
for (int displayNdx = displays.length - 1; displayNdx >= 0; --displayNdx) {
final int displayId = displays[displayNdx].getDisplayId();
//每个屏幕由ActivityDisplay进行描述标识,它拥有多个stack
ActivityDisplay activityDisplay = new ActivityDisplay(displayId);
if (activityDisplay.mDisplay == null) {
throw new IllegalStateException("Default Display does not exist");
}
//把display描述者加入到mActivityDisplays中进行管理
mActivityDisplays.put(displayId, activityDisplay);
}
//根据stackId,每个stackId由一个ActivityContainer管理,这个ActivityContainer包含了一个stack
createStackOnDisplay(HOME_STACK_ID, Display.DEFAULT_DISPLAY);
//默认情况下,创建出来的home stack是拥有focus的stack
mHomeStack = mFocusedStack = mLastFocusedStack = getStack(HOME_STACK_ID);
//输入/触摸事件管理者
mInputManagerInternal = LocalServices.getService(InputManagerInternal.class);
//leanback为tv支持库,这里判断系统是否为android tv系统
mLeanbackOnlyDevice = isLeanbackOnlyDevice();
}
}
上述ASS.setWindowManager()方法大概可以分为以下几个部分来解读:
ASS关联WMS。因为WMS涉及到Activity返回栈的操作,所以在此处初始化过程中对WMS进行关联,方便后期调用。
从DMS获取当前显示设备(Display)数量并封装为ASS能识别的ActivityDisplay。在通常情况下,DMS只有默认主屏设备,但不排除会有副屏甚至多屏显示需求,那么此时可能初始化多个ActivityDisplay用于描述这些Display设备。
在默认显示设备创建HomeStack。默认显示设备一般是displayId为0的主屏设备。它在AMS中由ActivityDisplay负责描述,在此处初始化时为这个主屏设备添加了HomeStack,并把这个HomeStack标记为拥有当前焦点的Stack。进一步来说,这个HomeStack其实是ActivityStack类型,它被容器ActivityContainer持有,并通过attachToDisplayLocked()方法被添加到ActivityDisplay中去。
// frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java
private int createStackOnDisplay(int stackId, int displayId) {
ActivityDisplay activityDisplay = mActivityDisplays.get(displayId);
if (activityDisplay == null) {
return -1;
}
//根据stackId创建容器Container,在容器中持有一个ActivityStack
ActivityContainer activityContainer = new ActivityContainer(stackId);
mActivityContainers.put(stackId, activityContainer);
//把容器添加到ActivityDisplay中去,需要注意的是,一个显示设备可能拥有多个ActivityStack
activityContainer.attachToDisplayLocked(activityDisplay);
return stackId;
}
获取触摸事件管理者并判断当前是否仅支持TV显示。
systemReady()方法时AMS在启动过程中最晚执行的方法,该方法较为庞大,同上述setSystemProcess()方法一样,下边我们分段进行解析。
因AMS.systemReady()方法可能多次被调用到,此处我们仅先分析首次调用的流程。在进入此方法后,其首先恢复了最近任务列表。
// frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java#systemReady part1
if (mRecentTasks == null) {
mRecentTasks = mTaskPersister.restoreTasksLocked();//从本地重新拉取task数据
if (!mRecentTasks.isEmpty()) {//创建单独的Stack来存放拉取的Task数据
mStackSupervisor.createStackForRestoredTaskHistory(mRecentTasks);
}
cleanupRecentTasksLocked(UserHandle.USER_ALL);
mTaskPersister.startPersisting();//开启write线程实时把mRecentTasks中的数据本地化
}
mRecentTasks是用于记录最近启动的TaskRecord集合(最近任务列表),在AMS启动时需要从TaskPersister中把之前保存的启动记录(如果有的话)从本地拉取到内存中。
接下来处理PRE_BOOT_COMPLETED广播,顾名思义,该广播先于BOOT_COMPLETED广播发送出来。
// frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java#systemReady part2
// Check to see if there are any update receivers to run.
if (!mDidUpdate) {
if (mWaitingUpdate) {
return;
}
final ArrayList<ComponentName> doneReceivers = new ArrayList<ComponentName>();
mWaitingUpdate = deliverPreBootCompleted(new Runnable() {
public void run() {
synchronized (ActivityManagerService.this) {
mDidUpdate = true;
}
writeLastDonePreBootReceivers(doneReceivers);//把广播到的组件名本地化
showBootMessage(mContext.getText(
R.string.android_upgrading_complete),
false);//即将完成启动。
systemReady(goingCallback);//重新执行方法
}
}, doneReceivers, UserHandle.USER_OWNER);
if (mWaitingUpdate) {
return;
}
mDidUpdate = true;
}
广播的发送逻辑主要通过deliverPreBootCompleted()方法完成,在这个方法中,首先通过PMS查询所有静态注册了PRE_BOOT_COMPLETED广播接收者的组件(仅系统应用有效),并通过方法broadcastIntentLocked()发送此广播。在发送完成时会调用deliverPreBootCompleted()方法的callback回调,就是在上述part分段中就是那个匿名Runnable。
此处由变量mDidUpdate和mWaitingUpdate来控制PRE_BOOT_COMPLETED的发送过程。
需要注意的是systemReady()方法时可能在多线程调用的,deliverPreBootCompleted()的Runnable中执行的systemReady()是在AMS构造方法中创建的服务线程中执行,而此处我们的systemReady()则是在SystemServer主线程中执行。
接下来则进入下一部分处理逻辑,在这部分中则对非persistent应用做了清理。
persistent意为持久化,指代android中的常驻内存应用,persistent类型的进程拥有极高优先级而不会被LMK机制杀死,且这种常驻进程在crash之后会由AMS重新启动(即保活效果)。这种应用一般在清单文件中有android:sharedUserId="android.uid.system"和android:persistent="true"两个属性修饰,这就意味着,persistent应用一定只能是系统应用。
// frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java#systemReady part3
//将非persistent应用添加到待kill进程中
ArrayList<ProcessRecord> procsToKill = null;
synchronized(mPidsSelfLocked) {
for (int i=mPidsSelfLocked.size()-1; i>=0; i--) {
ProcessRecord proc = mPidsSelfLocked.valueAt(i);
if (!isAllowedWhileBooting(proc.info)){
if (procsToKill == null) {
procsToKill = new ArrayList<ProcessRecord>();
}
procsToKill.add(proc);
}
}
}
//将非persistent应用清掉(杀死这些进程)
synchronized(this) {
if (procsToKill != null) {
for (int i=procsToKill.size()-1; i>=0; i--) {
ProcessRecord proc = procsToKill.get(i);
Slog.i(TAG, "Removing system update proc: " + proc);
removeProcessLocked(proc, true, false, "system update done");
}
}
mProcessesReady = true;
}
mPidsSelfLocked集合保存了AMS管理的所有系统进程及应用进程,即所有已启动的进程在mPidsSelfLocked都已有记录。在上述代码中,首先遍历这个集合来查找出所有已启动的非persistent进程并存放入procsToKill集合中,这个查找条件通过方法isAllowedWhileBooting()完成,其内部就是判断ApplicationInfo的persistent属性是否为true。
// frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
boolean isAllowedWhileBooting(ApplicationInfo ai) {
return (ai.flags&ApplicationInfo.FLAG_PERSISTENT) != 0;
}
查询出的所有非persistent进程都被放入procsToKill集合中,并马上通过removeProcessLocked()方法遍历清理掉这些进程。
在清理完提前启动的非persistent进程后,则加载了启动过程中需要的信息。
// frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java#systemReady part4
retrieveSettings();//从Settings中获取核心设置项
loadResourcesOnSystemReady();//加载Recents UI所需资源
synchronized (this) {
readGrantedUriPermissionsLocked();//读取uri权限信息
}
如上所示,加载的启动信息可区分为:
在完成了启动信息加载之后,接下来的代码如下所示:
// frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java#systemReady part5
if (goingCallback != null) goingCallback.run();//作为参数传进来的Runnable被调用,内部启动了systemui
mBatteryStatsService.noteEvent(BatteryStats.HistoryItem.EVENT_USER_RUNNING_START,
Integer.toString(mCurrentUserId), mCurrentUserId);通知电量统计服务当前用户启动
mBatteryStatsService.noteEvent(BatteryStats.HistoryItem.EVENT_USER_FOREGROUND_START,
Integer.toString(mCurrentUserId), mCurrentUserId);
mSystemServiceManager.startUser(mCurrentUserId);//通知所有系统服务当前用户启动
在上述分段中有两个操作:
调用systemReady()方法的传参即Runnable。在这个Runnable的run()方法中,首先通过SystemServiceManager通知系统服务AMS准备完成,并启动了负责显示系统窗口如状态栏、导航栏等的SystemUI应用。当然,其后也包含了一些其他与AMS相关的辅助服务的ready工作,基于这样的服务很多,以下代码就不展开了。
// frameworks/base/services/java/com/android/server/SystemServer.java#startOtherServices
mActivityManagerService.systemReady(new Runnable() {
@Override
public void run() {
//启动阶段设置为AMS准备完成
mSystemServiceManager.startBootPhase(SystemService.PHASE_ACTIVITY_MANAGER_READY);
try {
//开启本地crash上报
mActivityManagerService.startObservingNativeCrashes();
} catch (Throwable e) {
reportWtf("observing native crashes", e);
}
WebViewFactory.prepareWebViewInSystemServer();
try {
startSystemUi(context);//启动systemui,此处进行系统控件初始化,如状态栏、导航栏等
} catch (Throwable e) {
reportWtf("starting System UI", e);
}
//… 后续是其他辅助功能的systemReady
}
});
}
通知电池统计服务和所有SystemService当前用户启动。
// frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java#systemReady part6
if (mFactoryTest != FactoryTest.FACTORY_TEST_LOW_LEVEL) {
//启动persistent应用
try {
List apps = AppGlobals.getPackageManager().
getPersistentApplications(STOCK_PM_FLAGS);
if (apps != null) {
int N = apps.size();
int i;
for (i=0; i<N; i++) {
ApplicationInfo info
= (ApplicationInfo)apps.get(i);
if (info != null &&
!info.packageName.equals("android")) {
addAppLocked(info, false, null /* ABI override */);
}
}
}
} catch (RemoteException ex) {
// pm is in same process, this will never happen.
}
}
persistent应用的获取是通过PMS完成的,在PMS.getPersistentApplications()方法对于persistent应用的判断标准有两个:
是persistent应用,即清单文件的application标签中包含persistent属性且申明为true。
是系统应用,应用的清单文件中申明了uid所属为system。
通过PMS获取到这些persistent应用后,就调用addAppLocked()方法启动它们。addAppLocked()方法就不贴出来了,我们只需要知道,其最终调用了Process.start()方法通知Zygote进程新建一个进程。
在完成了系统persistent应用的启动之后,紧接着就是安卓桌面也就是Launcher进程的启动。Launcher进程运行于默认显示设备的HomeStack中,正因为AMS在启动完成之际需要启动Launcher,所以之前的setWindowManager()方法中关于焦点Stack等设置就不难理解了。
// frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java#systemReady part7
mBooting = true;
startHomeActivityLocked(mCurrentUserId);//启动Launcher
//...省略多用户启动广播的发送内容
mStackSupervisor.resumeTopActivitiesLocked();
sendUserSwitchBroadcastsLocked(-1, mCurrentUserId);//以广播形式通知用户发生切换
Launcher桌面启动通过方法startHomeActivityLocked()完成,且为了保证Launcher进程的桌面Activity可见还调用了ASS.resumeTopActivitiesLocked()进行配合。
至此,整个安卓桌面上的UI系统就已经启动成功,AMS启动过程也已告一段落。
手机扫一扫
移动阅读更方便
你可能感兴趣的文章