Android进程调度之adj算法

一、概述

提到进程调度,可能大家首先想到的是Linux cpu调度算法,进程优先级之类概念,本文并不打算介绍这些内容,而是介绍Android framework层中承载activity/service/contentprovider/broadcastrecevier的进程是如何根据组件运行状态而动态调节进程自身的状态。进程有两个比较重要的状态值,即adj(定义在ProcessList.java)和procState(定义在ActivityManager.java)。

本文是根据android 6.0原生系统的算法分析,不同手机厂商都会有各自的激进策略。 本文只介绍Google原生系统adj和procState有哪些级别。

1.1 Adj

定义在ProcessList.java文件,oom_adj划分为16级,从-17到16之间取值。adj值越大,优先级越低,adj<0的进程都是系统进程。

ADJ级别 取值 解释
UNKNOWN_ADJ 16 一般指将要会缓存进程,无法获取确定值
CACHED_APP_MAX_ADJ 15 不可见进程的adj最大值
CACHED_APP_MIN_ADJ 9 不可见进程的adj最小值
SERVICE_B_AD 8 B List中的Service(较老的、使用可能性更小)
PREVIOUS_APP_ADJ 7 上一个App的进程(往往通过按返回键)
HOME_APP_ADJ 6 Home进程
SERVICE_ADJ 5 服务进程(Service process)
HEAVY_WEIGHT_APP_ADJ 4 后台的重量级进程,system/rootdir/init.rc文件中设置
BACKUP_APP_ADJ 3 备份进程
PERCEPTIBLE_APP_ADJ 2 可感知进程,比如后台音乐播放
VISIBLE_APP_ADJ 1 可见进程(Visible process)
FOREGROUND_APP_ADJ 0 前台进程(Foreground process)
PERSISTENT_SERVICE_ADJ -11 关联着系统或persistent进程
PERSISTENT_PROC_ADJ -12 系统persistent进程,比如telephony
SYSTEM_ADJ -16 系统进程
NATIVE_ADJ -17 native进程(不被系统管理)

lmkd会根据会根据当前系统可能内存的情况,来决定杀掉不同adj级别的进程,Android进程生命周期与ADJ

FOREGROUND_APP_ADJ

1.2 ProcessState

定义在ActivityManager.java文件,process_state划分18类,从-1到16之间取值。

state级别 取值 解释
PROCESS_STATE_CACHED_EMPTY 16 进程处于cached状态,且为空进程
PROCESS_STATE_CACHED_ACTIVITY_CLIENT 15 进程处于cached状态,且为另一个cached进程(内含Activity)的client进程
PROCESS_STATE_CACHED_ACTIVITY 14 进程处于cached状态,且内含Activity
PROCESS_STATE_LAST_ACTIVITY 13 后台进程,且拥有上一次显示的Activity
PROCESS_STATE_HOME 12 后台进程,且拥有home Activity
PROCESS_STATE_RECEIVER 11 后台进程,且正在运行receiver
PROCESS_STATE_SERVICE 10 后台进程,且正在运行service
PROCESS_STATE_HEAVY_WEIGHT 9 后台进程,但无法执行restore,因此尽量避免kill该进程
PROCESS_STATE_BACKUP 8 后台进程,正在运行backup/restore操作
PROCESS_STATE_IMPORTANT_BACKGROUND 7 对用户很重要的进程,用户不可感知其存在
PROCESS_STATE_IMPORTANT_FOREGROUND 6 对用户很重要的进程,用户可感知其存在
PROCESS_STATE_TOP_SLEEPING 5 与PROCESS_STATE_TOP一样,但此时设备正处于休眠状态
PROCESS_STATE_FOREGROUND_SERVICE 4 拥有一个前台Service
PROCESS_STATE_BOUND_FOREGROUND_SERVICE 3 拥有一个前台Service,且由系统绑定
PROCESS_STATE_TOP 2 拥有当前用户可见的top Activity
PROCESS_STATE_PERSISTENT_UI 1 persistent系统进程,并正在执行UI操作
PROCESS_STATE_PERSISTENT 0 persistent系统进程
PROCESS_STATE_NONEXISTENT -1 不存在的进程

1.3 三大护法

调整进程的adj的3大护法, 也就是ADJ算法的核心方法:

  • updateOomAdjLocked:更新adj,当目标进程为空,或者被杀则返回false;否则返回true;
  • computeOomAdjLocked:计算adj,返回计算后RawAdj值;
  • applyOomAdjLocked:应用adj,当需要杀掉目标进程则返回false;否则返回true。

