深入分析AMS啟動流程
前言
AMS(ActivityManagerService)Android的核心服務之一,對于framework各個核心服務,如果不是專門去做framework開發(fā),先了解其基本的流程機制,再慢慢深究;
今天我們就來學習下AMS
一、AMS功能概述
1、AMS介紹
- AMS是Android中最核心的服務,主要負責系統(tǒng)中四大組件的啟動、切換、調度及應用進程的管理和調度等工作,其職責與操作系統(tǒng)中的進程管理和調度模塊相類似,因此它在Android中非常重要;
- 組件狀態(tài)管理:包括四大組件的開啟,關閉等一系列操作,如startActivity,startActivityAndWait,activityPaused,startService,stopService,removeContentProvider等;
- 組件狀態(tài)查詢:查詢組件當前運行等情況。如getCallingActivity,getService等;
- Task相關:包括removeTask,removeSubTask,moveTaskBackwards,moveTaskToFront等;
- AMS是通過ActivityStack及其他數(shù)據(jù)結構來記錄,管理系統(tǒng)中的Activity及其他組件狀態(tài)的,并提供查詢功能的一個系統(tǒng)服務;
2、AMS中重要的數(shù)據(jù)結構
ActivityRecord:記錄了Activity的所有信息,因此它用來描述一個activity。它是在activity啟動時被創(chuàng)建的,具體是在ActivityStarter的startActivity()中被創(chuàng)建的。它存儲的信息主要包括以下內容:
- service:AMS的引用
- info:ActivityInfo,Activity中代碼和AndroidManifest設置的節(jié)點信息,如launchMode
- launcherFromPackage:啟動activity的包名
- taskAffinity:activity希望歸屬的棧
- task:TaskRecord,Activity所在的TaskRecord
- app:ProcessRecord,ActivityRecord所在的應用程序進程
- state:ActivityState,當前activity的狀態(tài)
- icon:Activity的圖標資源和標致符
- theme:Activity的主題資源標識符
TaskRecord:用來描述一個Activity任務棧
- taskId:任務棧的唯一標識符
- affinity:任務棧的傾向性
- Intent:啟動這個activity的intent
- mActivites:ArrayList
,按照歷史順序排列的Activity記錄 - mStack:ActivityStack,當前歸屬的ActivityStack
- mService:AMS的引用
ActivityStack:用來管理系統(tǒng)所有的Activity,內部維護了Activity的所有狀態(tài),特殊狀態(tài)的Activity以及和Activity相關的列表等數(shù)據(jù);
二、AMS服務的啟動流程詳解
1、startBootstrapServices
- private void startBootstrapServices() {
- // Activity manager runs the show.
- mActivityManagerService = mSystemServiceManager.startService(
- ActivityManagerService.Lifecycle.class).getService();
- mActivityManagerService.setSystemProcess();
- ……
- mActivityManagerService.installSystemProviders();
- ……
- mActivityManagerService.systemReady(new Runnable() {
- @Override
- public void run() {
- Slog.i(TAG, "Making services ready");
- mSystemServiceManager.startBootPhase(
- SystemService.PHASE_ACTIVITY_MANAGER_READY);
- try {
- mActivityManagerService.startObservingNativeCrashes();
- } catch (Throwable e) {
- reportWtf("observing native crashes", e);
- }
SystemServer中關于AMS啟動時的幾個關鍵方法,主要分為4個步驟
- 創(chuàng)建AMS對象,并啟動服務
- 將AMS所在的系統(tǒng)進程,添加到進程管理中去
- 為系統(tǒng)進程安裝ContentProvider對象
- 在systemReady方法中做善后操作
- 一個一個的來看先這些方法的作用,這些方法就是AMS的啟動和初始化過程;
2、ActivityManagerService
啟動ActivityManagerService的方法
mActivityManagerService = mSystemServiceManager.startService(
ActivityManagerService.Lifecycle.class).getService();
AMS服務同樣是通過SystemServiceManager來啟動的,那我們首先來看ActivityManagerService.Lifecycle的構造方法,然后在來看它的Start函數(shù);
Lifecycle的構造方法中很簡單就是構造一個AMS的對象
mService = new ActivityManagerService(context);
創(chuàng)建AMS對象的時候需要傳遞一個Context作為參數(shù),那這個mSystemContext是就是上面創(chuàng)建的系統(tǒng)Context;
接著看AMS的構造方法;
- public ActivityManagerService(Context systemContext) {
- //系統(tǒng)的context
- mContext = systemContext;
- //獲得系統(tǒng)的ActivityThread
- mSystemThread = ActivityThread.currentActivityThread();
- //創(chuàng)建一個HandlerThread用來處理AMS接收的命令
- mHandlerThread = new ServiceThread(TAG,
- android.os.Process.THREAD_PRIORITY_FOREGROUND, false /*allowIo*/);
- mHandlerThread.start();
- mHandler = new MainHandler(mHandlerThread.getLooper());
- mUiHandler = new UiHandler();
- //初始化廣播的隊列
- 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;
- //初始化Service相關的容器
- mServices = new ActiveServices(this);
- //初始化Provider相關的Map,里面保存了注冊的ContentProvider
- mProviderMap = new ProviderMap(this);
- //初始化并創(chuàng)建data/system/目錄
- File dataDir = Environment.getDataDirectory();
- File systemDir = new File(dataDir, "system");
- systemDir.mkdirs();
- //初始化電量統(tǒng)計服務相關的信息
- mBatteryStatsService = new BatteryStatsService(systemDir, mHandler);
- mBatteryStatsService.getActiveStatistics().readLocked();
- mBatteryStatsService.scheduleWriteToDisk();
- mOnBattery = DEBUG_POWER ? true
- : mBatteryStatsService.getActiveStatistics().getIsOnBattery();
- mBatteryStatsService.getActiveStatistics().setCallback(this);
- //初始化系統(tǒng)統(tǒng)計服務,用于統(tǒng)計系統(tǒng)的運行信息
- mProcessStats = new ProcessStatsService(this, new File(systemDir, "procstats"));
- mAppOpsService = new AppOpsService(new File(systemDir, "appops.xml"), mHandler);
- mGrantFile = new AtomicFile(new File(systemDir, "urigrants.xml"));
- //創(chuàng)建系統(tǒng)的第一個user,userID為0,該用戶具有管理員權限
- mStartedUsers.put(UserHandle.USER_OWNER, new UserState(UserHandle.OWNER, true));
- mUserLru.add(UserHandle.USER_OWNER);
- updateStartedUserArrayLocked();
- //獲取opengle的版本
- GL_ES_VERSION = SystemProperties.getInt("ro.opengles.version",
- ConfigurationInfo.GL_ES_VERSION_UNDEFINED);
- //初始化字體語言等配置信息
- mConfiguration.setToDefaults();
- mConfiguration.setLocale(Locale.getDefault());
- ……;
- mRecentTasks = new RecentTasks(this);
- //初始化StackSupervisor,該類是Activity啟動和調度的核心類
- mStackSupervisor = new ActivityStackSupervisor(this, mRecentTasks);
- mTaskPersister = new TaskPersister(systemDir, mStackSupervisor, mRecentTasks);
- AMS的構造方法主要是在做一些初始化的先關操作;
- 保存了自己的運行環(huán)境的Context和ActivityThread;
- AMS負責調度四大組件,所以會初始化broadcast,service和contentProvider相關的變量,接著初始化了電量統(tǒng)計服務,創(chuàng)建了系統(tǒng)的第一個用戶,初始化了基本的配置信息,還創(chuàng)建了Activity調度的核心類,因為Activity調度比較復雜,Activity相關的信息初始化會在ActivityStackSupervisor中;
3、start
AMS的start方法。
- private void start() {
- mProcessCpuThread.start();
- mBatteryStatsService.publish(mContext);
- LocalServices.addService(ActivityManagerInternal.class, new LocalService());
- }
- AMS的start方法很簡單,只是啟動了幾個服務,并把AMS服務自己保存到localService中供程序內部調用;
- AMS的構造方法和start方法中做了AMS服務一些變量的初始化和相關服務的初始化。接著看下一個重要的方法setSystemProcess;
4、setSystemProcess
ActivityManagerService的setSystemProcess方法
- public void setSystemProcess() {
- try {
- //將AMS注冊到ServiceManager中
- ServiceManager.addService(Context.ACTIVITY_SERVICE, this, true);
- //注冊其他服務到ServiceMananger中
- ServiceManager.addService(ProcessStats.SERVICE_NAME, mProcessStats);
- ServiceManager.addService("meminfo", new MemBinder(this));
- ServiceManager.addService("gfxinfo", new GraphicsBinder(this));
- ServiceManager.addService("dbinfo", new DbBinder(this));
- if (MONITOR_CPU_USAGE) {
- ServiceManager.addService("cpuinfo", new CpuBinder(this));
- }
- //注冊權限服務到ServiceMananger中
- ServiceManager.addService("permission", new PermissionController(this));
- ServiceManager.addService("processinfo", new ProcessInfoService(this));
- //從PMS中查詢包名為android的application,即framework-res的Application信息
- ApplicationInfo info = mContext.getPackageManager().getApplicationInfo(
- "android", STOCK_PM_FLAGS);
- //將application信息配置到開始創(chuàng)建的activityThread中
- mSystemThread.installSystemApplicationInfo(info, getClass().getClassLoader());
- synchronized (this) {
- //創(chuàng)建了一個ProcessRecord對象,該對象中保存著系統(tǒng)ongoing服務的進程信息
- ProcessRecord app = newProcessRecordLocked(info, info.processName, false, 0);
- app.persistent = true;
- app.pid = MY_PID;
- app.maxAdj = ProcessList.SYSTEM_ADJ;
- app.makeActive(mSystemThread.getApplicationThread(), mProcessStats);
- synchronized (mPidsSelfLocked) {
- 然后將系統(tǒng)進程的processRecord對象也添加到mPidsSelfLocked集合中,和普通應用的進程一樣,接收AMS的管理調度
- mPidsSelfLocked.put(app.pid, app);
- }
- //更細進程管理的調度信息
- updateLruProcessLocked(app, false, null);
- updateOomAdjLocked();
- }
- setSystemProcess方法中,首先將自己AMS服務注冊到了ServiceManager中,然后又注冊了權限服務等其他的系統(tǒng)服務;
- 通過先前創(chuàng)建的Context,得到PMS服務,檢索framework-res的Application信息,然后將它配置到系統(tǒng)的ActivityThread中;
- 為了能讓AMS同樣可以管理調度系統(tǒng)進程,也創(chuàng)建了一個關于系統(tǒng)進程的ProcessRecord對象,ProcessRecord對象保存一個進程的相關信息;
- 然后將它保存到mPidsSelfLocked集合中方便管理;
- AMS具體是如何將檢索到的framework-res的application信息,配置到ActivityThread中的,需要繼續(xù)分析ActivityThread的installSystemApplicationInfo方法;
接著看installSystemApplicationInfo方法
- public void installSystemApplicationInfo(ApplicationInfo info, ClassLoader classLoader) {
- synchronized (this) {
- getSystemContext().installSystemApplicationInfo(info, classLoader);
- }
- }
這個方法中最終調用上面創(chuàng)建的SystemContext的installSystemApplication方法,那就接著看ConxtextImpl的installSystemApplication方法。
- void installSystemApplicationInfo(ApplicationInfo info, ClassLoader classLoader) {
- mPackageInfo.installSystemApplicationInfo(info, classLoader);
- }
- 它有最終調用了mPackageInfo的installSystemApplication方法,mPackageInfo就是在創(chuàng)建Context對象的時候傳進來的LoadedApk,里面保存了一個應用程序的基本信息;
- setSystemProcess主要就是設置系統(tǒng)集成的一些信息,在這里設置了系統(tǒng)進程的Application信息,創(chuàng)建了系統(tǒng)進程的ProcessRecord對象將其保存在進程集合中,方便AMS管理調度;
5、installSystemProvider
- ActivityManagerService的installSystemProvider方法;
- Android系統(tǒng)中有很多配置信息都需要保存,這些信息是保存在SettingsProvider中,而這個SettingsProvider也是運行在SystemServer進程中的,由于SystemServer進程依賴SettingsProvider,放在一個進程中可以減少進程間通信的效率損失;
- 下面就來分析下如何將SettingsProvider.apk也加載到SystemServer進程中;
- public final void installSystemProviders() {
- List<ProviderInfo> providers;
- synchronized (this) {
- //找到名稱為”System”的進程,就是上一步創(chuàng)建的processRecord對象
- ProcessRecord app = mProcessNames.get("system", Process.SYSTEM_UID);
- //找到所有和system進程相關的ContentProvider
- providers = generateApplicationProvidersLocked(app);
- if (providers != null) {
- for (int i=providers.size()-1; i>=0; i--) {
- ProviderInfo pi = (ProviderInfo)providers.get(i);
- //再次確認進程為system的provider,把不是該進程provider移除
- if ((pi.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) == 0) {
- Slog.w(TAG, "Not installing system proc provider " + pi.name
- + ": not system .apk");
- providers.remove(i);
- }
- }
- }
- }
- if (providers != null) {
- //把provider安裝到系統(tǒng)的ActivityThread中
- mSystemThread.installSystemProviders(providers);
- }
- mCoreSettingsObserver = new CoreSettingsObserver(this);
- }
找到名稱為system的進程對象,就是SystemServer進程,然后根據(jù)進程對象去查詢所有有關的ContentProvider,調用系統(tǒng)進程的主線程ActivityThread安裝所有相關的ContentProvider,具體是如何查找相關的contentProvider和如何安裝ContentProvider到系統(tǒng)主線程的,接著分析下面兩個方法;
- private final List<ProviderInfo> generateApplicationProvidersLocked(ProcessRecord app) {
- List<ProviderInfo> providers = null;
- try {
- //調用PMS根據(jù)進程ID和進程名稱來查詢Provider
- ParceledListSlice<ProviderInfo> slice = AppGlobals.getPackageManager().
- queryContentProviders(app.processName, app.uid,
- STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
- providers = slice != null ? slice.getList() : null;
- } catch (RemoteException ex) {
- }
- int userId = app.userId;
- if (providers != null) {
- int N = providers.size();
- for (int i=0; i<N; i++) {
- ProviderInfo cpi =
- (ProviderInfo)providers.get(i);
- ……
- ComponentName comp = new ComponentName(cpi.packageName, cpi.name);
- //從AMS管理的contentProvider列表中查詢對應的provider
- ContentProviderRecord cpr = mProviderMap.getProviderByClass(comp, userId);
- if (cpr == null) {
- //如果AMS的Provider列表中沒有對應的Provider實例,就根據(jù)查詢的provider信息,創(chuàng)建一個對象保存到隊列中
- cpr = new ContentProviderRecord(this, cpi, app.info, comp, singleton);
- mProviderMap.putProviderByClass(comp, cpr);
- }
- //同時將provider保存到processRecord對象的pubProviders列表中
- app.pubProviders.put(cpi.name, cpr);
- ……
- }
- }
- return providers;
- }
- 這個方法就是從PMS中查詢和SystemServer進程相關的Provider,也就是SettingsProvder,然后將它保存到AMS的contentProvider列表中;
- 同時也將它保存到系統(tǒng)進程對象ProcessRecord的變量pubProviders列表中,保存到AMS的provider列表中是因為AMS需要管理所有的ContentProvder;
- 保存到進程對象的pubProviders列表中是因為,每個ContentProvider都需要對應到一個進程中去;
- 接著看如何將SettingsProvider安裝到系統(tǒng)的主進程中去;
- private void installContentProviders(
- Context context, List<ProviderInfo> providers) {
- ……
- for (ProviderInfo cpi : providers) {
- //通過installProvider方法把provider封裝成一個ContentProviderHolder對象,有利于進程間傳輸
- IActivityManager.ContentProviderHolder cph = installProvider(context, null, cpi,
- false /*noisy*/, true /*noReleaseNeeded*/, true /*stable*/);
- if (cph != null) {
- cph.noReleaseNeeded = true;
- results.add(cph);
- }
- }
- try {
- //將上面得到的contentProviderHolder對象發(fā)布到AMS服務,getApplicationThread代表本地進程的一個binder對象,binder對象可跨進程傳輸,它在AMS中對應一個ProcessRecord.
- ActivityManagerNative.getDefault().publishContentProviders(
- getApplicationThread(), results);
- ……
- }
- 該方法將得到的contentProvider對象封裝成了contentProviderHolder對象,其實就是Binder對象,這樣就可以進程間傳輸了,然后跨進程調用AMS服務注冊Provider;
- AMS負責管理ContentProvider,只有將ContentProvider注冊到AMS服務其他進程才能訪問;
- 接著看AMS如何注冊Provider;
6、publishContentProviders
- public final void publishContentProviders(IApplicationThread caller,
- List<ContentProviderHolder> providers) {
- ……
- //根據(jù)調用者的進程得到相應的processRecord對象,就是系統(tǒng)進程的ProcessRecord
- final ProcessRecord r = getRecordForAppLocked(caller);
- ……
- final int N = providers.size();
- for (int i = 0; i < N; i++) {
- //ActivityThread客戶端傳過來的provider src
- ContentProviderHolder src = providers.get(i);
- //根據(jù)src provider name得到一開始保存的進程中保存的ProciderRecord
- ContentProviderRecord dst = r.pubProviders.get(src.info.name);
- if (dst != null) {
- ComponentName comp = new ComponentName(dst.info.packageName, dst.info.name);
- //按類將它保存在mProviderMap中
- mProviderMap.putProviderByClass(comp, dst);
- String names[] = dst.info.authority.split(";");
- for (int j = 0; j < names.length; j++) {
- //按authority保存在mProviderMap中
- mProviderMap.putProviderByName(names[j], dst);
- }
- ……
- }
- AMS的注冊服務就是根據(jù)參數(shù)傳過來的provider信息,找到原先進程中pubProviders列表中保存的ContentProviderRecord,然后將它分別以類為key保存在mProviderMap中,和以authority為key保存在mProviderMap中;
- 即AMS提供了多種方案來查找一個ContentProvider,一種是通過authority來查找,一種是指明CompomentName來查找;
- 此刻位置一個SettingsProvider就正式注冊到SystemServer進程中了,所以可以看出installSystemProvider方法的主要工作就是按照普通進程類似的方式,將SettingsProvider注冊到系統(tǒng)進程中,方便系統(tǒng)進程對settings的配置數(shù)據(jù)進行調用;
7、systemReady
ActivityManagerService的systemReady方法
- public void systemReady(final Runnable goingCallback) {
- synchronized(this) {
- //初始化Doze模式的controller
- mLocalDeviceIdleController
- = LocalServices.getService(DeviceIdleController.LocalService.class);
- //重置RecentTasks
- mRecentTasks.clear();
- mRecentTasks.addAll(mTaskPersister.restoreTasksLocked());
- mRecentTasks.cleanupLocked(UserHandle.USER_ALL);
- mTaskPersister.startPersisting();
- ……
- //設置systemReady為true
- mSystemReady = true;
- }
- ArrayList<ProcessRecord> procsToKill = null;
- //收集那些在AMS之前啟動的進程
- 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);
- }
- }
- }
- //將那些在AMS之前啟動的進程殺死,有的進程不能再AMS之前啟動
- 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");
- }
- }
- }
- //從settingsProvider的設置總初始化部分變量
- retrieveSettings();
- //調用callback方法,該方法在systemServer代碼中實現(xiàn)
- if (goingCallback != null) goingCallback.run();
- //查詢那些persistent為1的application,并啟動他們所在的進程
- 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 */);
- }
- }
- //啟動HomeActivity,也就是launcher程序
- mBooting = true;
- startHomeActivityLocked(mCurrentUserId, "systemReady");
- ……
- }
- }
SystemReady方法也是比較長,大致可以分為:
- 第一:在systemReady的時候初始化了deviceIdleController等對象
- 第二:移除并殺死了那些不該在AMS之前啟動的進程
- 第三:執(zhí)行了參數(shù)傳入的回調函數(shù)
- 第四:啟動了Launcer界面
- 第五:啟動那些persistent配置為1的進程;
- 再來看些systemReady參數(shù)的回調函數(shù)做了什么工作.
- try {
- //ams開始監(jiān)聽native層的crash信息
- mActivityManagerService.startObservingNativeCrashes();
- } catch (Throwable e) {
- reportWtf("observing native crashes", e);
- }
- //初始化webVew
- WebViewFactory.prepareWebViewInSystemServer();
- try {
- //啟動systemUI
- startSystemUi(context);
- } catch (Throwable e) {
reportWtf("starting System UI", e);
- }
- try {
- //調用其他服務的systemready方法
- if (networkScoreF != null) networkScoreF.systemReady();
- } catch (Throwable e) {
- reportWtf("making Network Score Service ready", e);
- }
這個回調函數(shù)中主要工作就是啟動systemUI并調用其他服務的systemReady方法,SystemReady函數(shù)完成了系統(tǒng)就緒的必要的工作,啟動了HomeActivity和SystemUI,然后Android系統(tǒng)就全部啟動了;
總結
AMS服務啟動主要分為幾個步驟:
- 調用AMS的構造方法和start方法,對AMS必要的內容進行初始化;
- 將函數(shù)AMS注冊到ServiceManager中,同時對systemServer進程也創(chuàng)建了一個ProcessRecord對象,并設置Context的appliation為framework-res的application對象;
- 將settingsProvider加載到系統(tǒng)進程systemServer中;
- 調用systemReady方法做一些啟動前的就緒工作,并啟動了HomeActivity和SystemUI;
本文轉載自微信公眾號「Android開發(fā)編程」