ソースコードベース: Android R
0. 序文
ブログ記事「oom_adj メモリ水位アルゴリズムの分析」では、 lmkd における oom_adj メモリ水位の計算と使用方法について詳細に分析しています。ブログ記事「oom_adj 更新原則 (1)」および「oom_adj 更新原則 (2)」では、 )」では、 Android システムが詳細に分析されています。oom_adj の更新原理が詳細に分析されています。これらのいくつかのブログ投稿を通じて、oom_adj についての理解が深まりました。
前回のブログ投稿に基づいて、この記事ではコードの詳細を分析し、各 oom_adj の値を詳細に解釈します。
1. 調整レベル
まず、これまでのブログ投稿と同様に、oom_adj の値を列挙します。以下、各 oom_adj の値を個別に説明します。
フレームワーク/base/services/core/java/com/android/server/am/ProcessList.java
ADJレベル | 価値 | 説明する |
不明_ADJ | 1001 | 特定の場所で使用され、通常はキャッシュ プロセスを指します。正確な値は不明です |
CACHED_APP_MAX_ADJ | 999 | 干渉せずに強制終了できる、目に見えないプロセスの最大値 |
CACHED_APP_LMK_FIRST_ADJ | 950 | oom_adj 強制終了が許可される最初のレベルは、CACHED_APP_MAX_ADJ と等しくすることはできません。 |
CACHED_APP_MIN_ADJ | 900 | 非表示プロセスの最小値 |
SERVICE_B_ADJ | 800 | B リストのサービス (古い、使用される可能性が低い) |
PREVIOUS_APP_ADJ | 700 | 前のアプリのプロセス (多くの場合リターンキーを押すことによる) |
HOME_APP_ADJ | 600 | ホームプロセス |
サービス_ADJ | 500 | アプリサービスプロセスを強制終了すると、通常は大きな影響はありません |
HEAVY_WEIGHT_APP_ADJ | 400 | バックグラウンドでの重量プロセス、system/rootdir/init.rc ファイルでの起動 |
BACKUP_APP_ADJ | 300 | プロセスをバックアップします。プロセスを強制終了するのは、致命的ではありませんが、悪いことです。 |
PERCEPTIBLE_LOW_APP_ADJ | 250 | ユーザーやシステムに束縛されたプロセスはサービスよりも重要ですが、強制終了されてもすぐに顧客の感覚に影響を与えるわけではありません。 |
PERCEPTIBLE_APP_ADJ | 200 | BGM の再生などの知覚可能なプロセス |
VISIBLE_APP_ADJ | 100 | 視覚プロセス |
PERCEPTIBLE_RECENT_FOREGROUND_APP_ADJ | 50 | 最近TOPプロセス |
FOREGROUND_APP_ADJ | 0 | フォアグラウンドプロセス |
PERSISTENT_SERVICE_ADJ | -700 | システム関連プロセスまたは常駐プロセス |
PERSISTENT_PROC_ADJ | -800 | 電話などのシステム常駐プロセス 間違いなく殺人を目的としたものではありませんが、完全に致命的ではありません |
SYSTEM_ADJ | -900 | システムプロセス |
NATIVE_ADJ | -1000 | ネイティブプロセスはシステムによって管理されないため、oom_adj の適応はありません。 |
2.ADJ < 0
adj 分類では、FOREGROUND_APP_ADJ の値は 0 であり、adj を所有するプロセスがフォアグラウンド プロセスです。システムは、0 未満の値を持つプロセスをシステム内で重要なプロセスであるとみなします。次のように:
- NATIVE_ADJ(-1000):これは init プロセスによってフォークされたネイティブ プロセスであり、システムによって制御されません。
- SYSTEM_ADJ(-900): system_server プロセスを指します。
- PERSISTENT_PROC_ADJ(-800): AndroidManifest.xml で android:persistent を true として宣言するシステム プロセス (つまり、FLAG_SYSTEM タグを含む) を指します。永続プロセスは通常の状況では強制終了されず、強制終了されたりクラッシュが発生したりした場合でも、システムはすぐにプロセスを再起動します。
- PERSISTENT_SERVICE_ADJ(-700):これは、関数 startIsolatedProcess() によって開始されたプロセス、または system_server または永続プロセス (および BIND_ABOVE_CLIENT または BIND_IMPORTANT) によってバインドされたサービス プロセスです。
2.1 SYSTEM_ADJ(-900)
SYSTEM_ADJ は、system_server プロセスのみを指します。AMS.setSystemProcess() は SystemServer.startBootstrapServices() 中に呼び出され、この関数で system_server の maxAdj がSYSTEM_ADJに設定されます。
frameworks/base/services/core/java/com/android/server/am/AMS.java
public void setSystemProcess() {
try {
...
synchronized (this) {
ProcessRecord app = mProcessList.newProcessRecordLocked(info, info.processName,
false,
0,
new HostingRecord("system"));
app.setPersistent(true);
app.pid = app.mPidForCompact = MY_PID;
app.getWindowProcessController().setPid(MY_PID);
app.maxAdj = ProcessList.SYSTEM_ADJ; //----这里设定system_server 的 maxAdj
app.makeActive(mSystemThread.getApplicationThread(), mProcessStats);
addPidLocked(app);
mProcessList.updateLruProcessLocked(app, false, null);
updateOomAdjLocked(OomAdjuster.OOM_ADJ_REASON_NONE);
}
}
...
}
updateOomAdjLocked() 関数を呼び出すと、パラメーターが渡されます。ブログ記事「oom_adj 更新の原則 (2)」の computeOomAdjLocked()から:
frameworks/base/services/core/java/com/android/server/am/OomAdjuster.java
if (app.maxAdj <= ProcessList.FOREGROUND_APP_ADJ) {
...
app.curAdj = app.maxAdj;
...
}
最終的な system_server プロセスの adj は -900 に設定されており、これは dumpsys meminfo からも確認できます。
153,028K: System
153,028K: system (pid 1143 / adj -900)
2.2 PERSISTENT_PROC_ADJ(-800)
PERSISTENT_PROC_ADJのプロセスは、 AndroidManifest.xml でandroid:persistent属性を true としてシステム (FLAG_SYSTEM を使用) プロセスを宣言する必要があります (永続プロセスとも呼ばれます)。永続プロセスは通常の状況では強制終了されず、強制終了されるかクラッシュが発生すると、システムはすぐにプロセスを再起動します。
場所を設定:
- プロセスリスト。newProcessRecordLocked();
- アムス。addAppLocked();
newProcessRecordLocked() は、前のセクションで説明した setSystemProcess() 関数などの system_server プロセスを含む、新しいアプリケーションの起動プロセス中に呼び出されます。
frameworks/base/services/core/java/com/android/server/am/AMS.java
public void setSystemProcess() {
try {
...
synchronized (this) {
ProcessRecord app = mProcessList.newProcessRecordLocked(info, info.processName,
false,
0,
new HostingRecord("system"));
app.setPersistent(true);
app.pid = app.mPidForCompact = MY_PID;
app.getWindowProcessController().setPid(MY_PID);
app.maxAdj = ProcessList.SYSTEM_ADJ; //----这里设定system_server 的 maxAdj
app.makeActive(mSystemThread.getApplicationThread(), mProcessStats);
addPidLocked(app);
mProcessList.updateLruProcessLocked(app, false, null);
updateOomAdjLocked(OomAdjuster.OOM_ADJ_REASON_NONE);
}
}
...
}
コードの最初の文は、 newProcessRecordLocked()関数を通じて ProcessRecord オブジェクトを作成することです。
この関数を見てみましょう:
frameworks/base/services/core/java/com/android/server/am/ProcessList.java
final ProcessRecord newProcessRecordLocked(ApplicationInfo info, String customProcess,
boolean isolated, int isolatedUid, HostingRecord hostingRecord) {
String proc = customProcess != null ? customProcess : info.processName;
final int userId = UserHandle.getUserId(info.uid);
int uid = info.uid;
if (isolated) {
...
}
final ProcessRecord r = new ProcessRecord(mService, info, proc, uid);
if (!mService.mBooted && !mService.mBooting
&& userId == UserHandle.USER_SYSTEM
&& (info.flags & PERSISTENT_MASK) == PERSISTENT_MASK) {
// The system process is initialized to SCHED_GROUP_DEFAULT in init.rc.
r.setCurrentSchedulingGroup(ProcessList.SCHED_GROUP_DEFAULT);
r.setSchedGroup = ProcessList.SCHED_GROUP_DEFAULT;
r.setPersistent(true);
r.maxAdj = ProcessList.PERSISTENT_PROC_ADJ;
}
if (isolated && isolatedUid != 0) {
// Special case for startIsolatedProcess (internal only) - assume the process
// is required by the system server to prevent it being killed.
r.maxAdj = ProcessList.PERSISTENT_SERVICE_ADJ;
}
addProcessNameLocked(r);
return r;
}
system_server の起動時にのみPERSISTENT_PROC_ADJに設定されることは関数からわかりますが、setSystemProcess() の終了時に system_server の maxAdj が SYSTEM_ADJ に変更されます。
プロセスが分離されている場合、maxAdj は PERSISTENT_SERVICE_ADJ に設定されます。詳細については、セクション2.3を参照してください。
別の関数 addAppLocked() を見てみましょう。
frameworks/base/services/core/java/com/android/server/am/AMS.java
final ProcessRecord addAppLocked(ApplicationInfo info, String customProcess, boolean isolated,
boolean disableHiddenApiChecks, boolean disableTestApiChecks,
boolean mountExtStorageFull, String abiOverride, int zygotePolicyFlags) {
ProcessRecord app;
if (!isolated) {
app = getProcessRecordLocked(customProcess != null ? customProcess : info.processName,
info.uid, true);
} else {
app = null;
}
if (app == null) {
app = mProcessList.newProcessRecordLocked(info, customProcess, isolated, 0,
new HostingRecord("added application",
customProcess != null ? customProcess : info.processName));
mProcessList.updateLruProcessLocked(app, false, null);
updateOomAdjLocked(app, OomAdjuster.OOM_ADJ_REASON_PROCESS_BEGIN);
}
...
if ((info.flags & PERSISTENT_MASK) == PERSISTENT_MASK) {
app.setPersistent(true);
app.maxAdj = ProcessList.PERSISTENT_PROC_ADJ;
}
if (app.thread == null && mPersistentStartingProcesses.indexOf(app) < 0) {
mPersistentStartingProcesses.add(app);
mProcessList.startProcessLocked(app, new HostingRecord("added application",
customProcess != null ? customProcess : app.processName),
zygotePolicyFlags, disableHiddenApiChecks, disableTestApiChecks,
mountExtStorageFull, abiOverride);
}
return app;
}
アプリケーション フラグが FLAG_SYSTEM | FLAG_PERSISTENT に設定されている場合、maxAdj の値は PERSISENT_PROC_ADJ に設定されます。
SystemServer が startOtherServices() を開始すると、ブート フェーズを完了するために AMS.systemReady() が呼び出されます。startPersistentApps () はここで呼び出されます。
frameworks/base/services/core/java/com/android/server/am/AMS.java
void startPersistentApps(int matchFlags) {
if (mFactoryTest == FactoryTest.FACTORY_TEST_LOW_LEVEL) return;
synchronized (this) {
try {
final List<ApplicationInfo> apps = AppGlobals.getPackageManager()
.getPersistentApplications(STOCK_PM_FLAGS | matchFlags).getList();
for (ApplicationInfo app : apps) {
if (!"android".equals(app.packageName)) {
addAppLocked(app, null, false, null /* ABI override */,
ZYGOTE_POLICY_FLAG_BATCH_LAUNCH);
}
}
} catch (RemoteException ex) {
}
}
}
ここでは、システムの永続プロセスがロードされ、addAppLocked() 関数が呼び出されます。
2.3 PERSISTENT_SERVICE_ADJ(-700)
PERSISTENT_SERVICE_ADJ のプロセスは、startIsolatedProcess() によって開始されるプロセス、または system_server によってバインドされるサービス プロセスまたは永続プロセスです。
前回の記事 newProcessRecordLocked()で、プロセスが分離されると maxAdj が PERSISTENT_SERVICE_ADJ に設定され、 newProcessRecordLocked() によってトリガーされるプロセスは次のとおりであると述べました。
AMS.startIsolatedProcess() -> ProcessList.startProcessLocked() -> newProcessRecordLocked()
もう 1 つは、updateOomAdjLocked() で computeOomAdjLocked() を呼び出すことです。
frameworks/base/services/core/java/com/android/server/am/OomAdjuster.java
private final boolean computeOomAdjLocked(ProcessRecord app, int cachedAdj,
ProcessRecord topApp, boolean doingAll, long now, boolean cycleReEval,
boolean computeClients) {
...
int capabilityFromFGS = 0; // capability from foreground service.
for (int is = app.numberOfRunningServices() - 1;
is >= 0 && (adj > ProcessList.FOREGROUND_APP_ADJ
|| schedGroup == ProcessList.SCHED_GROUP_BACKGROUND
|| procState > PROCESS_STATE_TOP);
is--) {
ServiceRecord s = app.getRunningServiceAt(is);
...
ArrayMap<IBinder, ArrayList<ConnectionRecord>> serviceConnections = s.getConnections();
for (int conni = serviceConnections.size() - 1;
conni >= 0 && (adj > ProcessList.FOREGROUND_APP_ADJ
|| schedGroup == ProcessList.SCHED_GROUP_BACKGROUND
|| procState > PROCESS_STATE_TOP);
conni--) {
ArrayList<ConnectionRecord> clist = serviceConnections.valueAt(conni);
for (int i = 0;
i < clist.size() && (adj > ProcessList.FOREGROUND_APP_ADJ
|| schedGroup == ProcessList.SCHED_GROUP_BACKGROUND
|| procState > PROCESS_STATE_TOP);
i++) {
...
int clientAdj = client.getCurRawAdj();
int clientProcState = client.getCurRawProcState();
if ((cr.flags & Context.BIND_WAIVE_PRIORITY) == 0) {
...
if (adj > clientAdj) {
if (app.hasShownUi && !app.getCachedIsHomeProcess()
&& clientAdj > ProcessList.PERCEPTIBLE_APP_ADJ) {
if (adj >= ProcessList.CACHED_APP_MIN_ADJ) {
adjType = "cch-bound-ui-services";
}
} else {
int newAdj;
if ((cr.flags&(Context.BIND_ABOVE_CLIENT
|Context.BIND_IMPORTANT)) != 0) {
if (clientAdj >= ProcessList.PERSISTENT_SERVICE_ADJ) {
newAdj = clientAdj;
} else {
newAdj = ProcessList.PERSISTENT_SERVICE_ADJ;
...
}
}
現在のプロセスがクライアントにバインドされており、現在のプロセスの調整優先度がクライアントの優先度ほど高くない場合は、BIND_ABOVE_CLIENT フラグまたは BIND_IMPORTANT フラグが設定されているかどうかを確認します。
3. FOREGROUND_APP_ADJ(0)
シナリオ 1:次の条件のいずれかを満たすプロセスは、FOREGROUND_APP_ADJ(0) 優先度に属します。
- 再開された状態のアクティビティ
- ライフサイクル コールバックを実行しているサービス (onCreate、onStartCommand、onDestroy などの実行)
- onReceive() を実行する BroadcastReceiver
- startInstrumentation() によってプロセスが開始されました
詳細なコードについては、ブログ投稿「oom_adj Update Principle (2)」の computeOomAdjLocked()を参照してください。
frameworks/base/services/core/java/com/android/server/am/OomAdjuster.java
private final boolean computeOomAdjLocked(ProcessRecord app, int cachedAdj,
ProcessRecord topApp, boolean doingAll, long now, boolean cycleReEval,
boolean computeClients) {
...
boolean foregroundActivities = false;
if (PROCESS_STATE_CUR_TOP == PROCESS_STATE_TOP && app == topApp) {
// The last app on the list is the foreground app.
adj = ProcessList.FOREGROUND_APP_ADJ;
...
} else if (app.runningRemoteAnimation) {
adj = ProcessList.VISIBLE_APP_ADJ;
...
} else if (app.getActiveInstrumentation() != null) {
adj = ProcessList.FOREGROUND_APP_ADJ;
...
} else if (app.getCachedIsReceivingBroadcast(mTmpBroadcastQueue)) {
adj = ProcessList.FOREGROUND_APP_ADJ;
...
} else if (app.executingServices.size() > 0) {
adj = ProcessList.FOREGROUND_APP_ADJ;
...
} else if (app == topApp) {
adj = ProcessList.FOREGROUND_APP_ADJ;
...
} else {
procState = PROCESS_STATE_CACHED_EMPTY;
...
}
シナリオ 2: クライアント プロセス アクティビティで bindingService() メソッドが呼び出され、フラグに BIND_ADJUST_WITH_ACTIVITY パラメータが含まれ、アクティビティが表示されると、現在のサービス プロセスもフォアグラウンド プロセスに属します。ソース コードは次のとおりです。
frameworks/base/services/core/java/com/android/server/am/OomAdjuster.java
private final boolean computeOomAdjLocked(ProcessRecord app, int cachedAdj,
ProcessRecord topApp, boolean doingAll, long now, boolean cycleReEval,
boolean computeClients) {
...
final ActivityServiceConnectionsHolder a = cr.activity;
if ((cr.flags&Context.BIND_ADJUST_WITH_ACTIVITY) != 0) {
if (a != null && adj > ProcessList.FOREGROUND_APP_ADJ
&& a.isActivityVisible()) {
adj = ProcessList.FOREGROUND_APP_ADJ;
app.setCurRawAdj(adj);
シナリオ 3: プロバイダー プロセスの場合、フォアグラウンド プロセスになるには次の 2 つの条件があります。
- プロバイダーのクライアント プロセス ADJ<=FOREGROUND_APP_ADJ の場合、プロバイダー プロセス ADJ は FOREGROUND_APP_ADJ と等しくなります。
- プロバイダーに外部 (フレームワーク以外) プロセスの依存関係がある場合、つまり getContentProviderExternal() メソッドが呼び出される場合、ADJ は少なくとも FOREGROUND_APP_ADJ と等しくなります。
4. VISIBLE_APP_ADJ(100)
可視プロセス: ActivityRecord のvisible=trueの場合、それはアクティビティに可視のプロセスです。
Android P 以降、ADJ レベルはさらに洗練され、 VISIBLE_APP_LAYER_MAX (99)が追加されています 。これは、VISIBLE_APP_ADJ (100) と PERCEPTIBLE_APP_ADJ (200) の間に 99 個のスロットがあることを意味します。可視レベル ADJ の値の範囲は [100,199] です。アルゴリズムは、その ADJ が配置されているタスクの mLayerRank に従って調整します。100 プラス mLayerRank がターゲット ADJ と等しくなります。レイヤーが大きいほど、ADJ は小さくなります。
TaskRecordのmLayerRankの計算方法は、updateOomAdjLocked()処理内でASSのrankTaskLayersIfNeeded()メソッドを呼び出すことになります。
TaskRecord の先頭にある ActivityRecord が空、終了している、または非表示の場合、TaskRecord の mLayerRank を -1 に設定します。各 ActivityDisplay の BaseLayer は 0 から始まり、先頭の TaskRecord から始まり、最初の ADJ=100、Add から始まります。上から1まで199が上限となります。
5. PERCEPTIBLE_APP_ADJ(200)
認識可能なプロセス: プロセスに非表示のアクティビティがあるが、そのアクティビティが PAUSING、PAUSED、または STOPPING 状態にある場合、それは PERCEPTIBLE_APP_ADJ です。
computeOomAdjLocked () 関数には、認識プロセス用の特別な計算もあります。
frameworks/base/services/core/java/com/android/server/am/OomAdjuster.java
private final boolean computeOomAdjLocked(ProcessRecord app, int cachedAdj,
ProcessRecord topApp, boolean doingAll, long now, boolean cycleReEval,
boolean computeClients) {
...
/********* 场景 1 **********/
// Examine all activities if not already foreground.
if (!foregroundActivities && app.getCachedHasActivities()) {
app.computeOomAdjFromActivitiesIfNecessary(mTmpComputeOomAdjWindowCallback,
adj, foregroundActivities, procState, schedGroup, appUid, logUid,
PROCESS_STATE_CUR_TOP);
adj = app.mCachedAdj;
...
}
...
/********* 场景 2 **********/
if (adj > ProcessList.PERCEPTIBLE_APP_ADJ
|| procState > PROCESS_STATE_FOREGROUND_SERVICE) {
if (app.hasForegroundServices()) {
// The user is aware of this app, so make it visible.
adj = ProcessList.PERCEPTIBLE_APP_ADJ;
procState = PROCESS_STATE_FOREGROUND_SERVICE;
app.adjType = "fg-service";
app.setCached(false);
schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
} else if (app.hasOverlayUi()) {
// The process is display an overlay UI.
adj = ProcessList.PERCEPTIBLE_APP_ADJ;
procState = PROCESS_STATE_IMPORTANT_FOREGROUND;
app.setCached(false);
app.adjType = "has-overlay-ui";
schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
}
}
...
/********* 场景 3 **********/
if (adj > ProcessList.PERCEPTIBLE_APP_ADJ
|| procState > PROCESS_STATE_TRANSIENT_BACKGROUND) {
if (app.forcingToImportant != null) {
adj = ProcessList.PERCEPTIBLE_APP_ADJ;
procState = PROCESS_STATE_TRANSIENT_BACKGROUND;
app.setCached(false);
app.adjType = "force-imp";
app.adjSource = app.forcingToImportant;
schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
}
}
シナリオ 1:フォアグラウンド プロセスではなく、キャッシュ アクティビティが存在する場合は、引き続き adj を決定する必要があります。
computeOomAdjFromActivitiesIfNecessary() を呼び出します。ここでは、oom_adj を計算するときにコールバックが渡され、アクティビティが表示状態 (PAUSING、STOPPING、またはその他の状態) にあるかどうかを確認するためにウィンドウが使用され、コールバックに対応するコールバック関数がそれに応じて呼び出されます。状態に。
- 可視: adj が VISIBLE_APP_ADJ より大きい場合、VISIBLE_APP_ADJ に戻されます。
- 一時停止: adj が PERCEPTIBLE_APP_ADJ より大きい場合、PERCEPTIBLE_APP_ADJ に戻されます。
- 停止: adj が PERCEPTIBLE_APP_ADJ より大きい場合、PERCEPTIBLE_APP_ADJ に戻されます。
シナリオ 2:プロセスにフォアグラウンド サービスがあるか、プロセスがオーバーレイ UI を使用する
価格調整の前提条件は、プロセスの重要性が知覚可能なレベルを下回っているか、プロセスのステータス レベルがフォアグラウンド サービスよりも高いことです。
フォアグラウンド サービスを使用するには、startForegroundService() 関数を実行します。
hasOverlayUi() は true で、表示タイプ TYPE_APPLICATION_OVERLAY のウィンドウなど、非アクティビティ UI が画面の上部にあることを示します。
シナリオ 3:プロセス forcingTo important が空ではありません
この値は null 以外で、トースト ポップアップ プロセスなどの setProcessMinimum() 関数が実行されたことを示します。
6.BACKUP_APP_ADJ(300)
frameworks/base/services/core/java/com/android/server/am/OomAdjuster.java
private final boolean computeOomAdjLocked(ProcessRecord app, int cachedAdj,
ProcessRecord topApp, boolean doingAll, long now, boolean cycleReEval,
boolean computeClients) {
...
final BackupRecord backupTarget = mService.mBackupTargets.get(app.userId);
if (backupTarget != null && app == backupTarget.app) {
// If possible we want to avoid killing apps while they're being backed up
if (adj > ProcessList.BACKUP_APP_ADJ) {
if (DEBUG_BACKUP) Slog.v(TAG_BACKUP, "oom BACKUP_APP_ADJ for " + app);
adj = ProcessList.BACKUP_APP_ADJ;
if (procState > PROCESS_STATE_TRANSIENT_BACKGROUND) {
procState = PROCESS_STATE_TRANSIENT_BACKGROUND;
}
app.adjType = "backup";
app.setCached(false);
}
if (procState > ActivityManager.PROCESS_STATE_BACKUP) {
procState = ActivityManager.PROCESS_STATE_BACKUP;
app.adjType = "backup";
}
}
前提条件は、backupTarget が空ではないことです。
- bindBackupAgent() プロセスを実行し、mBackupTarget 値を設定します。
- clearPendingBackup() または unbindBackupAgent() プロセスを実行し、mBackupTarget 値を空にします。
7. HEAVY_WEIGHT_APP_ADJ(400)
frameworks/base/services/core/java/com/android/server/am/OomAdjuster.java
private final boolean computeOomAdjLocked(ProcessRecord app, int cachedAdj,
ProcessRecord topApp, boolean doingAll, long now, boolean cycleReEval,
boolean computeClients) {
...
//重量级后台进程,把adj和proc_state都拉回到 heavy weight水平
if (app.getCachedIsHeavyWeight()) {
if (adj > ProcessList.HEAVY_WEIGHT_APP_ADJ) {
// We don't want to kill the current heavy-weight process.
adj = ProcessList.HEAVY_WEIGHT_APP_ADJ;
schedGroup = ProcessList.SCHED_GROUP_BACKGROUND;
app.setCached(false);
app.adjType = "heavy";
}
if (procState > ActivityManager.PROCESS_STATE_HEAVY_WEIGHT) {
procState = ActivityManager.PROCESS_STATE_HEAVY_WEIGHT;
app.adjType = "heavy";
}
}
- realStartActivityLocked() プロセスでは、アプリケーションの privateFlags が PRIVATE_FLAG_CANT_SAVE_STATE を識別すると、mHeavyWeightProcess 値を設定します。
- finishHeavyWeightApp()、空の mHeavyWeightProcess 値。
8. HOME_APP_ADJ(600)
frameworks/base/services/core/java/com/android/server/am/OomAdjuster.java
private final boolean computeOomAdjLocked(ProcessRecord app, int cachedAdj,
ProcessRecord topApp, boolean doingAll, long now, boolean cycleReEval,
boolean computeClients) {
...
//HOME 进程,将其拉回HOME_APP_ADJ
if (app.getCachedIsHomeProcess()) {
if (adj > ProcessList.HOME_APP_ADJ) {
// This process is hosting what we currently consider to be the
// home app, so we don't want to let it go into the background.
adj = ProcessList.HOME_APP_ADJ;
schedGroup = ProcessList.SCHED_GROUP_BACKGROUND;
app.setCached(false);
app.adjType = "home";
}
if (procState > ActivityManager.PROCESS_STATE_HOME) {
procState = ActivityManager.PROCESS_STATE_HOME;
app.adjType = "home";
}
}
mHomeProcess は、デスクトップ APP など、タイプ ACTIVITY_TYPE_HOME のアプリケーションが開始されるときに設定されます。
9. PREVIOUS_APP_ADJ(700)
frameworks/base/services/core/java/com/android/server/am/OomAdjuster.java
private final boolean computeOomAdjLocked(ProcessRecord app, int cachedAdj,
ProcessRecord topApp, boolean doingAll, long now, boolean cycleReEval,
boolean computeClients) {
...
/********* 场景 1 **********/
if (app.getCachedIsPreviousProcess() && app.getCachedHasActivities()) {
if (adj > ProcessList.PREVIOUS_APP_ADJ) {
// This was the previous process that showed UI to the user.
// We want to try to keep it around more aggressively, to give
// a good experience around switching between two apps.
adj = ProcessList.PREVIOUS_APP_ADJ;
schedGroup = ProcessList.SCHED_GROUP_BACKGROUND;
app.setCached(false);
app.adjType = "previous";
}
if (procState > PROCESS_STATE_LAST_ACTIVITY) {
procState = PROCESS_STATE_LAST_ACTIVITY;
app.adjType = "previous";
}
}
...
/********* 场景 2 **********/
if (app.lastProviderTime > 0 &&
(app.lastProviderTime + mConstants.CONTENT_PROVIDER_RETAIN_TIME) > now) {
if (adj > ProcessList.PREVIOUS_APP_ADJ) {
adj = ProcessList.PREVIOUS_APP_ADJ;
schedGroup = ProcessList.SCHED_GROUP_BACKGROUND;
app.setCached(false);
app.adjType = "recent-provider";
}
if (procState > PROCESS_STATE_LAST_ACTIVITY) {
procState = PROCESS_STATE_LAST_ACTIVITY;
app.adjType = "recent-provider";
}
}
computeOomAdjLocked() 関数を使用する場合、2 つのシナリオがあります。
シナリオ 1: UI を含むユーザーが使用する最後のプロセス 2 つの APP 間の切り替えエクスペリエンスをユーザーに向上させるために、前のプロセスの ADJ は PREVIOUS_APP_ADJ のレベルに設定されます。activityStoppedLocked() プロセスが前のアプリケーションを更新するとき。
シナリオ 2: プロバイダー プロセスが最後に使用された時間が 20 秒以内の場合、優先度は PREVIOUS_APP_ADJ より低くなりません。プロバイダー プロセスは Android 7.0 以降に追加された新しいロジックで、メモリが比較的少ない場合にプロバイダーを所有するプロセスの乱流、つまり起動後に強制終了されてプルされるのを避けることができるという利点があります。