前面提到调整adj的3大护法,最为常见的方法便是updateOomAdjLocked,这也是其他各个方法在需要更新adj时会调用的方法,该方法有3个不同参数的同名方法,定义如下:

  • 无参方法:updateOomAdjLocked()
  • 一参方法:updateOomAdjLocked(ProcessRecord app)
  • 五参方法:updateOomAdjLocked(ProcessRecord app, int cachedAdj,
  • ProcessRecord TOP_APP, boolean doingAll, long now)

updateOomAdjLocked实现过程中依次会computeOomAdjLockedapplyOomAdjLocked

二. ADJ的更新时机

先来说说哪些场景下都会触发updateOomAdjLocked来更新进程adj:

2.1 Activity

  • ASS.realStartActivityLocked: 启动Activity
  • AS.resumeTopActivityInnerLocked: 恢复栈顶Activity
  • AS.finishCurrentActivityLocked: 结束当前Activity
  • AS.destroyActivityLocked: 摧毁当前Activity

2.2 Service

位于ActiveServices.java

  • realStartServiceLocked: 启动服务
  • bindServiceLocked: 绑定服务(只更新当前app)
  • unbindServiceLocked: 解绑服务 (只更新当前app)
  • bringDownServiceLocked: 结束服务 (只更新当前app)
  • sendServiceArgsLocked: 在bringup或则cleanup服务过程调用 (只更新当前app)

2.3 broadcast

  • BQ.processNextBroadcast: 处理下一个广播
  • BQ.processCurBroadcastLocked: 处理当前广播
  • BQ.deliverToRegisteredReceiverLocked: 分发已注册的广播 (只更新当前app)

2.4 ContentProvider

  • AMS.removeContentProvider: 移除provider
  • AMS.publishContentProviders: 发布provider (只更新当前app)
  • AMS.getContentProviderImpl: 获取provider (只更新当前app)

2.5 Process

位于ActivityManagerService.java

  • setSystemProcess: 创建并设置系统进程
  • addAppLocked: 创建persistent进程
  • attachApplicationLocked: 进程创建后attach到system_server的过程;
  • trimApplications: 清除没有使用app
  • appDiedLocked: 进程死亡
  • killAllBackgroundProcesses: 杀死所有后台进程.即(ADJ>9或removed=true的普通进程)
  • killPackageProcessesLocked: 以包名的形式 杀掉相关进程;

三. updateOomAdjLocked

3.1 重要参数

在介绍updateOomAdjLocked方法之前,先简单介绍这个过程会遇到的比较重要的参数.

[-> ProcessList.java]

  • 空进程存活时长: MAX_EMPTY_TIME = 30min
  • (缓存+空)进程个数上限:MAX_CACHED_APPS = SystemProperties.getInt("sys.fw.bg_apps_limit",32) = 32(默认);
  • 空进程个数上限:MAX_EMPTY_APPS = computeEmptyProcessLimit(MAX_CACHED_APPS) = MAX_CACHED_APPS/2 = 16;
  • trim空进程个数上限:TRIM_EMPTY_APPS = computeTrimEmptyApps() = MAX_EMPTY_APPS/2 = 8;
  • trim缓存进程个数上限:TRIM_CACHED_APPS = computeTrimCachedApps() = MAX_CACHED_APPS-MAX_EMPTY_APPS)/3 = 5;
  • TRIM_CRITICAL_THRESHOLD = 3;

[-> AMS.java]

  • mBServiceAppThreshold = SystemProperties.getInt("ro.sys.fw.bservice_limit", 5);
  • mMinBServiceAgingTime =SystemProperties.getInt("ro.sys.fw.bservice_age", 5000);
  • mProcessLimit = ProcessList.MAX_CACHED_APPS
  • mProcessLimit = emptyProcessLimit(空进程上限) + cachedProcessLimit(缓存进程上限)
  • oldTime = now - ProcessList.MAX_EMPTY_TIME;
  • LRU进程队列长度 = numEmptyProcs(空进程数) + mNumCachedHiddenProcs(cached进程) + mNumNonCachedProcs(非cached进程)
  • emptyFactor = numEmptyProcs/3, 且大于等于1
  • cachedFactor = mNumCachedHiddenProcs/3, 且大于等于1

3.2 一参方法

