前言
Android 8.0 / 8.1是目前 Android 最新的正式发行版智能手机操做系统,2017年3月21日 Google 为开发者推出了新的 Android O 首个开发者预览版,2017 Google I/O 开发者大会上发布了第二个Android O开发者预览。2017年8月22日,谷歌正式发布了Android 8.0的正式版,其正式名称为:Android Oreo(奥利奥)。2017年12月5日谷歌正式发布了Android 8.1的正式版。在最近的 Android 版本更新中,能够看得出来,Google 已经更加注重 Android 的流畅性和续航能力等性能,这个倾斜会让 Android 的用户体验变得愈来愈好。html

听说谷歌重写的Android的底层源码,我在查看进程时就发现了一些显著的不一样,固然我没有使用实机操做,不知道这个现象是否正常。如下为我平常使用的Sony Xperia Z5 Premium 搭载 Android 7.1.1 和AVD上的一个Android 8.0 的虚拟在adb shell中查看进程的不一样之处。java


能够看到AVD已经再也不显示 root system 等USER的进程了,表头也发生了变化,sh进程NAME值为sh,而非7.0的/system/bin/sh。linux
Android系统架构

Android 操做系统是一个软件组件的栈,在架构图中它大体能够分为五个部分和四个主要层。android
Linux内核
在全部层的最底下是 Linux - 包括大约115个补丁的 Linux 3.6。它提供了基本的系统功能,好比进程管理,内存管理,设备管理(如摄像头,键盘,显示器)。同时,内核处理全部 Linux 所擅长的工做,如网络和大量的设备驱动,从而避免兼容大量外围硬件接口带来的不便。git
程序库
在 Linux 内核层的上面是一系列程序库的集合,包括开源的 Web 浏览器引擎 Webkit ,知名的 libc 库,用于仓库存储和应用数据共享的 SQLite 数据库,用于播放、录制音视频的库,用于网络安全的 SSL 库等。web
Android程序库
这个类别包括了专门为 Android 开发的基于 Java 的程序库。这个类别程序库的示例包括应用程序框架库,如用户界面构建,图形绘制和数据库访问。一些 Android 开发者可用的 Android 核心程序库总结以下:算法
- android.app - 提供应用程序模型的访问,是全部 Android 应用程序的基石。
- android.content - 方便应用程序之间,应用程序组件之间的内容访问,发布,消息传递。
- android.database - 用于访问内容提供者发布的数据,包含 SQLite 数据库管理类。
- android.opengl - OpenGL ES 3D 图片渲染 API 的 Java 接口。
- android.os - 提供应用程序访问标注操做系统服务的能力,包括消息,系统服务和进程间通讯。
- android.text - 在设备显示上渲染和操做文本。
- android.view - 应用程序用户界面的基础构建块。
- android.widget - 丰富的预置用户界面组件集合,包括按钮,标签,列表,布局管理,单选按钮等。
- android.webkit - 一系列类的集合,容许为应用程序提供内建的 Web 浏览能力。
看过了 Android 运行层内的基于 Java 的核心程序库,是时候关注一下 Android 软件栈中的基于 C/C++ 的程序库。shell
Android运行时
这是架构中的第三部分,自下而上的第二层。这个部分提供名为 Dalvik 虚拟机的关键组件,相似于 Java 虚拟机,但专门为 Android 设计和优化。数据库
Dalvik 虚拟机使得能够在 Java 中使用 Linux 核心功能,如内存管理和多线程。Dalvik 虚拟机使得每个 Android 应用程序运行在本身独立的虚拟机进程。浏览器
Android 运行时同时提供一系列核心的库来为 Android 应用程序开发者使用标准的 Java 语言来编写 Android 应用程序。
应用框架
应用框架层以 Java 类的形式为应用程序提供许多高级的服务。应用程序开发者被容许在应用中使用这些服务。
- 活动管理者 - 控制应用程序生命周期和活动栈的全部方面。
- 内容提供者 - 容许应用程序之间发布和分享数据。
- 资源管理器 - 提供对非代码嵌入资源的访问,如字符串,颜色设置和用户界面布局。
- 通知管理器 - 容许应用程序显示对话框或者通知给用户。
- 视图系统 - 一个可扩展的视图集合,用于建立应用程序用户界面。
应用程序
顶层中有全部的 Android 应用程序。你写的应用程序也将被安装在这层。这些应用程序包括通信录,浏览器,游戏等。
Android进程
查看Android进程
Android是基于Linux的,可是没有terminal因此咱们查看Android进程须要使用adb中的adb shell进入手机,再使用ps指令来查看,如前言所示。
Android进程
当某个应用组件启动且该应用没有运行其余任何组件时,Android 系统会使用单个执行线程为应用启动新的 Linux 进程。
默认状况下,同一应用的全部组件均在相同的进程中运行,且大多数应用都不会改变这一点。 可是,若是您发现须要控制某个组件所属的进程,则可在清单文件中执行此操做。
若是内存不足,而其余为用户提供更紧急服务的进程又须要内存时,Android 可能会决定在某一时刻关闭某一进程。在被终止进程中运行的应用组件也会随之销毁。 当这些组件须要再次运行时,系统将为它们重启进程。
决定终止哪一个进程时,Android 系统将权衡它们对用户的相对重要程度。例如,相对于托管可见 Activity 的进程而言,它更有可能关闭托管屏幕上再也不可见的 Activity 的进程。 所以,是否终止某个进程的决定取决于该进程中所运行组件的状态。
进程生命周期
Android 系统将尽可能长时间地保持应用进程,但为了新建进程或运行更重要的进程,最终须要移除旧进程来回收内存。 为了肯定保留或终止哪些进程,系统会根据进程中正在运行的组件以及这些组件的状态,将每一个进程放入“重要性层次结构”中。 必要时,系统会首先消除重要性最低的进程,而后是重要性略逊的进程,依此类推,以回收系统资源。
Android系统共有五种等级的进程

