本文基于Android 11.0源码分析
1.初步了解AMS的进程管理
1.1 Linux进程调度优先级和调度策略
调度优先级和调度策略是操作系统中一个很重要的概念。简而言之,它是系统中CPU资源的管理和控制手段。如何理解?此处进行简单介绍。读者可自行阅读操作系统方面的书籍以加深理解。
-
相对于在OS上运行的应用进程个数来说,CPU的资源非常有限。
-
调度优先级是OS分配CPU资源给应用进程时(即调度应用进程运行)需要参考的一个指标。一般而言,优先级高的进程将更有机会得到CPU资源。
调度策略用于描述OS调度模块分配CPU给应用进程所遵循的规则,即当将CPU控制权交给调度模块时,系统如何选择下一个要运行的进程。此处不能仅考虑各进程的调度优先级,因为存在多个进程具有相同调度优先级的情况。在这种情况下,一个需要考虑的重要因素是,每个进程所分配的时间片及它们的使用情况。
可简单认为,调度优先级及调度策略二者一起影响了系统分配CPU资源给应用进程。注意,此处的措词为“影响”,而非“控制”。因为对于用户空间可以调用的API来说,如果二者能控制CPU资源分配,那么该系统的安全性会大打折扣。
(1)setpriority
Linux提供了两个API用于设置调度优先级及调度策略。先来看设置调度优先级的函数setpriority,其原型如下:
int setpriority(int which, int who, int prio);
其中:
-
which和who参数联合使用。
-
当which为PRIO_PROGRESS时,who代表一个进程;
-
当which为PRIO_PGROUP时,who代表一个进程组;
-
当which为PRIO_USER时,who代表一个uid。
-
-
第三个参数prio用于设置应用进程的nicer值,可取范围从-20到19。Linux kernel用nicer值来描述进程的调度优先级,该值越大,表明该进程越优(nice),其被调度运行的几率越低。
(2)sched_setscheduler
下面来看设置调度策略的函数sched_setscheduler,其原型如下:
int sched_setscheduler(pid_t pid, int policy, conststruct sched_param *param);
其中:
-
第一个参数为进程id。
-
第二个参数为调度策略。目前Android支持四种调度策略:
-
SCHED_OTHER,标准round-robin分时共享策略(也就是默认的策略);
-
SCHED_BATCH,针对具有batch风格(批处理)进程的调度策略;
-
SCHED_IDLE,针对优先级非常低的适合在后台运行的进程。除此之外,Linux还支持实时(Real-time)调度策略,包括SCHED_FIFO,先入先出调度策略;
-
SCHED_RR,round-robin调度策略,也就是循环调度。这些策略的定义值在Process.java,下面的文章有介绍这个类。
-
-
param参数中最重要的是该结构体中的sched_priority变量。针对Android中的四种非实时调度策略,该值必须为NULL。
以上介绍了调度优先级和调度策略的概念。建议读者做个小实验来测试调动优先级及调动策略的作用,步骤如下:
-
挂载SD卡到PC机并往向其中复制一些媒体文件,然后重新挂载SD卡到手机。该操作就能触发MediaScanner扫描新增的这些媒体文件。
-
利用top命令查看CPU使用率,会发现进程com.process.media(即MediaScanner所在的进程)占用CPU较高(可达70%以上),原因是该进程会扫描媒体文件,该工作将利用较多的CPU资源。
-
此时,如果启动另一个进程,然后做一些操作,会发现MediaScanner所在进程的CPU利用率会降下来(例如下降到30%~40%),这表明系统将CPU资源更多地分给了用户正在操作的这个进程。
出现这种现象的原因是,MediaScannerSerivce的扫描线程将调度优先级设置为11,而默认的调度优先级为0。 相比而言,MediaScannerService优先级真的很高。
1.2 关于Linux进程oom_adj的介绍
从Linux kernel 2.6.11开始,内核提供了进程的OOM控制机制,目的是当系统出现内存不足(out of memory,简称OOM)的情况时,Kernel可根据进程的oom_adj来选择并杀死一些进程,以回收内存。简而言之,oom_adj可标示Linux进程内存资源的优先级,其可取范围从-16到15,另外有一个特殊值-17用于禁止系统在OOM情况下杀死该进程。和nicer值一样,oom_adj的值越高,那么在OOM情况下,该进程越有可能被杀掉。每个进程的oom_adj初值为0。
Linux没有提供单独的API用于设置进程的oom_adj。目前的做法就是向/proc/进程id/oom_adj文件中写入对应的oom_adj值,通过这种方式就能调节进程的oom_adj了。
另外,有必要简单介绍一下Android为Linux Kernel新增的lowmemorykiller(以后简称LMK)模块的工作方式:LMK的职责是根据当前内存大小去杀死对应oom_adj及以上的进程以回收内存。这里有两个关键参数:为LMK设置不同的内存阈值及oom_adj,它们分别由/sys/module/lowmemorykiller/parameters/minfree和/sys/module/lowmemorykiller/parameters/adj控制。
(1)注意:这两个参数的典型设置为:
-
minfree:2048,3072,4096,6144,7168,8192 用于描述不同级别的内存阈值,单位为KB。
-
adj:0,1,2,4,7,15 用于描述对应内存阈值的oom_adj值。
表示当剩余内存为2048KB时,LMK将杀死oom_adj大于等于0的进程。网络上有一些关于Android手机内存优化的方法,其中一种就利用了LMK的工作原理。
(2)提示
lowmemorykiller的代码在kernel/drivers/staging/android/lowmemorykiller.c中,感兴趣的读者可尝试自行阅读。
1.3 关于Android中的进程管理的介绍
前面介绍了Linux OS中进程管理(包括调度和OOM控制)方面的API,但AMS是如何利用它们的呢?这就涉及AMS中的进程管理规则了。这里简单介绍相关规则。
Android将应用进程分为五大类,分别为Forground类、Visible类、Service类、Background类及Empty类。这五大类的划分各有规则。
(1) Forground类
该类中的进程重要性最高,属于该类的进程包括下面几种情况:
-
含一个前端Activity(即onResume函数被调用过了,或者说当前正在显示的那个Activity)。
-
含一个Service,并且该Service和一个前端Activity绑定(例如Music应用包括一个前端界面和一个播放Service,当我们一边听歌一边操作Music界面时,该Service即和一个前端Activity绑定)。
-
含一个调用了startForground的Service,或者该进程的Service正在调用其生命周期的函数(onCreate、onStart或onDestroy)。
-
最后一种情况是,该进程中有BroadcastReceiver实例正在执行onReceive函数。
(2) Visible类
属于Visible类的进程中没有处于前端的组件,但是用户仍然能看到它们,例如位于一个对话框后的Activity界面。目前该类进程包括两种:
-
该进程包含一个仅onPause被调用的Activity(即它还在前台,只不过部分界面被遮住)。
-
或者包含一个Service,并且该Service和一个Visible(或Forground)的Activity绑定(从字面意义上看,这种情况不太好和Forground进程中第二种情况区分)。
(3) Service类、Background类及Empty类
这三类进程都没有可见的部分,具体情况如下。
-
Service进程:该类进程包含一个Service。此Service通过startService启动,并且不属于前面两类进程。这种进程一般在后台默默地干活,例如前面介绍的MediaScannerService。
-
Background进程:该类进程包含当前不可见的Activity(即它们的onStop被调用过)。系统保存这些进程到一个LRU(最近最少使用)列表。当系统需要回收内存时,该列表中那些最近最少使用的进程将被杀死。
-
Empty进程:这类进程中不包含任何组件。为什么会出现这种不包括任何组件的进程呢?其实很简单,假设该进程仅创建了一个Activity,它完成工作后主动调用finish函数销毁(destroy)自己,之后该进程就会成为Empty进程。系统保留Empty进程的原因是当又重新需要它们时(例如用户在别的进程中通过startActivity启动了它们),可以省去fork进程、创建Android运行环境等一系列漫长而艰苦的工作。
通过以上介绍可发现,当某个进程和前端显示有关系时,其重要性相对要高,这或许是体现Google重视用户体验的一个很直接的证据吧。
2.AMS的进程管理详情
AMS的进程管理跟三个类密切关系ProcessList,ProcessRecord和Process。方法的话有updateLruProcessLocked、computeOomAdjLocked、updateOomAdjLocked、applyOomAdjLocked 。其实在AMS中保持所有的进程信息:
//所有的进程信息
final ArrayList<ProcessRecord> mLruProcesses = new ArrayList<ProcessRecord>();
//移除的进程信息
final ArrayList<ProcessRecord> mRemovedProcesses = new ArrayList<ProcessRecord>();
//用pid来查询相关的进程信息
final SparseArray<ProcessRecord> mPidsSelfLocked = new SparseArray<ProcessRecord>();
2.1 ProcessList
// frameworks/base/services/core/java/com/android/server/am/ProcessList.java
public final class ProcessList {
private static final String TAG = TAG_WITH_CLASS_NAME ? "ProcessList" : TAG_AM;
// The minimum time we allow between crashes, for us to consider this
// application to be bad and stop and its services and reject broadcasts.
static final int MIN_CRASH_INTERVAL = 60*1000;
// 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;
// Memory pages are 4K.
static final int PAGE_SIZE = 4*1024;
private final int[] mOomAdj = new int[] {
FOREGROUND_APP_ADJ, VISIBLE_APP_ADJ, PERCEPTIBLE_APP_ADJ,
BACKUP_APP_ADJ, CACHED_APP_MIN_ADJ, CACHED_APP_MAX_ADJ
};
// These are the low-end OOM level limits. This is appropriate for an
// HVGA or smaller phone with less than 512MB. Values are in KB.
private final int[] mOomMinFreeLow = new int[] {
12288, 18432, 24576,
36864, 43008, 49152
};
// These are the high-end OOM level limits. This is appropriate for a
// 1280x800 or larger screen with around 1GB RAM. Values are in KB.
private final int[] mOomMinFreeHigh = new int[] {
73728, 92160, 110592,
129024, 147456, 184320
};
这个类主要是用于OOM的设定值。什么时候会发生OOM呢?跟oom_adj值有很大关系。oom_adj 的值有几个档位如下:
AMS16.png为了防止剩余内存过低,Android在内核空间有lowmemorykiller(简称LMK),LMK是通过注册shrinker来触发低内存回收的,这个机制并不太优雅,可能会拖慢Shrinkers内存扫描速度,已从内核4.12中移除,后续会采用用户空间的LMKD + memory cgroups机制,这里先不展开LMK讲解。
进程刚启动时ADJ等于INVALID_ADJ,当执行完attachApplication(),该进程的curAdj和setAdj不相等,则会触发执行setOomAdj()将该进程的节点/proc/pid/oom_score_adj写入oomadj值。下图参数为Android原生阈值,当系统剩余空闲内存低于某阈值(比如147MB),则从ADJ大于或等于相应阈值(比如900)的进程中,选择ADJ值最大的进程,如果存在多个ADJ相同的进程,则选择内存最大的进程。 如下是64位机器,LMK默认阈值图:
AMS17.png在updateOomLevels()过程,会根据手机屏幕尺寸或内存大小来调整scale,默认大多数手机内存都大于700MB,则scale等于1。对于64位手机,阈值会更大些,具体如下。
// frameworks/base/services/core/java/com/android/server/am/ProcessList.javas
private void updateOomLevels(int displayWidth, int displayHeight, boolean write) {
// Scale buckets from avail memory: at 300MB we use the lowest values to
// 700MB or more for the top values.
float scaleMem = ((float) (mTotalMemMb - 350)) / (700 - 350);
// Scale buckets from screen size.
int minSize = 480 * 800; // 384000
int maxSize = 1280 * 800; // 1024000 230400 870400 .264
float scaleDisp = ((float)(displayWidth * displayHeight) - minSize) / (maxSize - minSize);
if (false) {
Slog.i("XXXXXX", "scaleMem=" + scaleMem);
Slog.i("XXXXXX", "scaleDisp=" + scaleDisp + " dw=" + displayWidth
+ " dh=" + displayHeight);
}
float scale = scaleMem > scaleDisp ? scaleMem : scaleDisp;
if (scale < 0) scale = 0;
else if (scale > 1) scale = 1;
int minfree_adj = Resources.getSystem().getInteger(
com.android.internal.R.integer.config_lowMemoryKillerMinFreeKbytesAdjust);
int minfree_abs = Resources.getSystem().getInteger(
com.android.internal.R.integer.config_lowMemoryKillerMinFreeKbytesAbsolute);
if (false) {
Slog.i("XXXXXX", "minfree_adj=" + minfree_adj + " minfree_abs=" + minfree_abs);
}
final boolean is64bit = Build.SUPPORTED_64_BIT_ABIS.length > 0;
for (int i = 0; i < mOomAdj.length; i++) {
int low = mOomMinFreeLow[i];
int high = mOomMinFreeHigh[i];
if (is64bit) {
// Increase the high min-free levels for cached processes for 64-bit
if (i == 4) high = (high * 3) / 2;
else if (i == 5) high = (high * 7) / 4;
}
mOomMinFree[i] = (int)(low + ((high - low) * scale));
}
if (minfree_abs >= 0) {
for (int i = 0; i < mOomAdj.length; i++) {
mOomMinFree[i] = (int)((float)minfree_abs * mOomMinFree[i]
/ mOomMinFree[mOomAdj.length - 1]);
}
}
if (minfree_adj != 0) {
for (int i = 0; i < mOomAdj.length; i++) {
mOomMinFree[i] += (int)((float) minfree_adj * mOomMinFree[i]
/ mOomMinFree[mOomAdj.length - 1]);
if (mOomMinFree[i] < 0) {
mOomMinFree[i] = 0;
}
}
}
// The maximum size we will restore a process from cached to background, when under
// memory duress, is 1/3 the size we have reserved for kernel caches and other overhead
// before killing background processes.
mCachedRestoreLevel = (getMemLevel(ProcessList.CACHED_APP_MAX_ADJ) / 1024) / 3;
// Ask the kernel to try to keep enough memory free to allocate 3 full
// screen 32bpp buffers without entering direct reclaim.
int reserve = displayWidth * displayHeight * 4 * 3 / 1024;
int reserve_adj = Resources.getSystem().getInteger(
com.android.internal.R.integer.config_extraFreeKbytesAdjust);
int reserve_abs = Resources.getSystem().getInteger(
com.android.internal.R.integer.config_extraFreeKbytesAbsolute);
if (reserve_abs >= 0) {
reserve = reserve_abs;
}
if (reserve_adj != 0) {
reserve += reserve_adj;
if (reserve < 0) {
reserve = 0;
}
}
if (write) {
ByteBuffer buf = ByteBuffer.allocate(4 * (2 * mOomAdj.length + 1));
buf.putInt(LMK_TARGET);
for (int i = 0; i < mOomAdj.length; i++) {
buf.putInt((mOomMinFree[i] * 1024)/PAGE_SIZE);
buf.putInt(mOomAdj[i]);
}
writeLmkd(buf, null);
SystemProperties.set("sys.sysctl.extra_free_kbytes", Integer.toString(reserve));
mOomLevelsSet = true;
}
// GB: 2048,3072,4096,6144,7168,8192
// HC: 8192,10240,12288,14336,16384,20480
}
2.2 ProcessRecord
// frameworks/base/services/core/java/com/android/server/am/ProcessRecord.java
public final class ProcessRecord {
private static final String TAG = TAG_WITH_CLASS_NAME ? "ProcessRecord" : TAG_AM;
private final BatteryStatsImpl mBatteryStats; // where to collect runtime statistics//管理进程电量统计
public final ApplicationInfo info; // all about the first app in the process
final boolean isolated; // true if this is a special isolated process //独立进程
public final int uid; // uid of process; may be different from 'info' if isolated
final int userId; // user of process.
public final String processName; // name of the process
// List of packages running in the process
public final ArrayMap<String, ProcessStats.ProcessStateHolder> pkgList = new ArrayMap<>();
UidRecord uidRecord; // overall state of process's uid.
//进程运行依赖的包
ArraySet<String> pkgDeps; // additional packages we have a dependency on
//保存IApplicationThread,通过它可以和应用进程交互
public IApplicationThread thread; // the actual proc... may be null only if
// 'persistent' is true (in which case we
// are in the process of launching the app)
ProcessState baseProcessTracker;
BatteryStatsImpl.Uid.Proc curProcBatteryStats;
public int pid; // The process of this application; 0 if none
String procStatFile; // path to /proc/<pid>/stat
int[] gids; // The gids this process was launched with
String requiredAbi; // The ABI this process was launched with
String instructionSet; // The instruction set this process was launched with
boolean starting; // True if the process is being started
long lastActivityTime; // For managing the LRU list//每次updateLruProcessLocked()过程会更新该值
long lastPssTime; // Last time we retrieved PSS data
long nextPssTime; // Next time we want to request PSS data
long lastStateTime; // Last time setProcState changed
long initialIdlePss; // Initial memory pss of process for idle maintenance.
long lastPss; // Last computed memory pss.
long lastSwapPss; // Last computed SwapPss.
long lastCachedPss; // Last computed pss when in cached state.
long lastCachedSwapPss; // Last computed SwapPss when in cached state.
//和oom_adj有关
int maxAdj; // Maximum OOM adjustment for this process 进程的adj上限(adjustment)
int curRawAdj; // Current OOM unlimited adjustment for this process 当前正在计算的adj,这个值有可能大于maxAdj
int setRawAdj; // Last set OOM unlimited adjustment for this process 上次计算的curRawAdj设置到lowmemorykiller系统后的adj
public int curAdj; // Current OOM adjustment for this process 当前正在计算的adj,这是curRawAdj被maxAdj削平的值
int setAdj; // Last set OOM adjustment for this process 上次计算的curAdj设置到lowmemorykiller系统后的adj
int verifiedAdj; // The last adjustment that was verified as actually being set
//和调度优先级有关
int curSchedGroup; // Currently desired scheduling class
int setSchedGroup; // Last set to background scheduling class
int vrThreadTid; // Thread currently set for VR scheduling
//回收内存级别
//默认是80%,ComponentCallbacks2.TRIM_MEMORY_COMPLETE
int trimMemoryLevel; // Last selected memory trimming level
//判断该进程的状态,主要和其中运行的Activity,Service有关 ActivityManager.PROCESS_STATE
public 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
int savedPriority; // Previous priority value if we're switching to non-SCHED_OTHER
int renderThreadTid; // TID for RenderThread
boolean serviceb; // Process currently is on the service B list
boolean serviceHighRam; // We are forcing to service B list due to its RAM use
boolean notCachedSinceIdle; // Has this process not been in a cached state since last idle?
boolean hasClientActivities; // Are there any client services with activities?
boolean hasStartedServices; // Are there any started services running in this process?
boolean foregroundServices; // Running any services that are foreground?
boolean foregroundActivities; // Running any activities that are foreground?
boolean repForegroundActivities; // Last reported foreground activities.
//这个表示进程是否绑定的activity,通过activities.size的值和visible来判断,如果visible=true,就是false
boolean systemNoUi; // This is a system process, but not currently showing UI.
boolean hasShownUi; // Has UI been shown in this process since it was started?
//显示顶层的ui
boolean hasTopUi; // Is this process currently showing a non-activity UI that the user
// is interacting with? E.g. The status bar when it is expanded, but
// not when it is minimized. When true the
// process will be set to use the ProcessList#SCHED_GROUP_TOP_APP
// scheduling group to boost performance.
boolean hasOverlayUi; // Is the process currently showing a non-activity UI that
// overlays on-top of activity UIs on screen. E.g. display a window
// of type
// android.view.WindowManager.LayoutParams#TYPE_APPLICATION_OVERLAY
// When true the process will oom adj score will be set to
// ProcessList#PERCEPTIBLE_APP_ADJ at minimum to reduce the chance
// of the process getting killed.
boolean pendingUiClean; // Want to clean up resources from showing UI?
boolean hasAboveClient; // Bound using BIND_ABOVE_CLIENT, so want to be lower
boolean treatLikeActivity; // Bound using BIND_TREAT_LIKE_ACTIVITY
//判断该进程的状态,主要和其中运行的Activity,Service有关
boolean bad; // True if disabled in the bad process list 是否处于系统BadProcess列表
public boolean killedByAm; // True when proc has been killed by activity manager, not for RAM//当值为true,意味着该进程是被AMS所杀,而非由于内存低而被LMK所杀
public boolean killed; // True once we know the process has been killed//进程被杀死
boolean procStateChanged; // Keep track of whether we changed 'setAdj'.
boolean reportedInteraction;// Whether we have told usage stats about it being an interaction
boolean unlocked; // True when proc was started in user unlocked state
long interactionEventTime; // The time we sent the last interaction event
long fgInteractionTime; // When we became foreground for interaction purposes
public String waitingToKill; // Process is waiting to be killed when in the bg, and reason
Object forcingToImportant; // Token that is forcing this process to be important
//序号,每次调节进程优先级或者LRU列表位置时,这些序号都会递增
int adjSeq; // Sequence id for identifying oom_adj assignment cycles
int lruSeq; // Sequence id for identifying LRU update cycles
CompatibilityInfo compat; // last used compatibility mode
IBinder.DeathRecipient deathRecipient; // Who is watching for the death.
//activity正在运行
ActiveInstrumentation instr;// Set to currently active instrumentation running in process
boolean usingWrapper; // Set to true when process was launched with a wrapper attached
final ArraySet<BroadcastRecord> curReceivers = new ArraySet<BroadcastRecord>();// receivers currently running in the app
long whenUnimportant; // When (uptime) the process last became unimportant
long lastCpuTime; // How long proc has run CPU at last check
long curCpuTime; // How long proc has run CPU most recently
long lastRequestedGc; // When we last asked the app to do a gc
long lastLowMemory; // When we last told the app that memory is low
long lastProviderTime; // The last time someone else was using a provider in this process.
boolean reportLowMemory; // Set to true when waiting to report low mem
boolean empty; // Is this an empty background process?
boolean cached; // Is this a cached process?
String adjType; // Debugging: primary thing impacting oom_adj.
int adjTypeCode; // Debugging: adj code to report to app.
Object adjSource; // Debugging: option dependent object.
int adjSourceProcState; // Debugging: proc state of adjSource's process.
Object adjTarget; // Debugging: target component impacting oom_adj.
Runnable crashHandler; // Optional local handler to be invoked in the process crash.
// all activities running in the process
final ArrayList<ActivityRecord> activities = new ArrayList<>();
// all ServiceRecord running in this process
final ArraySet<ServiceRecord> services = new ArraySet<>();
// services that are currently executing code (need to remain foreground).
final ArraySet<ServiceRecord> executingServices = new ArraySet<>();
// All ConnectionRecord this process holds
final ArraySet<ConnectionRecord> connections = new ArraySet<>();
// all IIntentReceivers that are registered from this process.
final ArraySet<ReceiverList> receivers = new ArraySet<>();
// class (String) -> ContentProviderRecord
//保持provider
final ArrayMap<String, ContentProviderRecord> pubProviders = new ArrayMap<>();
// All ContentProviderRecord process is using
final ArrayList<ContentProviderConnection> conProviders = new ArrayList<>();
//有相关的class运行在这个进程中
String isolatedEntryPoint; // Class to run on start if this is a special isolated process.
String[] isolatedEntryPointArgs; // Arguments to pass to isolatedEntryPoint's main().
boolean execServicesFg; // do we need to be executing services in the foreground?
boolean persistent; // always keep this application running?//经常不被杀死,杀死也会被系统重新启动
boolean crashing; // are we in the process of crashing?
Dialog crashDialog; // dialog being displayed due to crash.
boolean forceCrashReport; // suppress normal auto-dismiss of crash dialog & report UI?
boolean notResponding; // does the app have a not responding dialog?
Dialog anrDialog; // dialog being displayed due to app not resp.
boolean removed; // has app package been removed from device?
boolean debugging; // was app launched for debugging?
boolean waitedForDebugger; // has process show wait for debugger dialog?
Dialog waitDialog; // current wait for debugger dialog
String shortStringName; // caching of toShortString() result.
String stringName; // caching of toString() result
ProcessRecord 记录了进程的所有信息,比如进程名,进程包的activity ,service以及oom的阈值等有关进程的信息,具体可以看上面的代码块,有关此类的介绍可以看这篇博文:https://blog.csdn.net/tonyandroid1984/article/details/70224827
2.3 Process
// frameworks/base/core/java/android/os/Process.java
public static final int THREAD_PRIORITY_DEFAULT = 0;
/*
* ***************************************
* ** Keep in sync with utils/threads.h **
* ***************************************
*/
/**
* Lowest available thread priority. Only for those who really, really
* don't want to run if anything else is happening.
* Use with {@link #setThreadPriority(int)} and
* {@link #setThreadPriority(int, int)}, <b>not</b> with the normal
* {@link java.lang.Thread} class.
*/
public static final int THREAD_PRIORITY_LOWEST = 19;
/**
* Standard priority background threads. This gives your thread a slightly
* lower than normal priority, so that it will have less chance of impacting
* the responsiveness of the user interface.
* Use with {@link #setThreadPriority(int)} and
* {@link #setThreadPriority(int, int)}, <b>not</b> with the normal
* {@link java.lang.Thread} class.
*/
public static final int THREAD_PRIORITY_BACKGROUND = 10;
/**
* Standard priority of threads that are currently running a user interface
* that the user is interacting with. Applications can not normally
* change to this priority; the system will automatically adjust your
* application threads as the user moves through the UI.
* Use with {@link #setThreadPriority(int)} and
* {@link #setThreadPriority(int, int)}, <b>not</b> with the normal
* {@link java.lang.Thread} class.
*/
public static final int THREAD_PRIORITY_FOREGROUND = -2;
/**
* Standard priority of system display threads, involved in updating
* the user interface. Applications can not
* normally change to this priority.
* Use with {@link #setThreadPriority(int)} and
* {@link #setThreadPriority(int, int)}, <b>not</b> with the normal
* {@link java.lang.Thread} class.
*/
public static final int THREAD_PRIORITY_DISPLAY = -4;
/**
* Standard priority of the most important display threads, for compositing
* the screen and retrieving input events. Applications can not normally
* change to this priority.
* Use with {@link #setThreadPriority(int)} and
* {@link #setThreadPriority(int, int)}, <b>not</b> with the normal
* {@link java.lang.Thread} class.
*/
public static final int THREAD_PRIORITY_URGENT_DISPLAY = -8;
/**
* Standard priority of audio threads. Applications can not normally
* change to this priority.
* Use with {@link #setThreadPriority(int)} and
* {@link #setThreadPriority(int, int)}, <b>not</b> with the normal
* {@link java.lang.Thread} class.
*/
public static final int THREAD_PRIORITY_AUDIO = -16;
/**
* Standard priority of the most important audio threads.
* Applications can not normally change to this priority.
* Use with {@link #setThreadPriority(int)} and
* {@link #setThreadPriority(int, int)}, <b>not</b> with the normal
* {@link java.lang.Thread} class.
*/
public static final int THREAD_PRIORITY_URGENT_AUDIO = -19;
/**
* Minimum increment to make a priority more favorable.
*/
public static final int THREAD_PRIORITY_MORE_FAVORABLE = -1;
/**
* Minimum increment to make a priority less favorable.
*/
public static final int THREAD_PRIORITY_LESS_FAVORABLE = +1;
/**
* Default scheduling policy
* @hide
*/
//以下就是进程创建的调度策略
public static final int SCHED_OTHER = 0;
/**
* First-In First-Out scheduling policy
* @hide
*/
public static final int SCHED_FIFO = 1;
/**
* Round-Robin scheduling policy
* @hide
*/
public static final int SCHED_RR = 2;
/**
* Batch scheduling policy
* @hide
*/
public static final int SCHED_BATCH = 3;
/**
* Idle scheduling policy
* @hide
*/
public static final int SCHED_IDLE = 5;
//paid,tid 的获取
public static final int myPid() {
return Os.getpid();
}
/**
* Returns the identifier of this process' parent.
* @hide
*/
public static final int myPpid() {
return Os.getppid();
}
/**
* Returns the identifier of the calling thread, which be used with
* {@link #setThreadPriority(int, int)}.
*/
public static final int myTid() {
return Os.gettid();
}
/**
* Returns the identifier of this process's uid. This is the kernel uid
* that the process is running under, which is the identity of its
* app-specific sandbox. It is different from {@link #myUserHandle} in that
* a uid identifies a specific app sandbox in a specific user.
*/
public static final int myUid() {
return Os.getuid();
}
//设置线程等级,也就是更大的可能获得cpu调度的时间。
public static final native void setThreadPriority(int tid, int priority)
throws IllegalArgumentException, SecurityException;
public static final native void setThreadPriority(int priority)
throws IllegalArgumentException, SecurityException;
//设置线程的调度等级和策略,等级有-20到19 策略有SCHED_OTHER,SCHED_FIFO,SCHED_RR
public static final native void setThreadScheduler(int tid, int policy, int priority)
throws IllegalArgumentException;
//group == THREAD_GROUP_FOREGROUND
public static final native void setProcessGroup(int pid, int group)
throws IllegalArgumentException, SecurityException;
/**
* Return the scheduling group of requested process.
*
* @hide
*/
public static final native int getProcessGroup(int pid)
throws IllegalArgumentException, SecurityException;
以上的是代码块并没有包含全部的类信息,只是挑选一些比较重要的字段和函数来说明。
网友评论