[-> ActivityManagerService.java]

  • final boolean updateOomAdjLocked(ProcessRecord app) {
  • //获取栈顶的Activity
  • final ActivityRecord TOP_ACT = resumedAppLocked();
  • final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
  • final boolean wasCached = app.cached;
  • mAdjSeq++;
  • //确保cachedAdj>=9
  • final int cachedAdj = app.curRawAdj >= ProcessList.CACHED_APP_MIN_ADJ
  • ? app.curRawAdj : ProcessList.UNKNOWN_ADJ;
  • //执行五参updateOomAdjLocked【见小节3.3】
  • boolean success = updateOomAdjLocked(app, cachedAdj, TOP_APP, false,
  • SystemClock.uptimeMillis());
  • //当app cached状态改变,或者curRawAdj=16,则执行无参数updateOomAdjLocked【见小节2.3】
  • if (wasCached != app.cached || app.curRawAdj == ProcessList.UNKNOWN_ADJ) {
  • updateOomAdjLocked();
  • }
  • return success;
  • }

该方法主要功能:

  1. 执行五参updateOomAdjLocked
  2. 当app经过更新adj操作后,其cached状态改变(包括由cached变成非cached,或者非cached变成cached),或者curRawAdj=16,则执行无参updateOomAdjLocked

3.3 五参方法

  • private final boolean updateOomAdjLocked(ProcessRecord app, int cachedAdj,
  • ProcessRecord TOP_APP, boolean doingAll, long now) {
  • if (app.thread == null) {
  • return false;
  • }
  • //【见小节4】
  • computeOomAdjLocked(app, cachedAdj, TOP_APP, doingAll, now);
  • //【见小节5】
  • return applyOomAdjLocked(app, doingAll, now, SystemClock.elapsedRealtime());
  • }

该方法是private方法,只提供给一参无参的同名方法调用,系统中并没有其他地方调用。