重要性层次结构一共有 5 级。如下列表按照重要程度列出了各种进程(第一个进程最重要,将是最后一个被终止的进程):
- 前台进程
用户当前操做所必需的进程。若是一个进程知足如下任一条件,即视为前台进程:
一般,在任意给定时间前台进程都为数很少。只有在内存不足以支持它们同时继续运行这一万不得已的状况下,系统才会终止它们。 此时,设备每每已达到内存分页状态,所以须要终止一些前台进程来确保用户界面正常响应。
- 可见进程
没有任何前台组件、但仍会影响用户在屏幕上所见内容的进程。 若是一个进程知足如下任一条件,即视为可见进程:
- 托管不在前台、但仍对用户可见的
Activity
(已调用其 onPause()
方法)。例如,若是前台 Activity 启动了一个对话框,容许在其后显示上一 Activity,则有可能会发生这种状况。
- 托管绑定到可见(或前台)Activity 的
Service
。
可见进程被视为是极其重要的进程,除非为了维持全部前台进程同时运行而必须终止,不然系统不会终止这些进程。
- 服务进程
正在运行已使用 startService()
方法启动的服务且不属于上述两个更高类别进程的进程。尽管服务进程与用户所见内容没有直接关联,可是它们一般在执行一些用户关心的操做(例如,在后台播放音乐或从网络下载数据)。所以,除非内存不足以维持全部前台进程和可见进程同时运行,不然系统会让服务进程保持运行状态。
- 后台进程
包含目前对用户不可见的 Activity 的进程(已调用 Activity 的 onStop()
方法)。这些进程对用户体验没有直接影响,系统可能随时终止它们,以回收内存供前台进程、可见进程或服务进程使用。 一般会有不少后台进程在运行,所以它们会保存在 LRU (最近最少使用)列表中,以确保包含用户最近查看的 Activity 的进程最后一个被终止。若是某个 Activity 正确实现了生命周期方法,并保存了其当前状态,则终止其进程不会对用户体验产生明显影响,由于当用户导航回该 Activity 时,Activity 会恢复其全部可见状态。 有关保存和恢复状态的信息,请参阅 Activity文档。
- 空进程
不含任何活动应用组件的进程。保留这种进程的的惟一目的是用做缓存,以缩短下次在其中运行组件所需的启动时间。 为使整体系统资源在进程缓存和底层内核缓存之间保持平衡,系统每每会终止这些进程。
进程优先级的定义
OOM adjustments与 Process Importance决定了进程在调用中的优先级。
ADJ值定义在frameworks\base\services\core\java\com\android\server\am\ProcessList.java中
// OOM adjustments for processes in various states:
// Uninitialized value for any major or minor adj fields
static final int INVALID_ADJ = -10000;
// Adjustment used in certain places where we don't know it yet.
// (Generally this is something that is going to be cached, but we
// don't know the exact value in the cached range to assign yet.)
static final int UNKNOWN_ADJ = 1001;
// This is a process only hosting activities that are not visible,
// so it can be killed without any disruption.
static final int CACHED_APP_MAX_ADJ = 906;
static final int CACHED_APP_MIN_ADJ = 900;
// The B list of SERVICE_ADJ -- these are the old and decrepit
// services that aren't as shiny and interesting as the ones in the A list.
static final int SERVICE_B_ADJ = 800;
// This is the process of the previous application that the user was in.
// This process is kept above other things, because it is very common to
// switch back to the previous app. This is important both for recent
// task switch (toggling between the two top recent apps) as well as normal
// UI flow such as clicking on a URI in the e-mail app to view in the browser,
// and then pressing back to return to e-mail.
static final int PREVIOUS_APP_ADJ = 700;
// This is a process holding the home application -- we want to try
// avoiding killing it, even if it would normally be in the background,
// because the user interacts with it so much.
static final int HOME_APP_ADJ = 600;
// This is a process holding an application service -- killing it will not
// have much of an impact as far as the user is concerned.
static final int SERVICE_ADJ = 500;
// This is a process with a heavy-weight application. It is in the
// background, but we want to try to avoid killing it. Value set in
// system/rootdir/init.rc on startup.
static final int HEAVY_WEIGHT_APP_ADJ = 400;
// This is a process currently hosting a backup operation. Killing it
// is not entirely fatal but is generally a bad idea.
static final int BACKUP_APP_ADJ = 300;
// This is a process only hosting components that are perceptible to the
// user, and we really want to avoid killing them, but they are not
// immediately visible. An example is background music playback.
static final int PERCEPTIBLE_APP_ADJ = 200;
// This is a process only hosting activities that are visible to the
// user, so we'd prefer they don't disappear.
static final int VISIBLE_APP_ADJ = 100;
static final int VISIBLE_APP_LAYER_MAX = PERCEPTIBLE_APP_ADJ - VISIBLE_APP_ADJ - 1;
// This is the process running the current foreground app. We'd really
// rather not kill it!
static final int FOREGROUND_APP_ADJ = 0;
// This is a process that the system or a persistent process has bound to,
// and indicated it is important.
static final int PERSISTENT_SERVICE_ADJ = -700;
// This is a system persistent process, such as telephony. Definitely
// don't want to kill it, but doing so is not completely fatal.
static final int PERSISTENT_PROC_ADJ = -800;
// The system process runs at the default adjustment.
static final int SYSTEM_ADJ = -900;
// Special code for native processes that are not being managed by the system (so
// don't have an oom adj assigned by the system).
static final int NATIVE_ADJ = -1000;
ADJ值越小则优先度越高,例如INVALID和NATIVE的ADJ值在Android 8.0中为-10000和-1000,优先度最高,系统不会去关闭它。紧随其后的是SYSTEM,ADJ值为-900。
ADJ值 |
类型 |
-10000 |
INVALID 未定义 |
-1000 |
NATIVE 本机持有的特殊代码 |
-900 |
SYSTEM |
-800 |
PERSISTENT_PROC 系统持续进程(电话) |
-700 |
PERSISTENT_SERVICE 系统服务进程 |
0 |
FOREGROUND_APP 前台应用 |
100 |
VISIBLE_APP 可见应用 |
200 |
PERCEPTIBLE_APP 后台应用 |
300 |
BACKUP_APP 备份进程 |
400 |
HEAVY_WEIGHT_APP 重量级后台进程 |
500 |
SERVICE 服务进程 |
600 |
HOME_APP 主进程 |
700 |
PREVIOUS_APP 上一个进程 |
800 |
SERVICE_B 旧的服务进程B列表 |
900 |
CACHED_APP_MIN |
906 |
CACHED_APP_MAX |
1001 |
UNKNOWN |
99(PERCEPTIBLE_APP_ADJ - VISIBLE_APP_ADJ - 1) |
VISIBLE_APP_LAYER_MAX |
一 : 前台进程 (Active Process): oom_adj为0。
前台进程包括 : 1 : 活动 正在前台接收用户输入
2:活动、服务与广播接收器正在执行一个onReceive事件的处理函数
3: 服务正在运行 onStart、onCreate或onDestroy事件处理函数。
二 : 已启动服务的进程(Started Service Process) :oom_adj值为0,这类进程包含一个已启动的服务。 服务并不直接与用户输入交互,所以服务的优先级
低于可见活动的优先级,可是,已启动服务的进程任被认为是前台进程,只有在活动以及可见活动须要资源时,已启动服务的进程才会被杀死。
三 :可见进程 (Visible Process): oom_adj 为 100。活动是可见的,但并不在前台,或者不响应用户的输入。例如,活动被非全屏或者透明的活动所遮挡。
//如下为旧版本
四 :后台进程 (Backgroud Process): oom_adj 值为 2,这类进程不包含任何可见的活动与启动的服务。一般大量后台进程存在时,系统会采用(last-seen-first-kill)后见先杀的方式,释放资源为前台进程使用。
五 :主界面 (home process): oom_adj 为 4
六 :隐藏进程 (hidden process): oom_adj为 7
七 :内容提供者 (content provider):oom_adj 为 14
八 :空进程 (Empty process):oom_adj为 15
Process Importance定义在frameworks/base/core/java/android/app/ActivityManager.java类中:
/**
* Constant for {@link #importance}: This process is running the
* foreground UI; that is, it is the thing currently at the top of the screen
* that the user is interacting with.
*/
public static final int IMPORTANCE_FOREGROUND = 100;
/**
* Constant for {@link #importance}: This process is running a foreground
* service, for example to perform music playback even while the user is
* not immediately in the app. This generally indicates that the process
* is doing something the user actively cares about.
*/
public static final int IMPORTANCE_FOREGROUND_SERVICE = 125;
/**
* Constant for {@link #importance}: This process is running the foreground
* UI, but the device is asleep so it is not visible to the user. This means
* the user is not really aware of the process, because they can not see or
* interact with it, but it is quite important because it what they expect to
* return to once unlocking the device.
*/
public static final int IMPORTANCE_TOP_SLEEPING = 150;
/**
* Constant for {@link #importance}: This process is running something
* that is actively visible to the user, though not in the immediate
* foreground. This may be running a window that is behind the current
* foreground (so paused and with its state saved, not interacting with
* the user, but visible to them to some degree); it may also be running
* other services under the system's control that it inconsiders important.
*/
public static final int IMPORTANCE_VISIBLE = 200;
/**
* Constant for {@link #importance}: {@link #IMPORTANCE_PERCEPTIBLE} had this wrong value
* before {@link Build.VERSION_CODES#O}. Since the {@link Build.VERSION_CODES#O} SDK,
* the value of {@link #IMPORTANCE_PERCEPTIBLE} has been fixed.
*
* <p>The system will return this value instead of {@link #IMPORTANCE_PERCEPTIBLE}
* on Android versions below {@link Build.VERSION_CODES#O}.
*
* <p>On Android version {@link Build.VERSION_CODES#O} and later, this value will still be
* returned for apps with the target API level below {@link Build.VERSION_CODES#O}.
* For apps targeting version {@link Build.VERSION_CODES#O} and later,
* the correct value {@link #IMPORTANCE_PERCEPTIBLE} will be returned.
*/
public static final int IMPORTANCE_PERCEPTIBLE_PRE_26 = 130;
/**
* Constant for {@link #importance}: This process is not something the user
* is directly aware of, but is otherwise perceptible to them to some degree.
*/
public static final int IMPORTANCE_PERCEPTIBLE = 230;
/**
* Constant for {@link #importance}: {@link #IMPORTANCE_CANT_SAVE_STATE} had
* this wrong value
* before {@link Build.VERSION_CODES#O}. Since the {@link Build.VERSION_CODES#O} SDK,
* the value of {@link #IMPORTANCE_CANT_SAVE_STATE} has been fixed.
*
* <p>The system will return this value instead of {@link #IMPORTANCE_CANT_SAVE_STATE}
* on Android versions below {@link Build.VERSION_CODES#O}.
*
* <p>On Android version {@link Build.VERSION_CODES#O} after, this value will still be
* returned for apps with the target API level below {@link Build.VERSION_CODES#O}.
* For apps targeting version {@link Build.VERSION_CODES#O} and later,
* the correct value {@link #IMPORTANCE_CANT_SAVE_STATE} will be returned.
*
* @hide
*/
public static final int IMPORTANCE_CANT_SAVE_STATE_PRE_26 = 170;
/**
* Constant for {@link #importance}: This process is running an
* application that can not save its state, and thus can't be killed
* while in the background.
* @hide
*/
public static final int IMPORTANCE_CANT_SAVE_STATE= 270;
/**
* Constant for {@link #importance}: This process is contains services
* that should remain running. These are background services apps have
* started, not something the user is aware of, so they may be killed by
* the system relatively freely (though it is generally desired that they
* stay running as long as they want to).
*/
public static final int IMPORTANCE_SERVICE = 300;
/**
* Constant for {@link #importance}: This process process contains
* cached code that is expendable, not actively running any app components
* we care about.
*/
public static final int IMPORTANCE_CACHED = 400;
/**
* @deprecated Renamed to {@link #IMPORTANCE_CACHED}.
*/
public static final int IMPORTANCE_BACKGROUND = IMPORTANCE_CACHED;
/**
* Constant for {@link #importance}: This process is empty of any
* actively running code.
* @deprecated This value is no longer reported, use {@link #IMPORTANCE_CACHED} instead.
*/
@Deprecated
public static final int IMPORTANCE_EMPTY = 500;
/**
* Constant for {@link #importance}: This process does not exist.
*/
public static final int IMPORTANCE_GONE = 1000;
IMPORTANCE值也是越小优先度越高。
IMPORTANCE_FOREGROUND 意味着这个进程正在运行前台UI,也就是说,它是当前在屏幕顶部的东西,用户正在进行交互的而进程,即以前提到的前台进程。
IMPORTANCE_FOREGROUND_SERVICE前台服务,即便用户不是在应用中时也执行音乐播放,这通常表示该进程正在作用户积极关心的事情。
在这里咱们发现了一个Android 8.0不一样以往的地方新增了IMPORTANCE_CACHED = 400的定义,然后台进程IMPORTANCE_BACKGROUND值与其相同。
IMPORTANCE值 |
属性 |
100 |
FOREGROUND |
125 |
FOREGROUND_SERVICE |
130 |
PERCEPTIBLE_PRE_26 |
170 |
CANT_SAVE_STATE_PRE_26 |
150 |
TOP_SLEEPING |
200 |
VISIBLE |
230 |
PERCEPTIBLE |
270 |
CANT_SAVE_STATE |
300 |
SERVICE |
400 |
CACHED & BACKGROUND |
500 |
EMPTY |
1000 |
GONE |
进程回收机制
这里参考自穿裤衩闯天下 的文章《Android 守护进程的实现方式》
Android
的Low Memory Killer
基于Linux
的OOM
机制,在Linux
中,内存是以页面为单位分配的,当申请页面分配时若是内存不足会经过如下流程选择bad进程来杀掉从而释放内存:
alloc_pages -> out_of_memory() -> select_bad_process() -> badness()
在Low Memory Killer
中经过进程的oom_adj
与占用内存的大小决定要杀死的进程,oom_adj
越小越不容易被杀死;
Low Memory Killer Driver
在用户空间指定了一组内存临界值及与之一一对应的一组oom_adj
值,当系统剩余内存位于内存临界值中的一个范围内时,若是一个进程的oom_adj
值大于或等于这个临界值对应的oom_adj
值就会被杀掉。
下边是表示Process State
(即老版本里的OOM_ADJ
)数值对照表,数值越大,重要性越低,在新版SDK中已经在android
层去除了小于0的进程状态
// Path:SDK/sources/android-25/android/app/ActivityManager#RunningAppProcessInfo.java
// 进程不存在。
public static final int PROCESS_STATE_NONEXISTENT = -1;
// 进程是一个持久的系统进程,通常指当前 UI 进程
public static final int PROCESS_STATE_PERSISTENT = 0;
// 进程是一个持久的系统进程,正在作和 UI 相关的操做,但不直接显示
public static final int PROCESS_STATE_PERSISTENT_UI = 1;
// 进程正在托管当前的顶级活动。请注意,这涵盖了用户可见的全部活动。
public static final int PROCESS_STATE_TOP = 2;
// 进程因为系统绑定而托管前台服务。
public static final int PROCESS_STATE_BOUND_FOREGROUND_SERVICE = 3;
// 进程正在托管前台服务。
public static final int PROCESS_STATE_FOREGROUND_SERVICE = 4;
// 与{@link #PROCESS_STATE_TOP}相同,但设备处于睡眠状态。
public static final int PROCESS_STATE_TOP_SLEEPING = 5;
// 进程对用户很重要,是他们知道的东西
public static final int PROCESS_STATE_IMPORTANT_FOREGROUND = 6;
// 进程对用户很重要,但不是他们知道的
public static final int PROCESS_STATE_IMPORTANT_BACKGROUND = 7;
// 进程在后台运行备份/恢复操做
public static final int PROCESS_STATE_BACKUP = 8;
// 进程在后台,但咱们不能恢复它的状态,因此咱们想尽可能避免杀死它,否则这个而进程就丢了
public static final int PROCESS_STATE_HEAVY_WEIGHT = 9;
// 进程在后台运行一个服务,与oom_adj不一样,此级别用于正常运行在后台状态和执行操做状态。
public static final int PROCESS_STATE_SERVICE = 10;
// 进程在后台运行一个接收器,注意,从oom_adj接收器的角度来看,在较高的前台级运行,可是对于咱们的优先级,这不是必需的,而且将它们置于服务之下意味着当它们接收广播时,一些进程状态中的更少的改变。
public static final int PROCESS_STATE_RECEIVER = 11;
// 进程在后台,但主持家庭活动
public static final int PROCESS_STATE_HOME = 12;
// 进程在后台,但托管最后显示的活动
public static final int PROCESS_STATE_LAST_ACTIVITY = 13;
// 进程正在缓存以供之后使用,并包含活动
public static final int PROCESS_STATE_CACHED_ACTIVITY = 14;
// 进程正在缓存供之后使用,而且是包含活动的另外一个缓存进程的客户端
public static final int PROCESS_STATE_CACHED_ACTIVITY_CLIENT = 15;
// 进程正在缓存以供之后使用,而且为空
public static final int PROCESS_STATE_CACHED_EMPTY = 16;
在Android 8.0 中是这样的,增长了1七、18两个值四个STATE:PROCESS_STATE_CACHED_EMPTY、PROCESS_STATE_NONEXISTENT、MIN_PROCESS_STATE、MAX_PROCESS_STATE。
/** @hide Not a real process state. */
public static final int PROCESS_STATE_UNKNOWN = -1;
/** @hide Process is a persistent system process. */
public static final int PROCESS_STATE_PERSISTENT = 0;
/** @hide Process is a persistent system process and is doing UI. */
public static final int PROCESS_STATE_PERSISTENT_UI = 1;
/** @hide Process is hosting the current top activities. Note that this covers
* all activities that are visible to the user. */
public static final int PROCESS_STATE_TOP = 2;
/** @hide Process is hosting a foreground service due to a system binding. */
public static final int PROCESS_STATE_BOUND_FOREGROUND_SERVICE = 3;
/** @hide Process is hosting a foreground service. */
public static final int PROCESS_STATE_FOREGROUND_SERVICE = 4;
/** @hide Same as {@link #PROCESS_STATE_TOP} but while device is sleeping. */
public static final int PROCESS_STATE_TOP_SLEEPING = 5;
/** @hide Process is important to the user, and something they are aware of. */
public static final int PROCESS_STATE_IMPORTANT_FOREGROUND = 6;
/** @hide Process is important to the user, but not something they are aware of. */
public static final int PROCESS_STATE_IMPORTANT_BACKGROUND = 7;
/** @hide Process is in the background transient so we will try to keep running. */
public static final int PROCESS_STATE_TRANSIENT_BACKGROUND = 8;
/** @hide Process is in the background running a backup/restore operation. */
public static final int PROCESS_STATE_BACKUP = 9;
/** @hide Process is in the background, but it can't restore its state so we want
* to try to avoid killing it. */
public static final int PROCESS_STATE_HEAVY_WEIGHT = 10;
/** @hide Process is in the background running a service. Unlike oom_adj, this level
* is used for both the normal running in background state and the executing
* operations state. */
public static final int PROCESS_STATE_SERVICE = 11;
/** @hide Process is in the background running a receiver. Note that from the
* perspective of oom_adj receivers run at a higher foreground level, but for our
* prioritization here that is not necessary and putting them below services means
* many fewer changes in some process states as they receive broadcasts. */
public static final int PROCESS_STATE_RECEIVER = 12;
/** @hide Process is in the background but hosts the home activity. */
public static final int PROCESS_STATE_HOME = 13;
/** @hide Process is in the background but hosts the last shown activity. */
public static final int PROCESS_STATE_LAST_ACTIVITY = 14;
/** @hide Process is being cached for later use and contains activities. */
public static final int PROCESS_STATE_CACHED_ACTIVITY = 15;
/** @hide Process is being cached for later use and is a client of another cached
* process that contains activities. */
public static final int PROCESS_STATE_CACHED_ACTIVITY_CLIENT = 16;
/** @hide Process is being cached for later use and is empty. */
public static final int PROCESS_STATE_CACHED_EMPTY = 17;
/** @hide Process does not exist. */
public static final int PROCESS_STATE_NONEXISTENT = 18;
/** @hide The lowest process state number */
public static final int MIN_PROCESS_STATE = PROCESS_STATE_PERSISTENT;
/** @hide The highest process state number */
public static final int MAX_PROCESS_STATE = PROCESS_STATE_NONEXISTENT;
Process State
(即老版本的OOM_ADJ
)与Process Importance
对应关系,这个方法也是在ActivityManager.java
类中,有了这个关系,就知道能够知道咱们的应用处于哪一个级别,对于咱们后边优化有个很好地参考
/**
* Path:SDK/sources/android-25/android/app/ActivityManager#RunningAppProcessInfo.java
* 这里在Android8.0中没有发生变化
* 经过这个方法,将Linux底层的 OOM_ADJ级别码和 android 层面的进程重要程度联系了起来
*/
public static int procStateToImportance(int procState) {
if (procState == PROCESS_STATE_NONEXISTENT) {
return IMPORTANCE_GONE;
} else if (procState >= PROCESS_STATE_HOME) {
return IMPORTANCE_BACKGROUND;
} else if (procState >= PROCESS_STATE_SERVICE) {
return IMPORTANCE_SERVICE;
} else if (procState > PROCESS_STATE_HEAVY_WEIGHT) {
return IMPORTANCE_CANT_SAVE_STATE;
} else if (procState >= PROCESS_STATE_IMPORTANT_BACKGROUND) {
return IMPORTANCE_PERCEPTIBLE;
} else if (procState >= PROCESS_STATE_IMPORTANT_FOREGROUND) {
return IMPORTANCE_VISIBLE;
} else if (procState >= PROCESS_STATE_TOP_SLEEPING) {
return IMPORTANCE_TOP_SLEEPING;
} else if (procState >= PROCESS_STATE_FOREGROUND_SERVICE) {
return IMPORTANCE_FOREGROUND_SERVICE;
} else {
return IMPORTANCE_FOREGROUND;
}
}
通常状况下,设备端进程被干掉有一下几种状况
进程结束场景 |
结束方式 |
影响范围 |
Android 系统自身内存回收机制 |
Low Memory Killer |
Process State 数值从大到小 |
第三方管理程序清理进程 无 Root 权限 |
killBackgroundProcess |
Process State 数值大于6进程 |
第三方管理程序清理进程 有 Root 权限 |
force-stop or Kill |
除当前前台进程外全部非系统进程 |
Rom 清除进程(用户手动清理) |
force-stop or Kill |
全部非系统进程 |
用户手动强制结束 |
force-stop |
第三方应用以及非 System 进程 |
Android进程状态转换
这里参考了一篇CSDN的文章

