ActivityManagerService是Android系统中一个特别重要的系统服务,由SytemServer启动,运行在SytemServer进程。也是上层APP打交道最多的系统服务之一。ActivityManagerService(以下简称AMS) 主要负责四大组件的启动、切换、调度以及应用进程的管理和调度工作。所有的APP应用都需要与AMS打交道。
Activity Manager的组成主要分为以下几个部分:
- 服务代理:由ActivityManagerProxy实现,用于与Server端提供的系统服务进行进程间通信
- 服务中枢:ActivityManagerNative继承自Binder并实现IActivityManager,它提供了服务接口和Binder接口的相互转化功能,并在内部存储服务代理对像,并提供了getDefault方法返回服务代理
- Client:由ActivityManager封装一部分服务接口供Client调用。ActivityManager内部通过调用ActivityManagerNative的getDefault方法,可以得到一个ActivityManagerProxy对像的引用,进而通过该代理对像调用远程服务的方法
- Server:由ActivityManagerService实现,提供Server端的系统服务
AMS的启动过程
AMS是在SystemServer中被添加的, 所以先到SystemServer中查看初始化
1 | public static void main(String[] args) { |
在SystemServer中,在startBootstrapServices()中去启动了AMS
1 | private void startBootstrapServices() { |
AMS是通过SystemServiceManager.startService去启动的,参数是ActivityManagerService.Lifecycle.class, 首先看看startService方法
1 | frameworks/base/services/core/java/com/android/server/SystemServiceManager.java |
startService方法很简单,是通过传进来的class然后反射创建对应的service服务。所以此处创建的是Lifecycle的实例, 然后通过startService启动了AMS服务,那再去看看ActivityManagerService.Lifecycle这个类的构造方法
1 | public static final class Lifecycle extends SystemService { |
再来看下AMS初始化做了什么
1 | public ActivityManagerService(Context systemContext) { |
1 | private void start() { |
再看下setSystemProcess 干了什么
1 | public void setSystemProcess() { |
注册服务。首先将ActivityManagerService注册到ServiceManager中,其次将几个与系统性能调试相关的服务注册到ServiceManager。
查询并处理ApplicationInfo。首先调用PackageManagerService的接口,查询包名为android的应用程序的ApplicationInfo信息,对应于framework-res.apk。然后以该信息为参数调用ActivityThread上的installSystemApplicationInfo方法。
创建并处理ProcessRecord。调用ActivityManagerService上的newProcessRecordLocked,创建一个 ProcessRecord类型的对象,并保存该对象的信息。
AMS是什么
- 从java角度来看,AMS就是一个java对象,实现了Ibinder接口,所以它是一个用于进程之间通信的 接口,这个对象初始化是在systemServer.java 的run()方法里面。
- AMS是一个服务,ActivityManagerService从名字就可以看出,它是一个服务,用来管理Activity,而且是一个系统服务
- AMS是一个Binder,AMS实现了Ibinder接口,所以它是一个Binder,这意味着他不但可以用于进程间通信,还是一个线程,因为一个Binder就是一个线程。
AMS相关重要类介绍
ProcessRecord
第一类数据:描述身份的数据
- ApplicationInfo info:AndroidManifest.xml中定义的Application信息
- boolean isolated:是不是isolated进程
- int uid:进程uid
- int userId:这个是android做的多用户系统id,就像windows可以登录很多用户一样,android 也希望可以实现类似的多用户
- String processName:进程名字,默认情况下是包名
- UidRecord uidRecord:记录已经使用的uid
- IApplicationThread thread:这个很重要,它是ApplicationThread的客户端,AMS就是通过这个对象给apk进程发送异步消息的(管理四大组件的消息),所以只有这个对象不为空的情况下, 才代表apk进程可是使用了
- int pid:进程的pid
- String procStatFile:proc目录下每一个进程都有一个以pid命名的目录文件,这个目录下记载着 进程的详细信息,这个目录及目录下的文件是内核创建的, proc是内核文件系统,proc就是 process的缩写,涉及的目的就是导出进程内核信息
- int[] gids:gid组
- CompatibilityInfo compat : 兼容性信息
- String requiredAbi : abi信息
- String instructionSet : 指令集信息
第二类数据:描述进程中组件的数据
- pkgList:进程中运行的包
- ArraySet pkgDeps:进程运行依赖的包
- ArrayList activities:进程启动的所有的activity组件记录表
- ArraySet services:进程启动的所有的service组件记录表
- ArraySet executingServices:正在运行(executing)是怎么定义的?首先需要明确的是系统是怎么控制组件的?发送消息给apk进程,apk进程处理消息,上报消息完成,这被定义为一个完整的执行过程,因此正在执行(executing)被定义为发送消息到上报完成这段时间
- ArraySet connections:绑定service的客户端记录表
- ArraySet receivers:广播接收器的记录表
- ContentProviderRecord pubProviders:pub是publish(发布)的意思,ContentProvider需要 安装然后把自己发布到系统(AMS)中后,才能使用,安装指的是apk进程加载ContentProvider 子类、初始化、创建数据库等过程,发布是将ContentProvider的binder客户端注册到AMS中
- ArrayList conProviders:使用ContentProvider的客户端记录表
- BroadcastRecord curReceiver:当前进程正在执行的广播
第三类数据:描述进程状态的数据
- int maxAdj:进程的adj上限(adjustment)
- int curRawAdj:当前正在计算的adj,这个值有可能大于maxAdj
- int setRawAdj:上次计算的curRawAdj设置到lowmemorykiller系统后的adj
- int curAdj:当前正在计算的adj,这是curRawAdj被maxAdj削平的值
- int setAdj:上次计算的curAdj设置到lowmemorykiller系统后的adj
- int verifiedAdj:setAdj校验后的值
- int curSchedGroup:正在计算的调度组
- int setSchedGroup:保存上次计算的调度组
- int curProcState:正在计算的进程状态
- int repProcState:发送给apk进程的状态
- int setProcState:保存上次计算的进程状态
- int pssProcState:pss进程状态
- ProcessState baseProcessTracker:进程状态监测器
- int adjSeq:计算adj的序列数
- int lruSeq:lru序列数
- IBinder forcingToForeground:强制将进程的状态设置为前台运行的IBinder,IBinder代表的是 组件的ID,这个是整个android系统唯一
第四类数据:和pss相关的数据
- long initialIdlePss:初始化pss
- long lastPss:上次pss
- long lastSwapPss:上次SwapPss数据
- long lastCachedPss:上次CachedPss数据
- long lastCachedSwapPss:上次CachedSwapPss数据
1 | VSS- Virtual Set Size 虚拟耗用内存(包含共享库占用的内存) |
第五类数据:和时间相关的数据
- long lastActivityTime:上次使用时间
- long lastPssTime:上次计算pss的时间
- long nextPssTime:下次计算pss的时间
- long lastStateTime:上次设置进程状态的时间
- long lastWakeTime:持有wakelock的时长
- long lastCpuTime:上次计算占用cpu的时长
- long curCpuTime:当前最新占用cpu的时长
- long lastRequestedGc:上次发送gc命令给apk进程的时间
- long lastLowMemory:上次发送低内存消息给apk进程的时间
- long lastProviderTime:上次进程中ContentProvider被使用的时间
- long interactionEventTime:上次发送交互时间时间
- long fgInteractionTime:变成前台的时间
第六类数据:crash和anr相关的数据
- IBinder.DeathRecipient deathRecipient:apk进程退出运行的话,会触发这个对象的 binderDied()方法,来回收系统资源
- boolean crashing:进程已经crash
- Dialog crashDialog:crash对话框
- boolean forceCrashReport:强制crash对话框显示
- boolean notResponding:是否处于anr状态
- Dialog anrDialog:anr显示对话框
- Runnable crashHandler:crash回调
- ActivityManager.ProcessErrorStateInfo crashingReport:crash报告的进程状态
- ActivityManager.ProcessErrorStateInfo notRespondingReport:anr报告的进程状态
- String waitingToKill:后台进程被kill原因
- ComponentName errorReportReceiver:接收error信息的组件
第七类数据:和instrumentation相关的数据
instrumentation 也可以说是apk的一个组件,如果提供的话,系统会默认使用 Instrumentation.java类,按照我们一般的理解,UI 线程控制activity的生命周期,是直接调用Activity 类的方法,实际是,UI线程调用的是instrumentation的方法,由它在调用Activity涉及生命周期的方法,所有如果我们覆写了instrumentation的这些方法,就可以了解所有的Activity的生命周期了。
- ComponentName instrumentationClass:AndroidManifest.xml中定义的instrumentation信 息
- ApplicationInfo instrumentationInfo:instrumentation应用信息
- String instrumentationProfileFile:instrumentation配置文件
- IInstrumentationWatcher instrumentationWatcher:instrumentation监测器
- IUiAutomationConnection instrumentationUiAutomationConnection:UiAutomation连接器
- ComponentName instrumentationResultClass:返回结果组件
第八类数据:电源信息和调试信息
- BatteryStatsImpl mBatteryStats:电量信息
- BatteryStatsImpl.Uid.Proc curProcBatteryStats:当前进程电量信息
- boolean debugging:处于调试中
- boolean waitedForDebugger:等待调试
- Dialog waitDialog:等待对话框
- String adjType:adj类型(或者说标示)
- int adjTypeCode:adj类型码(也是一种标示)
- Object adjSource:改变adj的组件记录表
- int adjSourceProcState:影响adj的进程状态
- Object adjTarget:改变adj的组件
- String shortStringName:进程记录表的字符串显示
- String stringName:进程记录表的字符串显示
第九类数据:一堆boolean类型的值
进程声明周期相关的
a.boolean starting:进程正在启动
b.boolean removed:进程系统资源已经清理
c.boolean killedByAm:进程被AMS主动kill掉
d.boolean killed:进程被kill掉了
e:boolean persistent:常驻内存进程
组件状态影响进程行为的
a.boolean empty:空进程,不含有任何组件的进程
b.boolean cached:缓存进程
c.boolean bad:60s内连续crash两次的进程被定义为bad进程
d.boolean hasClientActivities:进程有Activity绑定其他Service
e.boolean hasStartedServices:进程中包含启动了的Service
f.boolean foregroundServices:进程中包含前台运行的Service
g.boolean foregroundActivities:进程中包含前台运行的Activity
h.boolean repForegroundActivities:
i.boolean systemNoUi:系统进程,没有显示UI
j.boolean hasShownUi:重进程启动开始,是否已经显示UI
k.boolean pendingUiClean:
l.boolean hasAboveClient:进程中有组件使用BIND_ABOVE_CLIENT标志绑定其他Service
m.boolean treatLikeActivity:进程中有组件使用BIND_TREAT_LIKE_ACTIVITY标志绑定其他 Service
n.boolean execServicesFg:前台执行Service
o.boolean setIsForeground:设置运行前台UI
还有一些其他的。
ProcessRecord容器
永久性容器
- mProcessNames:根据进程名字检索进程记录表
- mPidsSelfLocked:根据进程pid检索进程记录表
- mLruProcesses:lru进程记录表容器,这个容器使用的是最近最少使用算法对进程记录表进行排 序,越是处于上层的越是最近使用的,对于系统来说就是最重要的,在内存吃紧回收进程时,越不 容易被回收,实现起来也很简单
临时性容器
- mPersistentStartingProcesses:常驻内存进程启动时容器
- mProcessesOnHold:进程启动挂起容器
- mProcessesToGc:将要执行gc回收的进程容器
- mPendingPssProcesses:将要计算Pss数据的进程容器
mRemovedProcesses:已经移除的进程
内部四大组件记录表的容器
组件运行才是进程存在的意义,由于android系统进程间的无缝结合,所以系统需要控制到组件级别, 所有的组件信息都需要映射到系统,
一个ActivityRecord记录对应一个Activity的信息
一个 ServiceRecord记录对应一个Service的信息
一个ConnectionRecord记录对应一个bind service的客户端信息
一个ReceiverList对应处理同一事件的一组广播
一个ContentProviderRecord记录对应一个 ContentProvider信息
一个ContentProviderConnection对应一个进程中的所有ContentProvider客户端
activity记录
activities:ActivityRecord的容器,进程启动的所有的activity组件记录表
service记录
services:ServiceRecord的容器,进程启动的所有的service组件记录表
executingServices:正在运行(executing)的ServiceRecord是怎么定义的?首先需要明确的是 系统是怎么控制组件的?发送消息给apk进程,apk进程处理消息,上报消息完成,这被定义为一 个完整的执行过程,因此正在执行(executing)被定义为发送消息到上报完成这段时间
connections:ConnectionRecord容器,绑定service的客户端记录表
广播接收器记录
receivers:ReceiverList容器,广播接收器的记录表
ContentProvider记录
pubProviders:名字到ContentProviderRecord的映射容器,pub是publish(发布)的意思, ContentProvider需要安装然后把自己发布到系统(AMS)中后,才能使用,安装指的是apk进程 加载ContentProvider子类、初始化、创建数据库等过程,发布是将ContentProvider的binder客户端注册到AMS中
conProviders:ContentProviderConnection容器,使用ContentProvider的客户端记录表
与Activity管理有关的数据结构
ActivityRecord
ActivityRecord,源码中的注释介绍:An entry in the history stack, representing an activity. 翻译:历史栈中的一个条目,代表一个activity。
ActivityRecord中存在着大量的成员变量,包含了一个Activity的所有信息。 ActivityRecord中的成员变量task表示其所在的TaskRecord,由此ActivityRecord与 TaskRecord建立了联系。
TaskRecord
TaskRecord,内部维护一个ArrayList用来保存ActivityRecord,TaskRecord中的mStack表示其所在的ActivityStack。 startActivity()时也会创建一个TaskRecord
ActivityStack
ActivityStack,内部维护了一个ArrayList,用来管理TaskRecord,ActivityStack中还持有ActivityStackSupervisor对象,这个是用来管理ActivityStacks的。 ActivityStack是由ActivityStackSupervisor来创建的,实际ActivityStackSupervisor就是用来管理 ActivityStack的
ActivityStackSupervisor
ActivityStackSupervisor内部有两个不同的ActivityStack对象:mHomeStack、mFocusedStack,用来管理不同的任务。 ActivityStackSupervisor内部包含了创建ActivityStack对象的方法。 AMS初始化时会创建一个ActivityStackSupervisor对象。
Activity启动流程相关
整体流程
以Launcher打开应用为例,整体流程如下:
1、Launcher通过ActivityTaskManger向ATMS请求打开应用
2、ATMS内部判断进程是否存在,不存在通知Zygote fork一个新的进程
3、Zygote fork新的进程启动后,把ApplicationThread attach到AMS
4、AMS绑定后执行Activity的启动,ATMS执行启动流程,向APP发生启动事件
5、APP处理启动事件,执行Activity的生命周期。
打开应用,进程存在的情况下,Activity启动流程都是一样的,不同的是目标进程是否存在的情况下,下面先看下进程不存在的情况下,进程创建的流程,就是上面总体流程图中的2,3,4三步。
AMS通知Zygote fork新进程的过程
Application进程启动后,attach过程
上面的两个时序图是Zygote fork新进程启动后,然后把app的IBinder绑定到了AMS的过程。ApplicationThread实现了IApplicationThread.Stub,是y一个Ibinder类,就是这个类在负责接收AMS的消息。
进程已经存在后面再梳理下Activity是如何启动的。大流程可以分为下面五步:
1、启动Activity端,准备启动参数阶段,Intent处理,前置条件判断
2、AMS端,处理ActivityStack阶段,产生ClientTransaction
3、跨进程传递生命周期触发器ClientTransaction阶段,传递给目标Activity端
4、目标Activity端生命周期触发器ClientTransaction触发执行阶段
5、启动Activity端的Activity stop阶段
1、准备启动参数阶段
2、处理ActivityStack阶段
3、跨进程传递生命周期触发器
4、ClientTransaction触发执行阶段
5、Activity stop阶段
方法很多,具体细节可以按照上面的时序图结合代码去过一遍。
adb shell dumpsys activity activities | sed -En -e ‘/Stack #/p’ -e ‘/Running activities/,/Run #0/p’