Android ActivityManagerService 启动流程总结

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/michael_yt/article/details/79322483

ActivityManagerService(AMS)是Android中核心的服务之一,主要负责系统中四大组件的启动、切换、调度及应用程序的管理和调度等工作。

AMS启动整体流程图

这里写图片描述
从上图可以看出,经过的类不是很多,但是每个方法中的细分支很多,这我就不贴代码了,详细的逻辑请见源码,这个只是做个大概的总结,流程中的部分分支和作用请见图中的文字说明

下面再说说两个关于内存管理的方法:

ActivityManagerService.updateLruProcessLocked

调度优先级:就是操作系统分配CPU资源给进程时,需要参考的一个重要指标。
调度策略:用于描述操作系统的调度模块,分配CPU资源给应用进程时,所遵循的规则。
oom_adj:当系统出现内存不足的情况时,内核可以根据进程的oom_adj值,来选择杀死一些进程,以回收内存。
Low Memory Killer(LMK)机制:LMK的配置文件中,预先定义了不同的内存阈值及对应的oom_adj。当LMK监控到系统内存下降到某个阈值时,就会kill掉当前系统内,oom_adj超过该阈值预定义oom_adj的所有进程。
重点内容
1. 是否需要调整进程在LRU表中的位置,LRU特意定义了两个索引mLruProcessServiceStart和mLruProcessActivityStart。包含Activity的进程,将插入到mLruProcessActivityStart之后的位置; 不包含Activity,但包含Service的进程,将插入到mLruProcessServiceStart之后,目前的流程并没有判断进程中是否含有Service,整体来讲,后运行的进程,将插入到先运行的进程的后面,即LRU表的前面保存的是老旧的进程,后面保存的是用户使用的较新的进程这里写图片描述
2. 在更新位置之前,先移除LRU中旧有的信息,并更新两个索引mLruProcessServiceStart或mLruProcessActivityStart 的值
3. 更新含有activity的进程,将运行在activity的进程直接插到最后,将本进程没有但客户端含有activity的进程插入到导数第二个,为了公平不同用户的进程位置会交换一下。(相同用户的多个进程连续排列的话)
4. 更新service进程,理论上是直接插入到mLruProcessActivityStart 即可,但是当前代码中hasService一直为false,所以并没有使用
5. 更新其它进程,一般都放在mLruProcessServiceStart,但是如果该进程含有客户端,那么当前进程就需要放在客户端之前,此时,若该进程绑定了仅含有Service或Provider的进程,这些进程将被插入到该进程的前面
6. 更新仅含有后台Service或ContentProvider的进程,通过updateLruProcessInternalLocked 更新,一般不会降低他们的重要性

ActivityManagerService.updateOomAdjLocked

  1. 在ProcessList.java中定义了很多进程在不同场景下oom_adj的值
  2. 通过逆序处理LRU中的进程,通过computeOomAdjLocked方法计算出每个进程oom_adj值,通过值的判断通过LMK来kill掉相关进程
  3. 通过进程优先级回收进程内存,不kill内存,对于重要性大于home的进程而言,重要性越大,内存的回收等级越低,对于重要性小于home的进程而言,重要性越大,内存的回收等级越高(需要组件自己实现onTrimMemory方法,大部分都没有实现,所以点几乎没作用)

computeOomAdjLocked的oom_adjzhi值的计算过程:

其实该函数的原理还是依据进程中运行的组件以及进程的种类,来计算相应的oom_adj。

  1. 包含前台Activity的进程、运行测试类的进程、处理广播的进程及包含正在运行服务的进程,其oom_adj均被赋值为FOREGROUND_APP_ADJ,即从LMK的角度来看,它们的重要性是一致的。 但这些进程的procState不同,于是从AMS主动回收内存的角度来看,它们的重要性不同。
  2. 处理包含Activity的进程时,进程最终的oom_adj将由其中最要的Activity决定。 即进程中存在可见Activity时,进程的oom_adj就为VISIBLE_APP_ADJ; 否则,若进程中存在处于PAUSING、PAUSED或STOPPING状态的Activity时,进程的oom_adj就为PERCEPTIBLE_APP_ADJ
  3. 当进程中含有Unbounded Service时,如果进程之前没有启动过UI,且Unbounded Service存活的时间没有超时, 进程的oom_ad才能被调整为SERVICE_ADJ;否则进程的oom_adj仍然是UNKNOW_ADJ或其它大于500的值。
  4. 处理Bounded Service时,整个计算的复杂度就飙升了,它将考虑到Bound时使用的flag及客户端的情况,综合调整进程的oom_adj。
  5. 处理含有ContentProvider的进程时,相对比较简单。基本上与处理含有Unbounded Service的进程一致,只是最后增加了一些特殊情况的处理

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的接口
5. 从这里我们可以看出应用进程通过binder的方式和systemserver进程进行通信

ApplicationThread相关类图关系

这里写图片描述
原图来自这里
如上图所示

  1. ActivityThread作为应用进程的主线程代表,在其中持有ApplicationThread
  2. ApplicationThread继承ApplicationThreadNative(ATN),当AMS与应用进程通信时,ApplicationThread将作为Binder通信的服务端。
  3. ATN继承自Binder并实现了IApplicationThread接口,即ATN将作为Binder通信的服务端为用户提供支持
  4. ApplicationThreadProxy实现了IApplicationThread接口,所以它将作为客户端使用的服务端代理
  5. AMS与应用进程通信时,通过ApplicationThreadNative获取应用进程对应的ApplicationThreadProxy对象,通过ApplicationThreadProxy对象,将调用信息通过Binder传递到ActivityThread中的ApplicationThread
  6. 从这里我们可以出systemserver通过binder的方式和应用程序进行通信

Binder使用

Native层Binder使用

这里写图片描述
原图来自这里

Framework层Binder使用

这里写图片描述
原图来自这里

Native层和Framework的区别就是,native是直接使用binder去跨进程通信,Framework层则在java层封装了一个service和一个service的代理类

AIDL的使用

这里写图片描述
原图来自这里

AIDL其实也是通过Framework层的binder框架实现的,只不过我们只需要定义好IRemoteService.aidl这个文件就好了,编译工具会自动帮我们生成java端可以调用的service和service的代理类,然后写个service使用这些对象就可以了

参考链接:
http://gityuan.com/2015/11/22/binder-use/
http://blog.csdn.net/gaugamela/article/details/53067769

猜你喜欢

转载自blog.csdn.net/michael_yt/article/details/79322483