3.4 无参方法(核心)

  • final void updateOomAdjLocked() {
  • //获取栈顶的Activity
  • final ActivityRecord TOP_ACT = resumedAppLocked();
  • final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
  • final long now = SystemClock.uptimeMillis();
  • final long nowElapsed = SystemClock.elapsedRealtime();
  • final long oldTime = now - ProcessList.MAX_EMPTY_TIME;
  • final int N = mLruProcesses.size();
  • //重置所有uid记录,把curProcState设置成16(空进程)
  • for (int i=mActiveUids.size()-1; i>=0; i--) {
  • final UidRecord uidRec = mActiveUids.valueAt(i);
  • uidRec.reset();
  • }
  • mAdjSeq++;
  • mNewNumServiceProcs = 0;
  • mNewNumAServiceProcs = 0;
  • final int emptyProcessLimit;
  • final int cachedProcessLimit;
  • // mProcessLimit默认值等于32,通过开发者选择可设置,或者厂商会自行调整
  • if (mProcessLimit <= 0) {
  • emptyProcessLimit = cachedProcessLimit = 0;
  • } else if (mProcessLimit == 1) {
  • emptyProcessLimit = 1;
  • cachedProcessLimit = 0;
  • } else {
  • //则emptyProcessLimit = 16, cachedProcessLimit = 16
  • emptyProcessLimit = ProcessList.computeEmptyProcessLimit(mProcessLimit);
  • cachedProcessLimit = mProcessLimit - emptyProcessLimit;
  • }
  • //经过计算得 numSlots =3
  • int numSlots = (ProcessList.CACHED_APP_MAX_ADJ
  • - ProcessList.CACHED_APP_MIN_ADJ + 1) / 2;
  • int numEmptyProcs = N - mNumNonCachedProcs - mNumCachedHiddenProcs;
  • //确保空进程个数不大于cached进程数
  • if (numEmptyProcs > cachedProcessLimit) {
  • numEmptyProcs = cachedProcessLimit;
  • }
  • int emptyFactor = numEmptyProcs/numSlots;
  • if (emptyFactor < 1) emptyFactor = 1;
  • int cachedFactor = (mNumCachedHiddenProcs > 0 ? mNumCachedHiddenProcs : 1)/numSlots;
  • if (cachedFactor < 1) cachedFactor = 1;
  • int stepCached = 0;
  • int stepEmpty = 0;
  • int numCached = 0;
  • int numEmpty = 0;
  • int numTrimming = 0;
  • mNumNonCachedProcs = 0;
  • mNumCachedHiddenProcs = 0;
  • //更新所有进程状态(基于当前状态)
  • int curCachedAdj = ProcessList.CACHED_APP_MIN_ADJ;
  • int nextCachedAdj = curCachedAdj+1;
  • int curEmptyAdj = ProcessList.CACHED_APP_MIN_ADJ;
  • int nextEmptyAdj = curEmptyAdj+2;
  • ProcessRecord selectedAppRecord = null;
  • long serviceLastActivity = 0;
  • int numBServices = 0;
  • for (int i=N-1; i>=0; i--) {
  • ProcessRecord app = mLruProcesses.get(i);
  • if (mEnableBServicePropagation && app.serviceb
  • && (app.curAdj == ProcessList.SERVICE_B_ADJ)) {
  • numBServices++;
  • for (int s = app.services.size() - 1; s >= 0; s--) {
  • ServiceRecord sr = app.services.valueAt(s);
  • //上次活跃时间距离现在小于5s,则不会迁移到BService
  • if (SystemClock.uptimeMillis() - sr.lastActivity
  • < mMinBServiceAgingTime) {
  • continue;
  • }
  • if (serviceLastActivity == 0) {
  • serviceLastActivity = sr.lastActivity;
  • selectedAppRecord = app;
  • //记录service上次活动时间最长的那个app
  • } else if (sr.lastActivity < serviceLastActivity) {
  • serviceLastActivity = sr.lastActivity;
  • selectedAppRecord = app;
  • }
  • }
  • }
  • if (!app.killedByAm && app.thread != null) {
  • app.procStateChanged = false;
  • //计算app的adj值【见小节4】
  • computeOomAdjLocked(app, ProcessList.UNKNOWN_ADJ, TOP_APP, true, now);
  • //当进程未分配adj的情况下,更新adj(cached和empty算法是相同的)
  • if (app.curAdj >= ProcessList.UNKNOWN_ADJ) {
  • switch (app.curProcState) {
  • case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY:
  • case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT:
  • //当进程procState=14或15,则设置adj=9;
  • app.curRawAdj = curCachedAdj;
  • app.curAdj = app.modifyRawOomAdj(curCachedAdj);
  • //当前cacheadj不等于下一次cachedadj时
  • if (curCachedAdj != nextCachedAdj) {
  • stepCached++;
  • //当stepCached大于cachedFactor,则将nextCachedAdj赋值给curCachedAdj,
  • // 并且nextCachedAdj加2,nextCachedAdj最大等于15;
  • if (stepCached >= cachedFactor) {
  • stepCached = 0;
  • curCachedAdj = nextCachedAdj;
  • nextCachedAdj += 2;
  • if (nextCachedAdj > ProcessList.CACHED_APP_MAX_ADJ) {
  • nextCachedAdj = ProcessList.CACHED_APP_MAX_ADJ;
  • }
  • }
  • }
  • break;
  • default:
  • app.curRawAdj = curEmptyAdj;
  • app.curAdj = app.modifyRawOomAdj(curEmptyAdj);
  • //更新curCachedAdj值
  • if (curEmptyAdj != nextEmptyAdj) {
  • stepEmpty++;
  • //当stepEmpty大于emptyFactor,则将nextEmptyAdj赋值给curEmptyAdj,
  • //并且nextEmptyAdj加2,nextEmptyAdj最大等于15;
  • if (stepEmpty >= emptyFactor) {
  • stepEmpty = 0;
  • curEmptyAdj = nextEmptyAdj;
  • nextEmptyAdj += 2;
  • if (nextEmptyAdj > ProcessList.CACHED_APP_MAX_ADJ) {
  • nextEmptyAdj = ProcessList.CACHED_APP_MAX_ADJ;
  • }
  • }
  • }
  • break;
  • }
  • }
  • //【见小节2.5】
  • applyOomAdjLocked(app, true, now, nowElapsed);
  • //根据当前进程procState状态来决策
  • switch (app.curProcState) {
  • case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY:
  • case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT:
  • mNumCachedHiddenProcs++;
  • numCached++;
  • // 当cached进程超过上限(cachedProcessLimit),则杀掉该进程
  • if (numCached > cachedProcessLimit) {
  • app.kill("cached #" + numCached, true);
  • }
  • break;
  • case ActivityManager.PROCESS_STATE_CACHED_EMPTY:
  • // 当空进程超过上限(TRIM_EMPTY_APPS),且空闲时间超过30分钟,则杀掉该进程
  • if (numEmpty > ProcessList.TRIM_EMPTY_APPS
  • && app.lastActivityTime < oldTime) {
  • app.kill("empty for "
  • + ((oldTime + ProcessList.MAX_EMPTY_TIME - app.lastActivityTime)
  • / 1000) + "s", true);
  • } else {
  • // 当空进程超过上限(emptyProcessLimit),则杀掉该进程
  • numEmpty++;
  • if (numEmpty > emptyProcessLimit) {
  • if (!CT_PROTECTED_PROCESS.equals(app.processName))
  • app.kill("empty #" + numEmpty, true);
  • }
  • }
  • break;
  • default:
  • mNumNonCachedProcs++;
  • break;
  • }
  • if (app.isolated && app.services.size() <= 0) {
  • //没有services运行的孤立进程,则直接杀掉
  • app.kill("isolated not needed", true);
  • } else {
  • final UidRecord uidRec = app.uidRecord;
  • if (uidRec != null && uidRec.curProcState > app.curProcState) {
  • uidRec.curProcState = app.curProcState;
  • }
  • }
  • if (app.curProcState >= ActivityManager.PROCESS_STATE_HOME
  • && !app.killedByAm) {
  • numTrimming++;
  • }
  • }
  • }
  • //当BServices个数超过上限(mBServiceAppThreshold),则
  • if ((numBServices > mBServiceAppThreshold) && (true == mAllowLowerMemLevel)
  • && (selectedAppRecord != null)) {
  • ProcessList.setOomAdj(selectedAppRecord.pid, selectedAppRecord.info.uid,
  • ProcessList.CACHED_APP_MAX_ADJ);
  • selectedAppRecord.setAdj = selectedAppRecord.curAdj;
  • }
  • mNumServiceProcs = mNewNumServiceProcs;
  • //根据CachedAndEmpty个数来调整内存因子memFactor
  • final int numCachedAndEmpty = numCached + numEmpty;
  • int memFactor;
  • if (numCached <= ProcessList.TRIM_CACHED_APPS
  • && numEmpty <= ProcessList.TRIM_EMPTY_APPS) {
  • if (numCachedAndEmpty <= ProcessList.TRIM_CRITICAL_THRESHOLD) {
  • memFactor = ProcessStats.ADJ_MEM_FACTOR_CRITICAL;
  • } else if (numCachedAndEmpty <= ProcessList.TRIM_LOW_THRESHOLD) {
  • memFactor = ProcessStats.ADJ_MEM_FACTOR_LOW;
  • } else {
  • memFactor = ProcessStats.ADJ_MEM_FACTOR_MODERATE;
  • }
  • } else {
  • memFactor = ProcessStats.ADJ_MEM_FACTOR_NORMAL;
  • }
  • if (memFactor > mLastMemoryLevel) {
  • if (!mAllowLowerMemLevel || mLruProcesses.size() >= mLastNumProcesses) {
  • memFactor = mLastMemoryLevel;
  • }
  • }
  • mLastMemoryLevel = memFactor;
  • mLastNumProcesses = mLruProcesses.size();
  • boolean allChanged = mProcessStats.setMemFactorLocked(memFactor, !isSleeping(), now);
  • final int trackerMemFactor = mProcessStats.getMemFactorLocked();
  • //当内存因子不是普通0级别的情况下
  • if (memFactor != ProcessStats.ADJ_MEM_FACTOR_NORMAL) {
  • if (mLowRamStartTime == 0) {
  • mLowRamStartTime = now;
  • }
  • int step = 0;
  • int fgTrimLevel;
  • switch (memFactor) {
  • case ProcessStats.ADJ_MEM_FACTOR_CRITICAL:
  • fgTrimLevel = ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL;
  • break;
  • case ProcessStats.ADJ_MEM_FACTOR_LOW:
  • fgTrimLevel = ComponentCallbacks2.TRIM_MEMORY_RUNNING_LOW;
  • break;
  • default:
  • fgTrimLevel = ComponentCallbacks2.TRIM_MEMORY_RUNNING_MODERATE;
  • break;
  • }
  • int factor = numTrimming/3;
  • int minFactor = 2;
  • if (mHomeProcess != null) minFactor++;
  • if (mPreviousProcess != null) minFactor++;
  • if (factor < minFactor) factor = minFactor;
  • //TRIM_MEMORY_COMPLETE:该进程处于LRU队列的尾部,当进程不足则会杀掉该进程
  • int curLevel = ComponentCallbacks2.TRIM_MEMORY_COMPLETE;
  • for (int i=N-1; i>=0; i--) {
  • ProcessRecord app = mLruProcesses.get(i);
  • if (allChanged || app.procStateChanged) {
  • setProcessTrackerStateLocked(app, trackerMemFactor, now);
  • app.procStateChanged = false;
  • }
  • //当curProcState > 12且没有被am杀掉的情况;
  • if (app.curProcState >= ActivityManager.PROCESS_STATE_HOME
  • && !app.killedByAm) {
  • if (app.trimMemoryLevel < curLevel && app.thread != null) {
  • //调度app执行trim memory的操作
  • app.thread.scheduleTrimMemory(curLevel);
  • }
  • app.trimMemoryLevel = curLevel;
  • step++;
  • if (step >= factor) {
  • step = 0;
  • switch (curLevel) {
  • case ComponentCallbacks2.TRIM_MEMORY_COMPLETE:
  • curLevel = ComponentCallbacks2.TRIM_MEMORY_MODERATE;
  • break;
  • case ComponentCallbacks2.TRIM_MEMORY_MODERATE:
  • curLevel = ComponentCallbacks2.TRIM_MEMORY_BACKGROUND;
  • break;
  • }
  • }
  • } else if (app.curProcState == ActivityManager.PROCESS_STATE_HEAVY_WEIGHT) {
  • if (app.trimMemoryLevel < ComponentCallbacks2.TRIM_MEMORY_BACKGROUND
  • && app.thread != null) {
  • app.thread.scheduleTrimMemory(
  • ComponentCallbacks2.TRIM_MEMORY_BACKGROUND);
  • }
  • app.trimMemoryLevel = ComponentCallbacks2.TRIM_MEMORY_BACKGROUND;
  • } else {
  • if ((app.curProcState >= ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND
  • || app.systemNoUi) && app.pendingUiClean) {
  • final int level = ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN;
  • if (app.trimMemoryLevel < level && app.thread != null) {
  • app.thread.scheduleTrimMemory(level);
  • }
  • app.pendingUiClean = false;
  • }
  • if (app.trimMemoryLevel < fgTrimLevel && app.thread != null) {
  • app.thread.scheduleTrimMemory(fgTrimLevel);
  • }
  • app.trimMemoryLevel = fgTrimLevel;
  • }
  • }
  • } else {
  • if (mLowRamStartTime != 0) {
  • mLowRamTimeSinceLastIdle += now - mLowRamStartTime;
  • mLowRamStartTime = 0;
  • }
  • for (int i=N-1; i>=0; i--) {
  • ProcessRecord app = mLruProcesses.get(i);
  • if (allChanged || app.procStateChanged) {
  • setProcessTrackerStateLocked(app, trackerMemFactor, now);
  • app.procStateChanged = false;
  • }
  • if ((app.curProcState >= ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND
  • || app.systemNoUi) && app.pendingUiClean) {
  • if (app.trimMemoryLevel < ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN
  • && app.thread != null) {
  • app.thread.scheduleTrimMemory(
  • ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN);
  • }
  • app.pendingUiClean = false;
  • }
  • app.trimMemoryLevel = 0;
  • }
  • }
  • //是否finish activity
  • if (mAlwaysFinishActivities) {
  • mStackSupervisor.scheduleDestroyAllActivities(null, "always-finish");
  • }
  • if (allChanged) {
  • requestPssAllProcsLocked(now, false, mProcessStats.isMemFactorLowered());
  • }
  • //更新 uid的改变
  • for (int i=mActiveUids.size()-1; i>=0; i--) {
  • final UidRecord uidRec = mActiveUids.valueAt(i);
  • if (uidRec.setProcState != uidRec.curProcState) {
  • uidRec.setProcState = uidRec.curProcState;
  • enqueueUidChangeLocked(uidRec, false);
  • }
  • }
  • ...
  • }