Android应用进程启动
当咱们在Launcher桌面上点击一个应用的图标时,固然Launcher启动以后,已经把桌面上每一个图标对应的信息都封装好了,用户点击以后,Launcher进程就会经过Binder进程间通讯机制调用startActivity的方式去打开目标进程的入口Activity,指令传达到ActivityManagerService当中时,AMS会去检测当有的应用进程是否已经启动,若是没有启动,那么就会先将当前的目标进程启动起来,启动目标进程是经过调用startProcessLocked方法来完成的。
方法的实如今ActivityManagerService类中,目录路径为frameworks\base\services\core\java\com\android\server\am\ActivityManagerService.java,startProcessLocked方法的源码以下:
private final void startProcessLocked(ProcessRecord app,
String hostingType, String hostingNameStr) {
startProcessLocked(app, hostingType, hostingNameStr, null /* abiOverride */,
null /* entryPoint */, null /* entryPointArgs */);
}
该方法就是直接调用另外一个重载方法来实如今,该重载方法的源码以下:
private final void startProcessLocked(ProcessRecord app, String hostingType,
String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs) {
long startTime = SystemClock.elapsedRealtime();
if (app.pid > 0 && app.pid != MY_PID) {
checkTime(startTime, "startProcess: removing from pids map");
synchronized (mPidsSelfLocked) {
mPidsSelfLocked.remove(app.pid);
mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
}
checkTime(startTime, "startProcess: done removing from pids map");
app.setPid(0);
}
if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG_PROCESSES,
"startProcessLocked removing on hold: " + app);
mProcessesOnHold.remove(app);
checkTime(startTime, "startProcess: starting to update cpu stats");
updateCpuStats();
checkTime(startTime, "startProcess: done updating cpu stats");
try {
try {
final int userId = UserHandle.getUserId(app.uid);
AppGlobals.getPackageManager().checkPackageStartable(app.info.packageName, userId);
} catch (RemoteException e) {
throw e.rethrowAsRuntimeException();
}
int uid = app.uid;
int[] gids = null;
int mountExternal = Zygote.MOUNT_EXTERNAL_NONE;
if (!app.isolated) {
int[] permGids = null;
try {
checkTime(startTime, "startProcess: getting gids from package manager");
final IPackageManager pm = AppGlobals.getPackageManager();
permGids = pm.getPackageGids(app.info.packageName,
MATCH_DEBUG_TRIAGED_MISSING, app.userId);
StorageManagerInternal storageManagerInternal = LocalServices.getService(
StorageManagerInternal.class);
mountExternal = storageManagerInternal.getExternalStorageMountMode(uid,
app.info.packageName);
} catch (RemoteException e) {
throw e.rethrowAsRuntimeException();
}
/*
* Add shared application and profile GIDs so applications can share some
* resources like shared libraries and access user-wide resources
*/
if (ArrayUtils.isEmpty(permGids)) {
gids = new int[3];
} else {
gids = new int[permGids.length + 3];
System.arraycopy(permGids, 0, gids, 3, permGids.length);
}
gids[0] = UserHandle.getSharedAppGid(UserHandle.getAppId(uid));
gids[1] = UserHandle.getCacheAppGid(UserHandle.getAppId(uid));
gids[2] = UserHandle.getUserGid(UserHandle.getUserId(uid));
}
checkTime(startTime, "startProcess: building args");
if (mFactoryTest != FactoryTest.FACTORY_TEST_OFF) {
if (mFactoryTest == FactoryTest.FACTORY_TEST_LOW_LEVEL
&& mTopComponent != null
&& app.processName.equals(mTopComponent.getPackageName())) {
uid = 0;
}
if (mFactoryTest == FactoryTest.FACTORY_TEST_HIGH_LEVEL
&& (app.info.flags & ApplicationInfo.FLAG_FACTORY_TEST) != 0) {
uid = 0;
}
}
int debugFlags = 0;
if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
debugFlags |= Zygote.DEBUG_ENABLE_JDWP;
debugFlags |= Zygote.DEBUG_JAVA_DEBUGGABLE;
// Also turn on CheckJNI for debuggable apps. It's quite
// awkward to turn on otherwise.
debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;
}
// Run the app in safe mode if its manifest requests so or the
// system is booted in safe mode.
if ((app.info.flags & ApplicationInfo.FLAG_VM_SAFE_MODE) != 0 ||
mSafeMode == true) {
debugFlags |= Zygote.DEBUG_ENABLE_SAFEMODE;
}
if ("1".equals(SystemProperties.get("debug.checkjni"))) {
debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;
}
String genDebugInfoProperty = SystemProperties.get("debug.generate-debug-info");
if ("true".equals(genDebugInfoProperty)) {
debugFlags |= Zygote.DEBUG_GENERATE_DEBUG_INFO;
}
if ("1".equals(SystemProperties.get("debug.jni.logging"))) {
debugFlags |= Zygote.DEBUG_ENABLE_JNI_LOGGING;
}
if ("1".equals(SystemProperties.get("debug.assert"))) {
debugFlags |= Zygote.DEBUG_ENABLE_ASSERT;
}
if (mNativeDebuggingApp != null && mNativeDebuggingApp.equals(app.processName)) {
// Enable all debug flags required by the native debugger.
debugFlags |= Zygote.DEBUG_ALWAYS_JIT; // Don't interpret anything
debugFlags |= Zygote.DEBUG_GENERATE_DEBUG_INFO; // Generate debug info
debugFlags |= Zygote.DEBUG_NATIVE_DEBUGGABLE; // Disbale optimizations
mNativeDebuggingApp = null;
}
String invokeWith = null;
if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
// Debuggable apps may include a wrapper script with their library directory.
String wrapperFileName = app.info.nativeLibraryDir + "/wrap.sh";
StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
try {
if (new File(wrapperFileName).exists()) {
invokeWith = "/system/bin/logwrapper " + wrapperFileName;
}
} finally {
StrictMode.setThreadPolicy(oldPolicy);
}
}
String requiredAbi = (abiOverride != null) ? abiOverride : app.info.primaryCpuAbi;
if (requiredAbi == null) {
requiredAbi = Build.SUPPORTED_ABIS[0];
}
String instructionSet = null;
if (app.info.primaryCpuAbi != null) {
instructionSet = VMRuntime.getInstructionSet(app.info.primaryCpuAbi);
}
app.gids = gids;
app.requiredAbi = requiredAbi;
app.instructionSet = instructionSet;
// the per-user SELinux context must be set
if (TextUtils.isEmpty(app.info.seInfoUser)) {
Slog.wtf(TAG, "SELinux tag not defined",
new IllegalStateException("SELinux tag not defined for "
+ app.info.packageName + " (uid " + app.uid + ")"));
}
final String seInfo = app.info.seInfo
+ (TextUtils.isEmpty(app.info.seInfoUser) ? "" : app.info.seInfoUser);
// Start the process. It will either succeed and return a result containing
// the PID of the new process, or else throw a RuntimeException.
boolean isActivityProcess = (entryPoint == null);
if (entryPoint == null) entryPoint = "android.app.ActivityThread";
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "Start proc: " +
app.processName);
checkTime(startTime, "startProcess: asking zygote to start proc");
ProcessStartResult startResult;
if (hostingType.equals("webview_service")) {
startResult = startWebView(entryPoint,
app.processName, uid, uid, gids, debugFlags, mountExternal,
app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
app.info.dataDir, null, entryPointArgs);
} else {
startResult = Process.start(entryPoint,
app.processName, uid, uid, gids, debugFlags, mountExternal,
app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
app.info.dataDir, invokeWith, entryPointArgs);
}
checkTime(startTime, "startProcess: returned from zygote!");
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
mBatteryStatsService.noteProcessStart(app.processName, app.info.uid);
checkTime(startTime, "startProcess: done updating battery stats");
EventLog.writeEvent(EventLogTags.AM_PROC_START,
UserHandle.getUserId(uid), startResult.pid, uid,
app.processName, hostingType,
hostingNameStr != null ? hostingNameStr : "");
try {
AppGlobals.getPackageManager().logAppProcessStartIfNeeded(app.processName, app.uid,
seInfo, app.info.sourceDir, startResult.pid);
} catch (RemoteException ex) {
// Ignore
}
if (app.persistent) {
Watchdog.getInstance().processStarted(app.processName, startResult.pid);
}
checkTime(startTime, "startProcess: building log message");
StringBuilder buf = mStringBuilder;
buf.setLength(0);
buf.append("Start proc ");
buf.append(startResult.pid);
buf.append(':');
buf.append(app.processName);
buf.append('/');
UserHandle.formatUid(buf, uid);
if (!isActivityProcess) {
buf.append(" [");
buf.append(entryPoint);
buf.append("]");
}
buf.append(" for ");
buf.append(hostingType);
if (hostingNameStr != null) {
buf.append(" ");
buf.append(hostingNameStr);
}
Slog.i(TAG, buf.toString());
app.setPid(startResult.pid);
app.usingWrapper = startResult.usingWrapper;
app.removed = false;
app.killed = false;
app.killedByAm = false;
checkTime(startTime, "startProcess: starting to update pids map");
ProcessRecord oldApp;
synchronized (mPidsSelfLocked) {
oldApp = mPidsSelfLocked.get(startResult.pid);
}
// If there is already an app occupying that pid that hasn't been cleaned up
if (oldApp != null && !app.isolated) {
// Clean up anything relating to this pid first
Slog.w(TAG, "Reusing pid " + startResult.pid
+ " while app is still mapped to it");
cleanUpApplicationRecordLocked(oldApp, false, false, -1,
true /*replacingPid*/);
}
synchronized (mPidsSelfLocked) {
this.mPidsSelfLocked.put(startResult.pid, app);
if (isActivityProcess) {
Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
msg.obj = app;
mHandler.sendMessageDelayed(msg, startResult.usingWrapper
? PROC_START_TIMEOUT_WITH_WRAPPER : PROC_START_TIMEOUT);
}
}
checkTime(startTime, "startProcess: done updating pids map");
} catch (RuntimeException e) {
Slog.e(TAG, "Failure starting process " + app.processName, e);
// Something went very wrong while trying to start this process; one
// common case is when the package is frozen due to an active
// upgrade. To recover, clean up any active bookkeeping related to
// starting this process. (We already invoked this method once when
// the package was initially frozen through KILL_APPLICATION_MSG, so
// it doesn't hurt to use it again.)
forceStopPackageLocked(app.info.packageName, UserHandle.getAppId(app.uid), false,
false, true, false, false, UserHandle.getUserId(app.userId), "start failure");
}
}
该方法中int uid = app.uid能够获取到目标进程的uid,uid是标识目标进程身份的一个整数,它最原始的分配是在应用进程安装时,由PackageManagerService分配好
关于Android进程模型
在安装Android应用程序的时候,Android会为每一个程序分配一个Linux用户id,并设置相应的权限,这样其它应用程序就不能访问此应用程序所拥有的数据和资源了。
默认状况下,每一个apk运行在它本身的Linux进程中。当须要执行应用程序中的代码时,Android会启动一个jvm,即一个新的进程来执行,所以不一样的apk运行在相互隔离的环境中。
同时,开发者能够给两个应用程序分配相同的linux用户id,这样他们就能访问对方所拥有的资源。为了保留系统资源,拥有相同用户id的应用程序能够运行在同一个进程中,共享同一个jvm。
课堂演示



