前言
AMS(ActivityManagerService)Android的核心服务之一,对于framework各个核心服务,如果不是专门去做framework开发,先了解其基本的流程机制,再慢慢深究;
今天我们就来学习下AMS
一、AMS功能概述
1、AMS介绍
AMS是Android中最核心的服务,主要负责系统中四大组件的启动、切换、调度及应用进程的管理和调度等工作,其职责与操作系统中的进程管理和调度模块相类似,因此它在Android中非常重要;
组件状态管理:包括四大组件的开启,关闭等一系列操作,如startActivity,startActivityAndWait,activityPaused,startService,stopService,removeContentProvider等;
组件状态查询:查询组件当前运行等情况。如getCallingActivity,getService等;
Task相关:包括removeTask,removeSubTask,moveTaskBackwards,moveTaskToFront等;
AMS是通过ActivityStack及其他数据结构来记录,管理系统中的Activity及其他组件状态的,并提供查询功能的一个系统服务;
2、AMS中重要的数据结构
ActivityRecord:记录了Activity的所有信息,因此它用来描述一个activity。它是在activity启动时被创建的,具体是在ActivityStarter的startActivity()中被创建的。它存储的信息主要包括以下内容:
service:AMS的引用
info:ActivityInfo,Activity中代码和AndroidManifest设置的节点信息,如launchMode
launcherFromPackage:启动activity的包名
taskAffinity:activity希望归属的栈
task:TaskRecord,Activity所在的TaskRecord
app:ProcessRecord,ActivityRecord所在的应用程序进程
state:ActivityState,当前activity的状态
icon:Activity的图标资源和标致符
theme:Activity的主题资源标识符
TaskRecord:用来描述一个Activity任务栈
taskId:任务栈的唯一标识符
affinity:任务栈的倾向性
Intent:启动这个activity的intent
mActivites:ArrayList<ActivityRecord>,按照历史顺序排列的Activity记录
mStack:ActivityStack,当前归属的ActivityStack
mService:AMS的引用
ActivityStack:用来管理系统所有的Activity,内部维护了Activity的所有状态,特殊状态的Activity以及和Activity相关的列表等数据;
二、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() {@Overridepublic 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个步骤
创建AMS对象,并启动服务
将AMS所在的系统进程,添加到进程管理中去
为系统进程安装ContentProvider对象
在systemReady方法中做善后操作
一个一个的来看先这些方法的作用,这些方法就是AMS的启动和初始化过程;
2、ActivityManagerService
启动ActivityManagerService的方法
mActivityManagerService = mSystemServiceManager.startService(
ActivityManagerService.Lifecycle.class).getService();
AMS服务同样是通过SystemServiceManager来启动的,那我们首先来看ActivityManagerService.Lifecycle的构造方法,然后在来看它的Start函数;
Lifecycle的构造方法中很简单就是构造一个AMS的对象
mService = new ActivityManagerService(context);
创建AMS对象的时候需要传递一个Context作为参数,那这个mSystemContext是就是上面创建的系统Context;
接着看AMS的构造方法;
public ActivityManagerService(Context systemContext) {//系统的contextmContext = systemContext;//获得系统的ActivityThreadmSystemThread = ActivityThread.currentActivityThread();//创建一个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,里面保存了注册的ContentProvidermProviderMap = new ProviderMap(this);//初始化并创建data/system/目录File dataDir = Environment.getDataDirectory();File systemDir = new File(dataDir, "system");systemDir.mkdirs();//初始化电量统计服务相关的信息mBatteryStatsService = new BatteryStatsService(systemDir, mHandler);mBatteryStatsService.getActiveStatistics().readLocked();mBatteryStatsService.scheduleWriteToDisk();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);mGrantFile = new AtomicFile(new File(systemDir, "urigrants.xml"));//创建系统的第一个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的构造方法主要是在做一些初始化的先关操作;
保存了自己的运行环境的Context和ActivityThread;
AMS负责调度四大组件,所以会初始化broadcast,service和contentProvider相关的变量,接着初始化了电量统计服务,创建了系统的第一个用户,初始化了基本的配置信息,还创建了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信息配置到开始创建的activityThread中mSystemThread.installSystemApplicationInfo(info, getClass().getClassLoader());synchronized (this) {//创建了一个ProcessRecord对象,该对象中保存着系统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) {然后将系统进程的processRecord对象也添加到mPidsSelfLocked集合中,和普通应用的进程一样,接收AMS的管理调度mPidsSelfLocked.put(app.pid, app);}//更细进程管理的调度信息updateLruProcessLocked(app, false, null);updateOomAdjLocked();}
setSystemProcess方法中,首先将自己AMS服务注册到了ServiceManager中,然后又注册了权限服务等其他的系统服务;
通过先前创建的Context,得到PMS服务,检索framework-res的Application信息,然后将它配置到系统的ActivityThread中;
为了能让AMS同样可以管理调度系统进程,也创建了一个关于系统进程的ProcessRecord对象,ProcessRecord对象保存一个进程的相关信息;
然后将它保存到mPidsSelfLocked集合中方便管理;
AMS具体是如何将检索到的framework-res的application信息,配置到ActivityThread中的,需要继续分析ActivityThread的installSystemApplicationInfo方法;
接着看installSystemApplicationInfo方法
public void installSystemApplicationInfo(ApplicationInfo info, ClassLoader classLoader) {synchronized (this) {getSystemContext().installSystemApplicationInfo(info, classLoader);}}
这个方法中最终调用上面创建的SystemContext的installSystemApplication方法,那就接着看ConxtextImpl的installSystemApplication方法。
void installSystemApplicationInfo(ApplicationInfo info, ClassLoader classLoader) {mPackageInfo.installSystemApplicationInfo(info, classLoader);}
它有最终调用了mPackageInfo的installSystemApplication方法,mPackageInfo就是在创建Context对象的时候传进来的LoadedApk,里面保存了一个应用程序的基本信息;
setSystemProcess主要就是设置系统集成的一些信息,在这里设置了系统进程的Application信息,创建了系统进程的ProcessRecord对象将其保存在进程集合中,方便AMS管理调度;
5、installSystemProvider
ActivityManagerService的installSystemProvider方法;
Android系统中有很多配置信息都需要保存,这些信息是保存在SettingsProvider中,而这个SettingsProvider也是运行在SystemServer进程中的,由于SystemServer进程依赖SettingsProvider,放在一个进程中可以减少进程间通信的效率损失;
下面就来分析下如何将SettingsProvider.apk也加载到SystemServer进程中;
public final void installSystemProviders() {List<ProviderInfo> providers;synchronized (this) {//找到名称为”System”的进程,就是上一步创建的processRecord对象ProcessRecord app = mProcessNames.get("system", Process.SYSTEM_UID);//找到所有和system进程相关的ContentProviderproviders = 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安装到系统的ActivityThread中mSystemThread.installSystemProviders(providers);}mCoreSettingsObserver = new CoreSettingsObserver(this);}
找到名称为system的进程对象,就是SystemServer进程,然后根据进程对象去查询所有有关的ContentProvider,调用系统进程的主线程ActivityThread安装所有相关的ContentProvider,具体是如何查找相关的contentProvider和如何安装ContentProvider到系统主线程的,接着分析下面两个方法;
private final List<ProviderInfo> generateApplicationProvidersLocked(ProcessRecord app) {List<ProviderInfo> providers = null;try {//调用PMS根据进程ID和进程名称来查询ProviderParceledListSlice<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列表中查询对应的providerContentProviderRecord cpr = mProviderMap.getProviderByClass(comp, userId);if (cpr == null) {//如果AMS的Provider列表中没有对应的Provider实例,就根据查询的provider信息,创建一个对象保存到队列中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列表中;
同时也将它保存到系统进程对象ProcessRecord的变量pubProviders列表中,保存到AMS的provider列表中是因为AMS需要管理所有的ContentProvder;
保存到进程对象的pubProviders列表中是因为,每个ContentProvider都需要对应到一个进程中去;
接着看如何将SettingsProvider安装到系统的主进程中去;
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对象发布到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) {……//根据调用者的进程得到相应的processRecord对象,就是系统进程的ProcessRecordfinal ProcessRecord r = getRecordForAppLocked(caller);……final int N = providers.size();for (int i = 0; i < N; i++) {//ActivityThread客户端传过来的provider srcContentProviderHolder src = providers.get(i);//根据src provider name得到一开始保存的进程中保存的ProciderRecordContentProviderRecord 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的注册服务就是根据参数传过来的provider信息,找到原先进程中pubProviders列表中保存的ContentProviderRecord,然后将它分别以类为key保存在mProviderMap中,和以authority为key保存在mProviderMap中;
即AMS提供了多种方案来查找一个ContentProvider,一种是通过authority来查找,一种是指明CompomentName来查找;
此刻位置一个SettingsProvider就正式注册到SystemServer进程中了,所以可以看出installSystemProvider方法的主要工作就是按照普通进程类似的方式,将SettingsProvider注册到系统进程中,方便系统进程对settings的配置数据进行调用;
7、systemReady
ActivityManagerService的systemReady方法
public void systemReady(final Runnable goingCallback) {synchronized(this) {//初始化Doze模式的controllermLocalDeviceIdleController= LocalServices.getService(DeviceIdleController.LocalService.class);//重置RecentTasksmRecentTasks.clear();mRecentTasks.addAll(mTaskPersister.restoreTasksLocked());mRecentTasks.cleanupLocked(UserHandle.USER_ALL);mTaskPersister.startPersisting();……//设置systemReady为truemSystemReady = 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代码中实现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之前启动的进程
第三:执行了参数传入的回调函数
第四:启动了Launcer界面
第五:启动那些persistent配置为1的进程;
再来看些systemReady参数的回调函数做了什么工作.
try {//ams开始监听native层的crash信息mActivityManagerService.startObservingNativeCrashes();} catch (Throwable e) {reportWtf("observing native crashes", e);}//初始化webVewWebViewFactory.prepareWebViewInSystemServer();try {//启动systemUIstartSystemUi(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);}
这个回调函数中主要工作就是启动systemUI并调用其他服务的systemReady方法,SystemReady函数完成了系统就绪的必要的工作,启动了HomeActivity和SystemUI,然后Android系统就全部启动了;
总结
AMS服务启动主要分为几个步骤:
调用AMS的构造方法和start方法,对AMS必要的内容进行初始化;
将函数AMS注册到ServiceManager中,同时对systemServer进程也创建了一个ProcessRecord对象,并设置Context的appliation为framework-res的application对象;
将settingsProvider加载到系统进程systemServer中;
调用systemReady方法做一些启动前的就绪工作,并启动了HomeActivity和SystemUI;
推荐阅读
Android10以上系统Audio音频遇到播放视频无声时的分析方法
干货|Android APP应用工程师转Framework工程师(仅此一篇够了)
Android中实现系统声音录制(内置声源的录制)-framework调用流程分析