3.5 小节

updateOomAdjLocked过程比较复杂,主要分为更新adj(满足条件则杀进程)和根据memFactor来调度执行TrimMemory操作;

第一部分:更新adj(满足条件则杀进程)

  • 遍历mLruProcesses进程

    • 当进程未分配adj的情况

      • 当进程procState=14或15,则设置adj=curCachedAdj(初始化=9);
        • 当curCachedAdj != nextCachedAdj,且stepCached大于cachedFactor时
          curCachedAdj = nextCachedAdj,(nextCachedAdj加2,nextCachedAdj上限为15);
      • 否则,则设置adj=curEmptyAdj(初始化=9);
        • 当curEmptyAdj != nextEmptyAdj,且stepEmpty大于EmptyFactor时
          curEmptyAdj = nextEmptyAdj,(nextEmptyAdj加2,nextEmptyAdj上限为15);


    • 根据当前进程procState状态来决策:

      • 当curProcState=14或15,且cached进程超过上限(cachedProcessLimit=16),则杀掉该进程
      • 当curProcState=16的前提下:
        • 当空进程超过上限(TRIM_EMPTY_APPS=8),且空闲时间超过30分钟,则杀掉该进程
        • 否则,当空进程超过上限(emptyProcessLimit=16),则杀掉该进程


    • 没有services运行的孤立进程,则杀掉该进程;

第二部分:根据memFactor来调度执行TrimMemory操作;

  • 根据CachedAndEmpty个数来调整内存因子memFactor(值越大,级别越高):

    • 当CachedAndEmpty < 3,则memFactor=3;
    • 当CachedAndEmpty < 5,则memFactor=2;
    • 当CachedAndEmpty >=5,且numCached<=5,numEmpty<=8,则memFactor=1;
    • 当numCached>5 或numEmpty>8,则memFactor=0;
  • 当内存因子不是普通0级别的情况下,根据memFactor来调整前台trim级别(fgTrimLevel):

    • 当memFactor=3,则fgTrimLevel=TRIM_MEMORY_RUNNING_CRITICAL;

    • 当memFactor=2,则fgTrimLevel=TRIM_MEMORY_RUNNING_LOW;

    • 否则(其实就是memFactor=1),则fgTrimLevel=TRIM_MEMORY_RUNNING_MODERATE

    • 再遍历mLruProcesses队列进程:
      • 当curProcState > 12且没有被am杀掉,则执行TrimMemory操作;
      • 否则,当curProcState = 9 且trimMemoryLevel<TRIM_MEMORY_BACKGROUND,则执行TrimMemory操作;
      • 否则,当curProcState > 7, 且pendingUiClean =true时
        • 当trimMemoryLevel<TRIM_MEMORY_UI_HIDDEN,则执行TrimMemory操作;
        • 当trimMemoryLevel<fgTrimLevel,则执行TrimMemory操作;

  • 当内存因子等于0的情况下,遍历mLruProcesses队列进程:
    • 当curProcState >=7, 且pendingUiClean =true时,
      • 当trimMemoryLevel< TRIM_MEMORY_UI_HIDDEN,则执行TrimMemory操作;

四. computeOomAdjLocked

  • private final int computeOomAdjLocked(ProcessRecord app, int cachedAdj, ProcessRecord TOP_APP,
  • boolean doingAll, long now)

该方法比较长,下面分几个部分来展开说明, 每一部分后主要功能便是设置adj和procState(进程状态): (adj和procState的取值原则是以优先级高为主)

1. 空进程情况

  • if (mAdjSeq == app.adjSeq) {
  • return app.curRawAdj; //已经调整完成
  • }
  • // 当进程对象为空时,则设置curProcState=16, curAdj=curRawAdj=15
  • if (app.thread == null) {
  • app.adjSeq = mAdjSeq;
  • app.curSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
  • app.curProcState = ActivityManager.PROCESS_STATE_CACHED_EMPTY;
  • return (app.curAdj=app.curRawAdj=ProcessList.CACHED_APP_MAX_ADJ);
  • }

2. maxAdj<=0情况

  • final int activitiesSize = app.activities.size();
  • if (app.maxAdj <= ProcessList.FOREGROUND_APP_ADJ) {
  • app.adjType = "fixed";
  • app.adjSeq = mAdjSeq;
  • app.curRawAdj = app.maxAdj;
  • app.foregroundActivities = false;
  • app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
  • app.curProcState = ActivityManager.PROCESS_STATE_PERSISTENT;
  • app.systemNoUi = true;
  • //顶部的activity就是当前app,则代表正处于展现UI
  • if (app == TOP_APP) {
  • app.systemNoUi = false;
  • //进程中的activity个数大于0时
  • } else if (activitiesSize > 0) {
  • for (int j = 0; j < activitiesSize; j++) {
  • final ActivityRecord r = app.activities.get(j);
  • if (r.visible) {
  • app.systemNoUi = false;
  • }
  • }
  • }
  • if (!app.systemNoUi) {
  • app.curProcState = ActivityManager.PROCESS_STATE_PERSISTENT_UI;
  • }
  • return (app.curAdj=app.maxAdj);
  • }

当maxAdj <=0的情况,也就意味这不允许app将其adj调整到低于前台app的优先级别, 这样场景下执行后将直接返回:

  • curProcState =PROCESS_STATE_PERSISTENT或 PROCESS_STATE_PERSISTENT_UI(存在visible的activity)
  • curAdj = app.maxAdj (curAdj<=0)