众所周知,Linux中的全部进程都是有init进程建立并运行的。首先Linux内核启动,而后在用户空间中启动init进程,再启动其余系统进程。在系统启动完成完成后,init将变为守护进程监视系统其余进程。Android是基于Linux的操做系统,因此init也是Android系统中用户空间的第一个进程,它的进程号是1。下面先简单的看一下init进程的启动过程。




Android 的线程调度
Android 进程生命周期与ADJ
Android 开发者应该都知道在系统中进程重要性的划分:
- 前台进程(Foreground process)
- 可见进程(Visible process)
- 服务进程(Service process)
- 后台进程(Background process)
- 空进程(Empty process)
相信你们都很清楚,这里就不作过多的介绍了,不过对于进程重要性是经过哪些操做发生变动的,以及和咱们前面讲的 Linux 进程分组又是怎么关联和映射上的,是下面要讲述的重点。
Android 进程优先级的相关概念
oom_score_adj
级别
对于每个运行中的进程,Linux 内核都经过 proc 文件系统暴露 /proc/[pid]/oom_score_adj
这样一个文件来容许其余程序修改指定进程的优先级,这个文件容许的值的范围是:-1000 ~ +1001之间。值越小,表示进程越重要。当内存很是紧张时,系统便会遍历全部进程,以肯定哪一个进程须要被杀死以回收内存,此时便会读取 oom_score_adj
这个文件的值。
PS:在Linux 2.6.36以前的版本中,Linux 提供调整优先级的文件是
/proc/[pid]/oom_adj
。这个文件容许的值的范围是-17 ~ +15之间。数值越小表示进程越重要。 这个文件在新版的 Linux 中已经废弃。但你仍然可使用这个文件,当你修改这个文件的时候,内核会直接进行换算,将结果反映到
oom_score_adj
这个文件上。
Android早期版本的实现中也是依赖
oom_adj
这个文件。可是在新版本中,已经切换到使用
oom_score_adj
这个文件。
为了便于管理,ProcessList.java中预约义了 oom_score_adj
的可能取值,这里的预约义值也是对应用进程的一种分类。

