Android OOM Adjustments
22290 ワード
以前、LMKを分析する文章を書いたことがありますが、それは主にLMKの実現原理を分析し、AMSのOOM Adjの調整を詳しく分析していません.今回はAndroid 9.0のコードを参考に分析してみましたが、主にコード実装を分析しています.まずOOM Adjの定義を見てみましょう.
Adj
Value
Comments
UNKNOWN_ADJ
1001
特定できないAdjは、通常キャッシュするプロセスです.
CACHED_APP_MAX_ADJ
906
非表示プロセスのAdj最大値
CACHED_APP_MIN_ADJ
900
非表示プロセスのAdj最小値
SERVICE_B_ADJ
800
Bリストのサービスは、Aリストよりユーザーへの接着度が小さい
PREVIOUS_APP_ADJ
700
ユーザの前回のインタラクションのプロセス
HOME_APP_ADJ
600
Launcherプロセス
SERVICE_ADJ
500
サービスプロセスの適用
HEAVY_WEIGHT_APP_ADJ
400
バックグラウンドのヘビー級プロセス
BACKUP_APP_ADJ
300
backup関連操作を担持するプロセス
PERCEPTIBLE_APP_ADJ
200
バックグラウンド音楽の再生など、感知可能なプロセス
VISIBLE_APP_ADJ
100
フロントに表示されるActivityプロセス
FOREGROUND_APP_ADJ
0
現在フロントで実行されているプロセス、つまりユーザーが対話しているプログラム
PERSISTENT_SERVICE_ADJ
-700
システムプロセスまたはPersistentプロセスにバインドされたプロセス
PERSISTENT_PROC_ADJ
-800
Persistentプロパティのプロセス、例えばtelephony
SYSTEM_ADJ
-900
システムプロセス
NATIVE_ADJ
-1000
Nativeプロセス、システム管理されない
updateOomAdj
OOM Adjの更新はAMSにおけるupdateOomAdjLocked()関数により行われる.この関数ではOOM Adjだけでなくメモリの調整も行います.まずOOM Adjの調整実装を見てみましょう.
OOM Adjの更新プロセスは主に以下の作業を完了します.プロセスのOOM Adj値を再計算し、更新する. Adj値が割り当てられていないプロセスは、プロセスステータスに応じてバックグラウンドキャッシュプロセスとemptyプロセスに分けられ、CACHED_APP_MIN_ADJからCACHED_APP_MAX_ADJは、Adj値を割り当てる.バックグラウンドキャッシュプロセスとemptyプロセスのAdj値は交差して増加し、各レベルのプロセス個数は予め計算された最大値を超えない. LRUのプロセスを逆処理し、制限を超えるバックグラウンドキャッシュプロセスとemptyプロセスを回収します.デフォルトの制限では、バックグラウンドキャッシュプロセスとemptyプロセスがそれぞれ16個ずつあります. isolatedプロセス結果にはサービスが含まれておらず、直接回収されています. プロセスのUIDERecordを更新します.
次にupdateOomAdjLocked()のメモリ調整に関する部分を分析します.Androidはシステムメモリの状態を4段階に分け、以下のように定義しています.
Adj
Value
Comments
ADJ_MEM_FACTOR_NORMAL
0
システムメモリは正常で、調整する必要はありません
ADJ_MEM_FACTOR_MODERATE
1
システムメモリは中程度で、正常な状態より低い
ADJ_MEM_FACTOR_LOW
2
システムメモリが低いので、メモリを回収する必要があります.
ADJ_MEM_FACTOR_CRITICAL
3
システムのメモリが不足しているので、メモリを回収しなければなりません.
ComponentCallbacks 2では、メモリ回収のレベルも定義されています.最初の3つはバックグラウンドキャッシュの回収レベル、後の3つはプロセス実行時の回収レベルです.
Adj
Value
Comments
TRIM_MEMORY_COMPLETE
80
バックグラウンドLRUリストの末尾にあるプロセスは、より多くのメモリが見つからない場合、すぐに殺されます.
TRIM_MEMORY_MODERATE
60
バックグラウンドLRUリストの中央にあるプロセスでは、メモリをクリーンアップすることで、後続のプロセスのパフォーマンスが向上します.
TRIM_MEMORY_BACKGROUND
40
バックグラウンドプロセスは、LRUリストの先頭にあり、メモリをクリーンアップすることで、プロセスをより効率的にフロントに戻すことができます.
TRIM_MEMORY_UI_HIDDEN
20
プロセスUIが表示されなくなり、UIリソースを解放できます.
TRIM_MEMORY_RUNNING_CRITICAL
15
デバイスは低メモリで動作しており、バックグラウンドプロセスの生存を保証できません.重要でないリソースをできるだけ解放する必要があります.次にonLowMemory()を呼び出してシステムのメモリが低く、ユーザーに顕著な影響を及ぼしていることを報告します.
TRIM_MEMORY_RUNNING_LOW
10
デバイスが低メモリで動作しているため、不要なリソースを解放する必要があります.
TRIM_MEMORY_RUNNING_MODERATE
5
デバイスの動作メモリが低いため、不要なリソースを解放する必要がある場合があります.
Androidシステムは、バックグラウンドキャッシュプロセスとemptyプロセスの数に応じてメモリレベルを区別します.システムは常にバックグラウンドプロセスをできるだけ多く保持しているため、プロセスの再起動時に起動時間を減らすことができ、ユーザー体験がより良い.しかし,システムメモリが不足するとlowmemeorykillerメカニズムが重要でないバックグラウンドプロセスを優先的に殺すため,バックグラウンドプロセスの数はlowmemrorykillerのトリガに関連していると考えられる.残りのバックグラウンドプロセスが少ないほど、Lowmemroykillerによって回収されるメモリが多いほど、システム全体のメモリが緊張することを示します.
メモリ調整の主な仕事は、プロセスを殺さずに、必要に応じてメモリを回収することです.メモリが低い場合、プロセス状態がHOMEより大きい重要でないプロセスでは、LRUの逆順序メモリ回収レベルに応じて徐々に低下します. メモリが低い場合、重要なプロセスほど重要なメモリ回収レベルが高くなります. メモリが正常であれば、バックグラウンドにUIがあるプロセスのメモリ回収を行います.
computeOomAdj
上でupdateOomAdjLocked()の大まかな流れを分析し、次にその中の重要な関数computeOomAdjLocked()の1つを分析し、OOM Adjをどのように計算するかを分析します.
computeOomAdjLocked()はコード量が多く,論理が非常に複雑である.簡単に言えば,プロセスの様々な状態に応じて,Adj,schedGroup,procStateなどを調整する.ここは簡単に大まかな流れを引いただけで、細部は書いていません.多すぎます.
applyOomAdj
プロセスのOOM Adjを計算した後、Adj値をAndroid LowMemoryKiller(LMK)メカニズムに設定する必要があります.具体的なソースコードは以下の通りです.
applyOomAdjLocked()はLMKのAdj値を設定するだけでなく、TOPプロセスのスケジューリングポリシーや優先度の調整、PSSデータの収集、ステータス変更ブロードキャストの送信などの作業も完了している.
Adj
Value
Comments
UNKNOWN_ADJ
1001
特定できないAdjは、通常キャッシュするプロセスです.
CACHED_APP_MAX_ADJ
906
非表示プロセスのAdj最大値
CACHED_APP_MIN_ADJ
900
非表示プロセスのAdj最小値
SERVICE_B_ADJ
800
Bリストのサービスは、Aリストよりユーザーへの接着度が小さい
PREVIOUS_APP_ADJ
700
ユーザの前回のインタラクションのプロセス
HOME_APP_ADJ
600
Launcherプロセス
SERVICE_ADJ
500
サービスプロセスの適用
HEAVY_WEIGHT_APP_ADJ
400
バックグラウンドのヘビー級プロセス
BACKUP_APP_ADJ
300
backup関連操作を担持するプロセス
PERCEPTIBLE_APP_ADJ
200
バックグラウンド音楽の再生など、感知可能なプロセス
VISIBLE_APP_ADJ
100
フロントに表示されるActivityプロセス
FOREGROUND_APP_ADJ
0
現在フロントで実行されているプロセス、つまりユーザーが対話しているプログラム
PERSISTENT_SERVICE_ADJ
-700
システムプロセスまたはPersistentプロセスにバインドされたプロセス
PERSISTENT_PROC_ADJ
-800
Persistentプロパティのプロセス、例えばtelephony
SYSTEM_ADJ
-900
システムプロセス
NATIVE_ADJ
-1000
Nativeプロセス、システム管理されない
updateOomAdj
OOM Adjの更新はAMSにおけるupdateOomAdjLocked()関数により行われる.この関数ではOOM Adjだけでなくメモリの調整も行います.まずOOM Adjの調整実装を見てみましょう.
final void updateOomAdjLocked() {
......
boolean retryCycles = false;
// service , cycle ,
for (int i=N-1; i>=0; i--) {
ProcessRecord app = mLruProcesses.get(i);
app.containsCycle = false;
}
for (int i=N-1; i>=0; i--) {
ProcessRecord app = mLruProcesses.get(i);
if (!app.killedByAm && app.thread != null) {
app.procStateChanged = false;
// app OOM adj
computeOomAdjLocked(app, ProcessList.UNKNOWN_ADJ, TOP_APP, true, now);
// cycle ,
retryCycles |= app.containsCycle;
// Adj , 。
if (app.curAdj >= ProcessList.UNKNOWN_ADJ) {
......
}
}
}
// cycle , OOM Adj,
int cycleCount = 0;
while (retryCycles) {
cycleCount++;
retryCycles = false;
for (int i=0; i=0; i--) {
ProcessRecord app = mLruProcesses.get(i);
if (!app.killedByAm && app.thread != null) {
// OOM Adj
applyOomAdjLocked(app, true, now, nowElapsed);
// , empty
switch (app.curProcState) {
case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY:
case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT:
......
break;
case ActivityManager.PROCESS_STATE_CACHED_EMPTY:
......
break;
default:
mNumNonCachedProcs++;
break;
}
if (app.isolated && app.services.size() <= 0 && app.isolatedEntryPoint == null) {
//
app.kill("isolated not needed", true);
} else {
// , uid
final UidRecord uidRec = app.uidRecord;
......
}
// HOME ,
if (app.curProcState >= ActivityManager.PROCESS_STATE_HOME
&& !app.killedByAm) {
numTrimming++;
}
}
}
// uid ,
incrementProcStateSeqAndNotifyAppsLocked();
mNumServiceProcs = mNewNumServiceProcs;
......
//
......
// Activity
if (mAlwaysFinishActivities) {
mStackSupervisor.scheduleDestroyAllActivities(null, "always-finish");
}
if (allChanged) {
requestPssAllProcsLocked(now, false, mProcessStats.isMemFactorLowered());
}
ArrayList becameIdle = null;
// UidRecord
if (mLocalPowerManager != null) {
mLocalPowerManager.startUidChanges();
}
for (int i=mActiveUids.size()-1; i>=0; i--) {
......
}
if (mLocalPowerManager != null) {
mLocalPowerManager.finishUidChanges();
}
......
}
OOM Adjの更新プロセスは主に以下の作業を完了します.
次にupdateOomAdjLocked()のメモリ調整に関する部分を分析します.Androidはシステムメモリの状態を4段階に分け、以下のように定義しています.
Adj
Value
Comments
ADJ_MEM_FACTOR_NORMAL
0
システムメモリは正常で、調整する必要はありません
ADJ_MEM_FACTOR_MODERATE
1
システムメモリは中程度で、正常な状態より低い
ADJ_MEM_FACTOR_LOW
2
システムメモリが低いので、メモリを回収する必要があります.
ADJ_MEM_FACTOR_CRITICAL
3
システムのメモリが不足しているので、メモリを回収しなければなりません.
ComponentCallbacks 2では、メモリ回収のレベルも定義されています.最初の3つはバックグラウンドキャッシュの回収レベル、後の3つはプロセス実行時の回収レベルです.
Adj
Value
Comments
TRIM_MEMORY_COMPLETE
80
バックグラウンドLRUリストの末尾にあるプロセスは、より多くのメモリが見つからない場合、すぐに殺されます.
TRIM_MEMORY_MODERATE
60
バックグラウンドLRUリストの中央にあるプロセスでは、メモリをクリーンアップすることで、後続のプロセスのパフォーマンスが向上します.
TRIM_MEMORY_BACKGROUND
40
バックグラウンドプロセスは、LRUリストの先頭にあり、メモリをクリーンアップすることで、プロセスをより効率的にフロントに戻すことができます.
TRIM_MEMORY_UI_HIDDEN
20
プロセスUIが表示されなくなり、UIリソースを解放できます.
TRIM_MEMORY_RUNNING_CRITICAL
15
デバイスは低メモリで動作しており、バックグラウンドプロセスの生存を保証できません.重要でないリソースをできるだけ解放する必要があります.次にonLowMemory()を呼び出してシステムのメモリが低く、ユーザーに顕著な影響を及ぼしていることを報告します.
TRIM_MEMORY_RUNNING_LOW
10
デバイスが低メモリで動作しているため、不要なリソースを解放する必要があります.
TRIM_MEMORY_RUNNING_MODERATE
5
デバイスの動作メモリが低いため、不要なリソースを解放する必要がある場合があります.
Androidシステムは、バックグラウンドキャッシュプロセスとemptyプロセスの数に応じてメモリレベルを区別します.システムは常にバックグラウンドプロセスをできるだけ多く保持しているため、プロセスの再起動時に起動時間を減らすことができ、ユーザー体験がより良い.しかし,システムメモリが不足するとlowmemeorykillerメカニズムが重要でないバックグラウンドプロセスを優先的に殺すため,バックグラウンドプロセスの数はlowmemrorykillerのトリガに関連していると考えられる.残りのバックグラウンドプロセスが少ないほど、Lowmemroykillerによって回収されるメモリが多いほど、システム全体のメモリが緊張することを示します.
final void updateOomAdjLocked() {
......
// empty
final int numCachedAndEmpty = numCached + numEmpty;
int memFactor;
// cache empty TRIM ,
// CUR_TRIM_EMPTY_PROCESSES=8,CUR_TRIM_CACHED_PROCESSES=5
if (numCached <= mConstants.CUR_TRIM_CACHED_PROCESSES
&& numEmpty <= mConstants.CUR_TRIM_EMPTY_PROCESSES) {
if (numCachedAndEmpty <= ProcessList.TRIM_CRITICAL_THRESHOLD) {
// cache+empty 3 ,
memFactor = ProcessStats.ADJ_MEM_FACTOR_CRITICAL;
} else if (numCachedAndEmpty <= ProcessList.TRIM_LOW_THRESHOLD) {
// cache+empty 5 ,
memFactor = ProcessStats.ADJ_MEM_FACTOR_LOW;
} else {
//
memFactor = ProcessStats.ADJ_MEM_FACTOR_MODERATE;
}
} else {
memFactor = ProcessStats.ADJ_MEM_FACTOR_NORMAL;
}
......
mLastMemoryLevel = memFactor;
mLastNumProcesses = mLruProcesses.size();
// , true
boolean allChanged = mProcessStats.setMemFactorLocked(memFactor, !isSleepingLocked(), now);
final int trackerMemFactor = mProcessStats.getMemFactorLocked();
// ,
if (memFactor != ProcessStats.ADJ_MEM_FACTOR_NORMAL) {
if (mLowRamStartTime == 0) {
mLowRamStartTime = now;
}
int step = 0;
int fgTrimLevel;
// fgTrimLevel, ComponentCallbacks2
switch (memFactor) {
......
}
// factory, trimLevel
int factor = numTrimming/3;
int minFactor = 2;
if (mHomeProcess != null) minFactor++;
if (mPreviousProcess != null) minFactor++;
if (factor < minFactor) factor = minFactor;
// trimLevel,
int curLevel = ComponentCallbacks2.TRIM_MEMORY_COMPLETE;
// LRU
for (int i=N-1; i>=0; i--) {
ProcessRecord app = mLruProcesses.get(i);
......
// , HOME
if (app.curProcState >= ActivityManager.PROCESS_STATE_HOME
&& !app.killedByAm) {
// trimLevel ,
if (app.trimMemoryLevel < curLevel && app.thread != null) {
try {
app.thread.scheduleTrimMemory(curLevel);
} catch (RemoteException e) {
}
......
}
// trimLevel, factor :COMPLETE->MODERATE->BACKGROUND
app.trimMemoryLevel = curLevel;
step++;
if (step >= factor) {
......
}
} else if (app.curProcState == ActivityManager.PROCESS_STATE_HEAVY_WEIGHT
&& !app.killedByAm) {
// heavy weight TRIM_MEMORY_BACKGROUND
if (app.trimMemoryLevel < ComponentCallbacks2.TRIM_MEMORY_BACKGROUND
&& app.thread != null) {
try {
app.thread.scheduleTrimMemory(
ComponentCallbacks2.TRIM_MEMORY_BACKGROUND);
} catch (RemoteException e) {
}
}
app.trimMemoryLevel = ComponentCallbacks2.TRIM_MEMORY_BACKGROUND;
} else {
// UI , TRIM_MEMORY_UI_HIDDEN
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) {
try {
app.thread.scheduleTrimMemory(level);
} catch (RemoteException e) {
}
}
app.pendingUiClean = false;
}
// fgTrimLevel trimLevel , fgTrimLevel
if (app.trimMemoryLevel < fgTrimLevel && app.thread != null) {
try {
app.thread.scheduleTrimMemory(fgTrimLevel);
} catch (RemoteException e) {
}
}
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;
}
// UI TRIM_MEMORY_UI_HIDDEN
if ((app.curProcState >= ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND
|| app.systemNoUi) && app.pendingUiClean) {
if (app.trimMemoryLevel < ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN
&& app.thread != null) {
try {
app.thread.scheduleTrimMemory(
ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN);
} catch (RemoteException e) {
}
}
app.pendingUiClean = false;
}
app.trimMemoryLevel = 0;
}
}
......
}
メモリ調整の主な仕事は、プロセスを殺さずに、必要に応じてメモリを回収することです.
computeOomAdj
上でupdateOomAdjLocked()の大まかな流れを分析し、次にその中の重要な関数computeOomAdjLocked()の1つを分析し、OOM Adjをどのように計算するかを分析します.
private final boolean computeOomAdjLocked(ProcessRecord app, int cachedAdj,
ProcessRecord TOP_APP, boolean doingAll, long now) {
// Adj ,
if (mAdjSeq == app.adjSeq) {
......
}
// Adj
if (app.thread == null) {
......
}
......
// Adj FOREGROUND Adj, Persistent
if (app.maxAdj <= ProcessList.FOREGROUND_APP_ADJ) {
// Adj,SchedGroup,ProcState,UI
......
app.curAdj = app.maxAdj;
app.completedAdjSeq = app.adjSeq;
// Adj , Adj
return app.curAdj < prevAppAdj;
}
......
// Adj,SchedGroup,ProcState
if (PROCESS_STATE_CUR_TOP == ActivityManager.PROCESS_STATE_TOP && app == TOP_APP) {
//
......
} else if (app.runningRemoteAnimation) {
//
......
} else if (app.instr != null) {
//
......
} else if (isReceivingBroadcastLocked(app, mTmpBroadcastQueue)) {
//
......
} else if (app.executingServices.size() > 0) {
// Service
......
} else if (app == TOP_APP) {
// ,
......
} else {
//
......
}
// activities, Adj
if (!foregroundActivities && activitiesSize > 0) {
int minLayer = ProcessList.VISIBLE_APP_LAYER_MAX;
for (int j = 0; j < activitiesSize; j++) {
......
if (r.visible) {
// activity,Adj , VISIBLE
......
} else if (r.isState(ActivityState.PAUSING, ActivityState.PAUSED)) {
// activity ,Adj PERCEPTIBLE
......
} else if (r.isState(ActivityState.STOPPING)) {
// activity ,Adj PERCEPTIBLE
......
} else {
// cached-activity, procState
......
}
}
// activity Adj , Adj
if (adj == ProcessList.VISIBLE_APP_ADJ) {
adj += minLayer;
}
}
......
if (adj > ProcessList.PERCEPTIBLE_APP_ADJ
|| procState > ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE) {
// overylay UI ,Adj PERCEPTIBLE, procState
......
}
if (adj > ProcessList.PERCEPTIBLE_APP_ADJ
|| procState > ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND) {
// toasts,Adj PERCEPTIBLE
......
}
if (app == mHeavyWeightProcess) {
// ,Adj HEAVY_WEIGHT
......
}
if (app == mHomeProcess) {
// home ,Adj HOME
......
}
if (app == mPreviousProcess && app.activities.size() > 0) {
// ,Adj PREVIOUS
......
}
......
if (mBackupTarget != null && app == mBackupTarget.app) {
// , ,Adj BACKUP
......
}
......
// service Adj
for (int is = app.services.size()-1;
is >= 0 && (adj > ProcessList.FOREGROUND_APP_ADJ
|| schedGroup == ProcessList.SCHED_GROUP_BACKGROUND
|| procState > ActivityManager.PROCESS_STATE_TOP);
is--) {
ServiceRecord s = app.services.valueAt(is);
if (s.startRequested) {
// Unbounded Service
......
}
for (int conni = s.connections.size()-1;
conni >= 0 && (adj > ProcessList.FOREGROUND_APP_ADJ
|| schedGroup == ProcessList.SCHED_GROUP_BACKGROUND
|| procState > ActivityManager.PROCESS_STATE_TOP);
conni--) {
// Bounded Service
......
}
}
// ContentProvider
for (int provi = app.pubProviders.size()-1;
provi >= 0 && (adj > ProcessList.FOREGROUND_APP_ADJ
|| schedGroup == ProcessList.SCHED_GROUP_BACKGROUND
|| procState > ActivityManager.PROCESS_STATE_TOP);
provi--) {
ContentProviderRecord cpr = app.pubProviders.valueAt(provi);
......
}
// ContentProvider ,Adj PREVIOU
if (app.lastProviderTime > 0 &&
(app.lastProviderTime+mConstants.CONTENT_PROVIDER_RETAIN_TIME) > now) {
......
}
// services providers top ,
if (mayBeTop && procState > ActivityManager.PROCESS_STATE_TOP) {
......
}
// Cache ,
if (procState >= ActivityManager.PROCESS_STATE_CACHED_EMPTY) {
......
}
// service
if (adj == ProcessList.SERVICE_ADJ) {
......
}
......
return app.curAdj < prevAppAdj;
}
computeOomAdjLocked()はコード量が多く,論理が非常に複雑である.簡単に言えば,プロセスの様々な状態に応じて,Adj,schedGroup,procStateなどを調整する.ここは簡単に大まかな流れを引いただけで、細部は書いていません.多すぎます.
applyOomAdj
プロセスのOOM Adjを計算した後、Adj値をAndroid LowMemoryKiller(LMK)メカニズムに設定する必要があります.具体的なソースコードは以下の通りです.
private final boolean applyOomAdjLocked(ProcessRecord app, boolean doingAll, long now,
long nowElapsed) {
......
if (app.curAdj != app.setAdj) {
// curAdj LMK ,Adj Proc
ProcessList.setOomAdj(app.pid, app.uid, app.curAdj);
app.setAdj = app.curAdj;
app.verifiedAdj = ProcessList.INVALID_ADJ;
}
if (app.setSchedGroup != app.curSchedGroup) {
int oldSchedGroup = app.setSchedGroup;
app.setSchedGroup = app.curSchedGroup;
if (app.waitingToKill != null && app.curReceivers.isEmpty()
&& app.setSchedGroup == ProcessList.SCHED_GROUP_BACKGROUND) {
// ,
app.kill(app.waitingToKill, true);
success = false;
} else {
......
try {
// Group
setProcessGroup(app.pid, processGroup);
if (app.curSchedGroup == ProcessList.SCHED_GROUP_TOP_APP) {
// Group TOP TOP , UI Render 。
// RT , -10。
......
} else if (oldSchedGroup == ProcessList.SCHED_GROUP_TOP_APP &&
app.curSchedGroup != ProcessList.SCHED_GROUP_TOP_APP) {
// Group TOP TOP , UI Render 。
// SCHED_OTHER, 0。
......
} catch (Exception e) {
......
}
}
// activities ProcessState
......
if (app.setProcState == ActivityManager.PROCESS_STATE_NONEXISTENT
|| ProcessList.procStatesDifferForMem(app.curProcState, app.setProcState)) {
// PSS
......
} else {
// , PSS
......
}
if (app.setProcState != app.curProcState) {
//
......
} else if (app.reportedInteraction && (nowElapsed-app.interactionEventTime)
> mConstants.USAGE_STATS_INTERACTION_INTERVAL) {
// ,
maybeUpdateUsageStatsLocked(app, nowElapsed);
}
// activities , 。
if (changes != 0) {
......
}
return success;
}
applyOomAdjLocked()はLMKのAdj値を設定するだけでなく、TOPプロセスのスケジューリングポリシーや優先度の調整、PSSデータの収集、ステータス変更ブロードキャストの送信などの作業も完了している.