3. 前台的情况

  • if (app == TOP_APP) {
  • adj = ProcessList.FOREGROUND_APP_ADJ;
  • schedGroup = Process.THREAD_GROUP_DEFAULT;
  • app.adjType = "top-activity";
  • foregroundActivities = true;
  • procState = PROCESS_STATE_TOP;
  • if(app == mHomeProcess) {
  • mHomeKilled = false;
  • mHomeProcessName = mHomeProcess.processName;
  • }
  • } else if (app.instrumentationClass != null) {
  • adj = ProcessList.FOREGROUND_APP_ADJ;
  • schedGroup = Process.THREAD_GROUP_DEFAULT;
  • app.adjType = "instrumentation";
  • procState = ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE;
  • } else if ((queue = isReceivingBroadcast(app)) != null) {
  • adj = ProcessList.FOREGROUND_APP_ADJ;
  • schedGroup = (queue == mFgBroadcastQueue)
  • ? Process.THREAD_GROUP_DEFAULT : Process.THREAD_GROUP_BG_NONINTERACTIVE;
  • app.adjType = "broadcast";
  • procState = ActivityManager.PROCESS_STATE_RECEIVER;
  • } else if (app.executingServices.size() > 0) {
  • adj = ProcessList.FOREGROUND_APP_ADJ;
  • schedGroup = app.execServicesFg ?
  • Process.THREAD_GROUP_DEFAULT : Process.THREAD_GROUP_BG_NONINTERACTIVE;
  • app.adjType = "exec-service";
  • procState = ActivityManager.PROCESS_STATE_SERVICE;
  • } else {
  • //top app; isReceivingBroadcast;executingServices;
  • // 除此之外则为PROCESS_STATE_CACHED_EMPTY
  • schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
  • adj = cachedAdj;
  • procState = ActivityManager.PROCESS_STATE_CACHED_EMPTY;
  • app.cached = true;
  • app.empty = true;
  • app.adjType = "cch-empty";
  • if (mHomeKilled && app.processName.equals(mHomeProcessName)) {
  • adj = ProcessList.PERSISTENT_PROC_ADJ;
  • schedGroup = Process.THREAD_GROUP_DEFAULT;
  • app.cached = false;
  • app.empty = false;
  • app.adjType = "top-activity";
  • }
  • }
Case adj procState
当app是当前展示的app adj=0 procState=2
当instrumentation不为空时 adj=0 procState=4
当进程存在正在接收的broadcastrecevier adj=0 procState=11
当进程存在正在执行的service adj=0 procState=10
以上条件都不符合 adj=cachedAd(>=0)j procState=16

4. 非前台activity的情况

```java
if (!foregroundActivities && activitiesSize > 0) {
for (int j = 0; j < activitiesSize; j++) { final ActivityRecord r = app.activities.get(j); if (r.app != app) { continue; } 当activity可见, 则adj=1,procState=2 if (r.visible) { if (adj > ProcessList.VISIBLE_APP_ADJ) {
adj = ProcessList.VISIBLE_APP_ADJ;
app.adjType = "visible";
}
if (procState > PROCESS_STATE_TOP) {
procState = PROCESS_STATE_TOP;
}
schedGroup = Process.THREAD_GROUP_DEFAULT;
app.cached = false;
app.empty = false;
foregroundActivities = true;
break;
当activity正在暂停或者已经暂停, 则adj=2,procState=2
} else if (r.state == ActivityState.PAUSING || r.state == ActivityState.PAUSED) {
if (adj > ProcessList.PERCEPTIBLE_APP_ADJ) {
adj = ProcessList.PERCEPTIBLE_APP_ADJ;
app.adjType = "pausing";
}
if (procState > PROCESS_STATE_TOP) {
procState = PROCESS_STATE_TOP;
}
schedGroup = Process.THREAD_GROUP_DEFAULT;
app.cached = false;
app.empty = false;
foregroundActivities = true;
当activity正在停止, 则adj=2,procState=13(activity尚未finish)
} else if (r.state == ActivityState.STOPPING) {
if (adj > ProcessList.PERCEPTIBLE_APP_ADJ) {
adj = ProcessList.PERCEPTIBLE_APP_ADJ;
app.adjType = "stopping";
}

  • if (!r.finishing) {
  • if (procState > ActivityManager.PROCESS_STATE_LAST_ACTIVITY) {
  • procState = ActivityManager.PROCESS_STATE_LAST_ACTIVITY;
  • }
  • }
  • app.cached = false;
top Created with Sketch.