Lowmemorykiller 根据当前可用内存状况来进行进程释放,总设计了6个级别,即上表中“解释列”加粗的行,即 Lowmemorykiller 的杀进程的6档,以下:
CACHED_APP_MAX_ADJ
CACHED_APP_MIN_ADJ
BACKUP_APP_ADJ
PERCEPTIBLE_APP_ADJ
VISIBLE_APP_ADJ
FOREGROUND_APP_ADJ
系统内存从很宽裕到不足,Lowmemorykiller 也会相应地从 CACHED_APP_MAX_ADJ
(第1档)开始杀进程,若是内存还不足,那么会杀 CACHED_APP_MIN_ADJ
(第2档),不断深刻,直到知足内存阈值条件。
ProcessRecord中下面这些属性反应了 oom_score_adj
的值:
int maxAdj; // Maximum OOM adjustment for this process int curRawAdj; // Current OOM unlimited adjustment for this process int setRawAdj; // Last set OOM unlimited adjustment for this process int curAdj; // Current OOM adjustment for this process int setAdj; // Last set OOM adjustment for this process int verifiedAdj; // The last adjustment that was verified as actually being set
Process State
对应的在 ActivityManager 重定义了 process_state 级别的划分,Android 系统会在修改进程状态的同时更新 oom_score_adj
的分级:

