privatefinalintcomputeOomAdjLocked(ProcessRecord app, int cachedAdj, ProcessRecord TOP_APP, boolean doingAll, long now) { ... app.systemNoUi = false;
// Determine the importance of the process, starting with most // important to least, and assign an appropriate OOM adjustment. int adj; int schedGroup; int procState; booleanforegroundActivities=false; BroadcastQueue queue; if (app == TOP_APP) { // The last app on the list is the foreground app. // 列表中的最后一个应用程序是前台应用程序,这取决于用户的操作,我们无法干预。 adj = ProcessList.FOREGROUND_APP_ADJ; schedGroup = Process.THREAD_GROUP_DEFAULT; app.adjType = "top-activity"; foregroundActivities = true; procState = ActivityManager.PROCESS_STATE_TOP; } elseif (app.instrumentationClass != null) { // Don't want to kill running instrumentation. // 这个case可以尝试,可将 app adj 值降低至 0 adj = ProcessList.FOREGROUND_APP_ADJ; schedGroup = Process.THREAD_GROUP_DEFAULT; app.adjType = "instrumentation"; procState = ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND; } elseif ((queue = isReceivingBroadcast(app)) != null) { // An app that is currently receiving a broadcast also // counts as being in the foreground for OOM killer purposes. // It's placed in a sched group based on the nature of the // broadcast as reflected by which queue it's active in. // 这个 case 要求 app 正在或将要接收广播,可以尝试但操作难度较高 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; } elseif (app.executingServices.size() > 0) { // An app that is currently executing a service callback also // counts as being in the foreground. // 一个正在执行代码的 Service 可将 adj 的值调整至 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; //Slog.i(TAG, "EXEC " + (app.execServicesFg ? "FG" : "BG") + ": " + app); } else { // As far as we know the process is empty. We may change our mind later. schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE; // At this point we don't actually know the adjustment. Use the cached adj // value that the caller wants us to. adj = cachedAdj; procState = ActivityManager.PROCESS_STATE_CACHED_EMPTY; app.cached = true; app.empty = true; app.adjType = "cch-empty"; } // Examine all activities if not already foreground. if (!foregroundActivities && activitiesSize > 0) { for (intj=0; j < activitiesSize; j++) { finalActivityRecordr= app.activities.get(j); if (r.app != app) { Slog.w(TAG, "Wtf, activity " + r + " in proc activity list not using proc " + app + "?!?"); continue; } if (r.visible) { // App has a visible activity; only upgrade adjustment. // 维护一个用户不可见的 Activity 可以将应用的 adj 降低至 1 if (adj > ProcessList.VISIBLE_APP_ADJ) { adj = ProcessList.VISIBLE_APP_ADJ; app.adjType = "visible"; } if (procState > ActivityManager.PROCESS_STATE_TOP) { procState = ActivityManager.PROCESS_STATE_TOP; } schedGroup = Process.THREAD_GROUP_DEFAULT; app.cached = false; app.empty = false; foregroundActivities = true; break; } ... } } if (adj > ProcessList.PERCEPTIBLE_APP_ADJ) { // 维护一个前台 Service 可将 app adj值降低至 2. if (app.foregroundServices) { // The user is aware of this app, so make it visible. adj = ProcessList.PERCEPTIBLE_APP_ADJ; procState = ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND; app.cached = false; app.adjType = "fg-service"; schedGroup = Process.THREAD_GROUP_DEFAULT; } elseif (app.forcingToForeground != null) { // The user is aware of this app, so make it visible. adj = ProcessList.PERCEPTIBLE_APP_ADJ; procState = ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND; app.cached = false; app.adjType = "force-fg"; app.adjSource = app.forcingToForeground; schedGroup = Process.THREAD_GROUP_DEFAULT; } } ... } }
经过我们的分析,我们可以从以下几个方面尝试:
尝试在 Manifest 中注册一个 Instrumentation
尝试维护一个用户无法感知的 Activity
尝试维持一个前台 Service
其他还可以考虑永动机式的 Service 及不停的收发广播这两种变态的方案,在实践中考虑到对性能及的耗电量的影响,这两条并没有尝试。基于以上的分析可将 App 的 OOM_ADJ 的降低至 2,最低可以降低至 0。