copy from : http://gityuan.com/2016/08/07/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
实现过程中依次会computeOomAdjLocked
和applyOomAdjLocked
。
二. 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_APPSmProcessLimit
= emptyProcessLimit(空进程上限) + cachedProcessLimit(缓存进程上限)oldTime
= now - ProcessList.MAX_EMPTY_TIME;LRU进程队列长度
= numEmptyProcs(空进程数) + mNumCachedHiddenProcs(cached进程) + mNumNonCachedProcs(非cached进程)emptyFactor
= numEmptyProcs/3, 且大于等于1cachedFactor
= 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; }
该方法主要功能:
- 执行
五参updateOomAdjLocked
; - 当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; }