在 ProcessRecord 中,记录了和进程状态相关的属性:
int curProcState = PROCESS_STATE_NONEXISTENT; // Currently computed process state int repProcState = PROCESS_STATE_NONEXISTENT; // Last reported process state int setProcState = PROCESS_STATE_NONEXISTENT; // Last set process state in process tracker int pssProcState = PROCESS_STATE_NONEXISTENT; // Currently requesting pss for
Schedule Group
对应到底层进程分组,除了上面提到的 Process.java
定义的不一样线程组的定义,同时还为 Activity manager
定义了一套相似的调度分组,和以前的线程分组定义也存在对应关系:
// Activity manager's version of Process.THREAD_GROUP_BG_NONINTERACTIVE static final int SCHED_GROUP_BACKGROUND = 0; // Activity manager's version of Process.THREAD_GROUP_DEFAULT static final int SCHED_GROUP_DEFAULT = 1; // Activity manager's version of Process.THREAD_GROUP_TOP_APP static final int SCHED_GROUP_TOP_APP = 2; // Activity manager's version of Process.THREAD_GROUP_TOP_APP // Disambiguate between actual top app and processes bound to the top app static final int SCHED_GROUP_TOP_APP_BOUND = 3;
在 ProcessRecord 中,也记录了和调度组相关的属性:
int curSchedGroup; // Currently desired scheduling class int setSchedGroup; // Last set to background scheduling class
Android 进程优先级的变化
咱们知道影响 Android 应用进程优先级变化的是根据 Android
应用组件的生命周期变化相关。Android进程调度之adj算法 里面罗列了全部会触发进程状态发生变化的事件,主要包括:
Actvity
- ActivityStackSupervisor.realStartActivityLocked: 启动Activity
- ActivityStack.resumeTopActivityInnerLocked: 恢复栈顶Activity
- ActivityStack.finishCurrentActivityLocked: 结束当前Activity
- ActivityStack.destroyActivityLocked: 摧毁当前Activity
Service
位于ActiveServices.java
- realStartServiceLocked: 启动服务
- bindServiceLocked: 绑定服务(只更新当前app)
- unbindServiceLocked: 解绑服务 (只更新当前app)
- bringDownServiceLocked: 结束服务 (只更新当前app)
- sendServiceArgsLocked: 在bringup或则cleanup服务过程调用 (只更新当前app)
broadcast
- BQ.processNextBroadcast: 处理下一个广播
- BQ.processCurBroadcastLocked: 处理当前广播
- BQ.deliverToRegisteredReceiverLocked: 分发已注册的广播 (只更新当前app)
ContentProvider
- AMS.removeContentProvider: 移除provider
- AMS.publishContentProviders: 发布provider (只更新当前app)
- AMS.getContentProviderImpl: 获取provider (只更新当前app)
Process
位于 ActivityManagerService.java
- setSystemProcess: 建立并设置系统进程
- addAppLocked: 建立persistent进程
- attachApplicationLocked: 进程建立后attach到system_server的过程;
- trimApplications: 清除没有使用app
- appDiedLocked: 进程死亡
- killAllBackgroundProcesses: 杀死全部后台进程.即(ADJ>9或removed=true的普通进程)
- killPackageProcessesLocked: 以包名的形式 杀掉相关进程;
这些事件都会直接或间接调用到 ActivityManagerService.java
中的 updateOomAdjLocked
方法来更新进程的优先级,updateOomAdjLocked
先经过 computeOomAdjLocked
方法负责计算进程的优先级,再经过调用 applyOomAdjLocked
应用进程的优先级。
computeOomAdjLocked
computeOomAdjLocked
方法负责计算进程的优先级,总计约700行,执行流程比较清晰,步骤以下,因为代码有点多这里就不贴了,想仔细研究的能够比着系统源码看: