Android oom_adj 更新原則 (1)

ソースコードベース: Android R

0. 序文

以前の 2 つのブログ投稿「lmkd メカニズムの詳細説明」「Oom_adj メモリ水位アルゴリズムの分析」によると、計算された min_score_adj に基づいて、この値より大きい oom_adj を持つプロセスが kill 処理の対象として選択されます。oom_adj の値はアプリケーションのステータスに応じて変化します。

この記事では、ソース コードを通じて oom_adj 更新の原理を分析します。

1. 形容詞の概念

Android システムの設計コンセプトは、ユーザー エクスペリエンスを向上させるために、アプリケーション プロセスができるだけ長く存続することを望んでいます。Android では、アプリケーションを初めて開くと時間がかかります。このプロセスには、プロセスの作成、アプリケーションの初期化、その他のアプリケーション ロジックなどが含まれます。そのため、アプリケーションが終了するとき、プロセスを直接終了したり強制終了されたりするわけではありませんが、は一定期間存続するため、次回起動するときにすぐに起動できるようになります。

もちろん、物事が極端に進んだ場合には、逆転する必要があります。多数のアプリケーションを起動すると、大量のメモリが使用され、それに応じて携帯電話のパフォーマンスが低下します。すべてのプロセスが存続できるようにすると、システム メモリが使い果たされてしまいます。したがって、Android では、adj とプロセス状態という 2 つの重要な標準を通じて測定される、合理的なリサイクル メカニズムが必要です。システムは、プロセスの形成状況に基づいて各プロセスの優先度調整値を決定し、一定の戦略に従って優先度の低いプロセスを選択して強制終了するなど、期待されるプロセスを再利用することでシステムの正常な動作を保証します。システムリソース。

2. 調整レベル

フレームワーク/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 の適応はありません。

3. 処理状況

ステータスレベル 価値 説明する
PROCESS_STATE_CACHED_EMPTY 19 プロセスはキャッシュされますが、空のプロセスです
PROCESS_STATE_CACHED_RECENT 18 プロセスはキャッシュされ、最近のタスクと通信するアクティビティが存在します。
PROCESS_STATE_CACHED_ACTIVITY_CLIENT 17 プロセスはキャッシュされ、他のアクティビティとともにキャッシュされたプロセスのクライアントになります。
PROCESS_STATE_CACHED_ACTIVITY 16 プロセスはキャッシュされ、アクティビティが含まれます
PROCESS_STATE_LAST_ACTIVITY 15 バックグラウンドプロセスを実行し、最後に表示されたアクティビティを所有します
PROCESS_STATE_HOME 14 バックグラウンドプロセスとホームアクティビティがあります
PROCESS_STATE_HEAVY_WEIGHT 13 バックグラウンドプロセスですが、復元は実行できないため、プロセスを強制終了しないようにしてください
PROCESS_STATE_TOP_SLEEPING 12 PROCESS_STATE_TOP と同じですが、デバイスはスリープ状態です
PROCESS_STATE_RECEIVER 11 バックグラウンドプロセスと受信機が実行中です
PROCESS_STATE_SERVICE 10 バックグラウンドプロセスとサービスが実行中です
PROCESS_STATE_BACKUP 9 バックグラウンドプロセス、バックアップ/復元操作の実行
PROCESS_STATE_TRANSIENT_BACKGROUND 8 実行し続ける必要がある短期間のバックグラウンド プロセス
PROCESS_STATE_IMPORTANT_BACKGROUND 7 ユーザーにとって重要であるにもかかわらず認識されていないプロセス
PROCESS_STATE_IMPORTANT_FOREGROUND 6 ユーザーにとって重要であり、認識できるプロセス
PROCESS_STATE_BOUND_FOREGROUND_SERVICE 5 プロセスにはフォアグラウンド サービスがあり、システムによってバインドされています
PROCESS_STATE_FOREGROUND_SERVICE 4 プロセスにはフォアグラウンド サービスがあります
PROCESS_STATE_BOUND_TOP 3 TOPアプリにバインドされたプロセス
PROCESS_STATE_TOP 2 プロセスは現在のトップアクティビティを所有しており、ユーザーに表示されます
PROCESS_STATE_PERSISTENT_UI 1 このプロセスは永続的なシステム プロセスであり、UI を実行します。
PROCESS_STATE_PERSISTENT 0 常驻的系统进程

4. 3个核心函数

oom_adj 涉及三个重要函数:

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

其中 computeOomAdjLocked()applyOomAdjLocked() 都是在 updateOomAdjLocked() 中调用到,代码位于 frameworks/base/services/core/java/com/android/server/am/OomAdjuster.java 中。

当四大组件状态改变时会通过 updateOomAdjLocked() 来同步更新相应进程的 ADJ 优先级。需要注意的是,当同一个进程有多个决定其优先级的组件状态时,取优先级最高的 ADJ 作为最终的 ADJ。另外,进程会通过设置 maxAdj 来限定ADJ 的上限。

5. updateOomAdjLocked() 简析

在上一节中我们得知 oom_adj 涉及三个重要的函数,源头都是 updateOomAdjLocked(),在详细剖析该函数之前先来了解下。

首先该接口的源头都位于 AMS 中,在AMS 中提供了三个接口:

frameworks/base/services/core/java/com/android/server/am/AMS.java

    final void updateOomAdjLocked(String oomAdjReason) {
        mOomAdjuster.updateOomAdjLocked(oomAdjReason);
    }

    final void updateOomAdjLocked(ProcessRecord app, String oomAdjReason) {
        mOomAdjuster.updateOomAdjLocked(app, oomAdjReason);
    }

    final boolean updateOomAdjLocked(ProcessRecord app, boolean oomAdjAll,
            String oomAdjReason) {
        return mOomAdjuster.updateOomAdjLocked(app, oomAdjAll, oomAdjReason);
    }

AMS 中提供的三个接口分别对应 OomAdjuster 中的三个接口,四大组件在更新 ADJ 时都是通过这里的接口。

6. ADJ 更新时机

6.1 activity 中更新 oom_adj

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

6.2 service 中更新 oom_adj

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

6.3 broadcast 中更新 oom_adj

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

6.4 ContentProvider 中更新 oom_adj

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

6.5 Process相关

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

7. updateOomAdjLocked() 一参

AMS 中一个参数的更新最终会调用到 OomAdjuster.java 中:

frameworks/base/services/core/java/com/android/server/am/OomAdjuster.java

    void updateOomAdjLocked(String oomAdjReason) {
        // 前台的app(若无app 处于前台则是TASK栈栈顶的应用)
        final ProcessRecord topApp = mService.getTopAppLocked();

        // 一参方法最终调用这里
        updateOomAdjLockedInner(oomAdjReason, topApp , null, null, true, true);
    }

参数是 oomAdjReason,定义在 OomAdjuster.java 文件最开始的地方:

    static final String OOM_ADJ_REASON_METHOD = "updateOomAdj";
    static final String OOM_ADJ_REASON_NONE = OOM_ADJ_REASON_METHOD + "_meh";
    static final String OOM_ADJ_REASON_ACTIVITY = OOM_ADJ_REASON_METHOD + "_activityChange";
    static final String OOM_ADJ_REASON_FINISH_RECEIVER = OOM_ADJ_REASON_METHOD + "_finishReceiver";
    static final String OOM_ADJ_REASON_START_RECEIVER = OOM_ADJ_REASON_METHOD + "_startReceiver";
    static final String OOM_ADJ_REASON_BIND_SERVICE = OOM_ADJ_REASON_METHOD + "_bindService";
    static final String OOM_ADJ_REASON_UNBIND_SERVICE = OOM_ADJ_REASON_METHOD + "_unbindService";
    static final String OOM_ADJ_REASON_START_SERVICE = OOM_ADJ_REASON_METHOD + "_startService";
    static final String OOM_ADJ_REASON_GET_PROVIDER = OOM_ADJ_REASON_METHOD + "_getProvider";
    static final String OOM_ADJ_REASON_REMOVE_PROVIDER = OOM_ADJ_REASON_METHOD + "_removeProvider";
    static final String OOM_ADJ_REASON_UI_VISIBILITY = OOM_ADJ_REASON_METHOD + "_uiVisibility";
    static final String OOM_ADJ_REASON_WHITELIST = OOM_ADJ_REASON_METHOD + "_whitelistChange";
    static final String OOM_ADJ_REASON_PROCESS_BEGIN = OOM_ADJ_REASON_METHOD + "_processBegin";
    static final String OOM_ADJ_REASON_PROCESS_END = OOM_ADJ_REASON_METHOD + "_processEnd";

一参的 updateOomAdjLocked() 最终调用的是 updateOomAdjLockedInner(),就是更新 LRU list (所有由 AMS 启动的进程都会保存在这里)中所有的 process 的 oom adj,并且对 cached 进程和 empty进程进行处理,详细看下文第 11 节。

8. updateOomAdjLocked() 二参

在了解完 updateOomAdjLocked() 一参的流程之后,二参函数应该会简单些。相比于一参的函数,这里多了一个参数 app,这个是指定一个进程。该函数用以更新指定进程以及所有绑定(直接/间接)的其他进程的adj。如果该进程中拥有service 或content provider,则其client进程的procState将不会被重新评估。

    /*更新指定进程的 adj 等值,如果参数app为null,表示更新所有LRU 进程*/
    boolean updateOomAdjLocked(ProcessRecord app, String oomAdjReason) {
        // 如果传入的app 为null,表示全部 LRU 进程都更新
        if (app == null || !mConstants.OOMADJ_UPDATE_QUICK) {
            updateOomAdjLocked(oomAdjReason);
            return true;
        }

        // 从 AMS 中获取topApp
        final ProcessRecord topApp = mService.getTopAppLocked();

        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, oomAdjReason);
        mService.mOomAdjProfiler.oomAdjStarted();

        // 用于标识 oom_adj 分配周期的id
        // 每次 updateOomAdjLocked() 函数调用都会有 mAdjSeq 序号,用以与进程adjSeq对比
        //    用以确认进程是否已经处理
        mAdjSeq++;

        // 第一步,更新进程自己
        // 确认是否处于 cached状态
        final boolean wasCached = app.isCached();
        // 获取当前 unlimit的adj
        final int oldAdj = app.getCurRawAdj();
        // 进而确认cached adj
        final int cachedAdj = oldAdj >= ProcessList.CACHED_APP_MIN_ADJ
                ? oldAdj : ProcessList.UNKNOWN_ADJ;
        final boolean wasBackground = ActivityManager.isProcStateBackground(app.setProcState);
        app.containsCycle = false;
        app.procStateChanged = false;
        app.resetCachedInfo();

        // 调用 5参的函数,更新adj
        boolean success = updateOomAdjLocked(app, cachedAdj, topApp, false,
                SystemClock.uptimeMillis());

        // 是cached 进程并且background状态未变,但没有5参更新成功(进程被kill了)
        if (!success || (wasCached == app.isCached() && oldAdj != ProcessList.INVALID_ADJ
                && wasBackground == ActivityManager.isProcStateBackground(app.setProcState))) {
            // Okay, it's unchanged, it won't impact any service it binds to, we're done here.
            if (DEBUG_OOM_ADJ) {
                Slog.i(TAG_OOM_ADJ, "No oomadj changes for " + app);
            }
            mService.mOomAdjProfiler.oomAdjEnded();
            Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
            return success; // 返回失败
        }

        //第二步:找到所有的reachable进程, 更新reachable进程
        ArrayList<ProcessRecord> processes = mTmpProcessList;
        ActiveUids uids = mTmpUidRecords;
        //mTmpQueue:大小是两倍的 CUR_MAX_CACHED_PROCESSES = 32 
        ArrayDeque<ProcessRecord> queue = mTmpQueue;

        processes.clear();
        uids.clear();
        queue.clear();

        // Track if any of them reachables could include a cycle
        boolean containsCycle = false;
        // Scan downstreams of the process record
        app.mReachable = true;
        // 循环遍历reachable的进程,其实就是遍历有关联的service和provider
        // 第一个for循环执行的是app,此时queue为空,第一个for循环将app的所有相关联service和provider都加入到queue中
        // 之后的for循环就是遍历queue,即遍历reachable进程
        // poll:检索并移除队列的头部
        for (ProcessRecord pr = app; pr != null; pr = queue.poll()) {
            if (pr != app) {
                processes.add(pr);
            }
            if (pr.uidRecord != null) {
                uids.put(pr.uidRecord.uid, pr.uidRecord);
            }

            // 有连接相关的进程
            for (int i = pr.connections.size() - 1; i >= 0; i--) {
                ConnectionRecord cr = pr.connections.valueAt(i);
                ProcessRecord service = (cr.flags & ServiceInfo.FLAG_ISOLATED_PROCESS) != 0
                        ? cr.binding.service.isolatedProc : cr.binding.service.app;
                if (service == null || service == pr) {
                    continue;
                }
                containsCycle |= service.mReachable;
                if (service.mReachable) {
                    continue;
                }
                // BIND_WAIVE_PRIORITY: 不会影响服务的进程优先级,像通用的应用进程一样将服务放在一个LRU表中
                if ((cr.flags & (Context.BIND_WAIVE_PRIORITY
                        | Context.BIND_TREAT_LIKE_ACTIVITY
                        | Context.BIND_ADJUST_WITH_ACTIVITY))
                        == Context.BIND_WAIVE_PRIORITY) {
                    continue;
                }
                // 加入队列尾部
                queue.offer(service);
                service.mReachable = true;
            }
            for (int i = pr.conProviders.size() - 1; i >= 0; i--) {
                ContentProviderConnection cpc = pr.conProviders.get(i);
                ProcessRecord provider = cpc.provider.proc;
                if (provider == null || provider == pr || (containsCycle |= provider.mReachable)) {
                    continue;
                }
                containsCycle |= provider.mReachable;
                if (provider.mReachable) {
                    continue;
                }
                queue.offer(provider);
                provider.mReachable = true;
            }
        }

        // Reset the flag
        app.mReachable = false;
        int size = processes.size();
        if (size > 0) {
            // Reverse the process list, since the updateOomAdjLockedInner scans from the end of it.
            for (int l = 0, r = size - 1; l < r; l++, r--) {
                ProcessRecord t = processes.get(l);
                processes.set(l, processes.get(r));
                processes.set(r, t);
            }
            mAdjSeq--;
            // 更新传入的进程列表,然后通过 updateOomAdjLockedInner()来更新这些进程
            updateOomAdjLockedInner(oomAdjReason, topApp, processes, uids, containsCycle, false);
        } else if (app.getCurRawAdj() == ProcessList.UNKNOWN_ADJ) {
            // In case the app goes from non-cached to cached but it doesn't have other reachable
            // processes, its adj could be still unknown as of now, assign one.
            processes.add(app);
            assignCachedAdjIfNecessary(processes);
            applyOomAdjLocked(app, false, SystemClock.uptimeMillis(),
                    SystemClock.elapsedRealtime());
        }
        //统计系统进入计算OomAdj的起始和结束时间,最后计算出OomAdj的运行时间
        //  mOomAdjProfiler 这个类应该是用来统计所有OomAdj信息的,在AMS中有定义实例
        mService.mOomAdjProfiler.oomAdjEnded();
        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
        return true;
    }

9. updateOomAdjLocked() 三参

三参的函数比较简单,相比于二参函数,多了一个参数 oomAdjAll。如果该值为true,则与二参的流程一样;如果该值为 false,则直接调用五参函数进行直接更新。

    boolean updateOomAdjLocked(ProcessRecord app, boolean oomAdjAll,
            String oomAdjReason) {
        if (oomAdjAll && mConstants.OOMADJ_UPDATE_QUICK) {
            return updateOomAdjLocked(app, oomAdjReason);
        }
        final ProcessRecord TOP_APP = mService.getTopAppLocked();
        final boolean wasCached = app.isCached();

        mAdjSeq++;

        // This is the desired cached adjusment we want to tell it to use.
        // If our app is currently cached, we know it, and that is it.  Otherwise,
        // we don't know it yet, and it needs to now be cached we will then
        // need to do a complete oom adj.
        final int cachedAdj = app.getCurRawAdj() >= ProcessList.CACHED_APP_MIN_ADJ
                ? app.getCurRawAdj() : ProcessList.UNKNOWN_ADJ;
        boolean success = updateOomAdjLocked(app, cachedAdj, TOP_APP, false,
                SystemClock.uptimeMillis());
        if (oomAdjAll
                && (wasCached != app.isCached() || app.getCurRawAdj() == ProcessList.UNKNOWN_ADJ)) {
            // Changed to/from cached state, so apps after it in the LRU
            // list may also be changed.
            updateOomAdjLocked(oomAdjReason);
        }
        return success;
    }

10. updateOomAdjLocked() 五参

该函数是private 函数,会被二参函数和三参的函数调用,该函数只是更新某一个特定进程以及其关联进程,按照逻辑看参数doingAll 都被置为false。

    private final boolean updateOomAdjLocked(ProcessRecord app, int cachedAdj,
            ProcessRecord TOP_APP, boolean doingAll, long now) {
        if (app.thread == null) {
            return false;
        }

        // 重置cached info
        app.resetCachedInfo();

        // 获取进程所在用户组的整体状态,UidRecord用于记录某个用户组中进程的运行状态
        UidRecord uidRec = app.uidRecord;
        if (uidRec != null) {
            if (DEBUG_UID_OBSERVERS) {
                Slog.i(TAG_UID_OBSERVERS, "Starting update of " + uidRec);
            }
            uidRec.reset();
        }

        // 计算进程相关的adj,最后参数为true,即把client 进程也计算
        computeOomAdjLocked(app, cachedAdj, TOP_APP, doingAll, now, false, true);

        // 应用adj
        boolean success = applyOomAdjLocked(app, doingAll, now, SystemClock.elapsedRealtime());

        // 更新UidRecord
        if (uidRec != null) {
            // After uidRec.reset() above, for UidRecord that has multiple processes (ProcessRecord)
            // , We need to apply all ProcessRecord into UidRecord.
            final ArraySet<ProcessRecord> procRecords = app.uidRecord.procRecords;
            for (int i = procRecords.size() - 1; i >= 0; i--) {
                final ProcessRecord pr = procRecords.valueAt(i);
                if (!pr.killedByAm && pr.thread != null) {
                    if (pr.isolated && pr.numberOfRunningServices() <= 0
                            && pr.isolatedEntryPoint == null) {
                        // No op.
                    } else {
                        // Keeping this process, update its uid.
                        updateAppUidRecLocked(pr);
                    }
                }
            }
            if (uidRec.getCurProcState() != PROCESS_STATE_NONEXISTENT
                    && (uidRec.setProcState != uidRec.getCurProcState()
                    || uidRec.setCapability != uidRec.curCapability
                    || uidRec.setWhitelist != uidRec.curWhitelist)) {
                ActiveUids uids = mTmpUidRecords;
                uids.clear();
                uids.put(uidRec.uid, uidRec);
                updateUidsLocked(uids, now);
                mProcessList.incrementProcStateSeqAndNotifyAppsLocked(uids);
            }
        }

        return success;
    }

主要调用 computeOomAdjLocked() 和 applyOomAdjLocked(),详细可以查看《更新原理(二)》

11. updateOomAdjLockedInner()

frameworks/base/services/core/java/com/android/server/am/OomAdjuster.java

    private void updateOomAdjLockedInner(String oomAdjReason, final ProcessRecord topApp,
            ArrayList<ProcessRecord> processes, ActiveUids uids, boolean potentialCycles,
            boolean startProfiling) {
        if (startProfiling) {
            Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, oomAdjReason);
            mService.mOomAdjProfiler.oomAdjStarted();
        }
        final long now = SystemClock.uptimeMillis();
        final long nowElapsed = SystemClock.elapsedRealtime();

        // 这里有个30mins的限制,如果activity 30分钟内没有活跃,后面会被kill掉
        final long oldTime = now - ProcessList.MAX_EMPTY_TIME;
        final boolean fullUpdate = processes == null;
        ActiveUids activeUids = uids;

        // 确定是否使用参数中传入的进程list,如果参数为NULL,则使用LRU processes
        ArrayList<ProcessRecord> activeProcesses = fullUpdate ? mProcessList.mLruProcesses
                : processes;
        final int numProc = activeProcesses.size();

        // 确认传入的uid是否为NULL,如果是则用 mActiveUids初始化
        if (activeUids == null) {
            final int numUids = mActiveUids.size();
            activeUids = mTmpUidRecords;
            activeUids.clear();
            for (int i = 0; i < numUids; i++) {
                UidRecord r = mActiveUids.valueAt(i);
                activeUids.put(r.uid, r);
            }
        }

        // 重置用户组中所有进程的状态
        for (int  i = activeUids.size() - 1; i >= 0; i--) {
            final UidRecord uidRec = activeUids.valueAt(i);
            if (DEBUG_UID_OBSERVERS) {
                Slog.i(TAG_UID_OBSERVERS, "Starting update of " + uidRec);
            }
            uidRec.reset();
        }

        if (mService.mAtmInternal != null) {
            mService.mAtmInternal.rankTaskLayersIfNeeded();
        }

        // 用于标识 oom_adj 分配周期的id
        // 每次 updateOomAdjLocked() 函数调用都会有 mAdjSeq 序号,用以与进程adjSeq对比
        //    用以确认进程是否已经处理
        mAdjSeq++;
        if (fullUpdate) {
            mNewNumServiceProcs = 0;
            mNewNumAServiceProcs = 0;
        }

        boolean retryCycles = false;
        boolean computeClients = fullUpdate || potentialCycles;

        // 先进行一些 reset 工作
        for (int i = numProc - 1; i >= 0; i--) {
            ProcessRecord app = activeProcesses.get(i);
            //所有进程的reachable都改为false
            app.mReachable = false;
            // app.adjSeq会记录进程上一次的更新序号,如果已经评估过,后面就不会在计算
            if (app.adjSeq != mAdjSeq) {
                app.containsCycle = false;
                //设为 empty 进程
                app.setCurRawProcState(PROCESS_STATE_CACHED_EMPTY);
                //adj 设为UNKNOWN_ADJ
                app.setCurRawAdj(ProcessList.UNKNOWN_ADJ);
                app.setCapability = PROCESS_CAPABILITY_NONE;
                app.resetCachedInfo();
            }
        }
        // 进入compute 阶段
        for (int i = numProc - 1; i >= 0; i--) {
            ProcessRecord app = activeProcesses.get(i);
            if (!app.killedByAm && app.thread != null) {
                app.procStateChanged = false;
                computeOomAdjLocked(app, ProcessList.UNKNOWN_ADJ, topApp, fullUpdate, now, false,
                        computeClients); // It won't enter cycle if not computing clients.
                // if any app encountered a cycle, we need to perform an additional loop later
                retryCycles |= app.containsCycle;
                // Keep the completedAdjSeq to up to date.
                app.completedAdjSeq = mAdjSeq;
            }
        }

        //将 cache 进程和 empty 进程均匀分散到slot中去
        assignCachedAdjIfNecessary(mProcessList.mLruProcesses);

        //是否需要计算进程绑定的client的adj,同时一参调用是需要计算的
        if (computeClients) { // There won't be cycles if we didn't compute clients above.
            // Cycle strategy:
            // - Retry computing any process that has encountered a cycle.
            // - Continue retrying until no process was promoted.
            // - Iterate from least important to most important.
            int cycleCount = 0;
            while (retryCycles && cycleCount < 10) {
                cycleCount++;
                retryCycles = false;

                for (int i = 0; i < numProc; i++) {
                    ProcessRecord app = activeProcesses.get(i);
                    if (!app.killedByAm && app.thread != null && app.containsCycle) {
                        app.adjSeq--;
                        app.completedAdjSeq--;
                    }
                }

                for (int i = 0; i < numProc; i++) {
                    ProcessRecord app = activeProcesses.get(i);
                    if (!app.killedByAm && app.thread != null && app.containsCycle) {
                        if (computeOomAdjLocked(app, app.getCurRawAdj(), topApp, true, now,
                                true, true)) {
                            retryCycles = true;
                        }
                    }
                }
            }
        }

        // 非cached或empty进程数置0
        mNumNonCachedProcs = 0;
        // cached hidden进程数置0
        mNumCachedHiddenProcs = 0;

        // 杀掉超过限额的empty进程和cached进程,这个函数很重要
        boolean allChanged = updateAndTrimProcessLocked(now, nowElapsed, oldTime, activeUids);
        mNumServiceProcs = mNewNumServiceProcs;

        if (mService.mAlwaysFinishActivities) {
            // Need to do this on its own message because the stack may not
            // be in a consistent state at this point.
            mService.mAtmInternal.scheduleDestroyAllActivities("always-finish");
        }

        if (allChanged) {
            mService.requestPssAllProcsLocked(now, false,
                    mService.mProcessStats.isMemFactorLowered());
        }

        updateUidsLocked(activeUids, nowElapsed);

        if (mService.mProcessStats.shouldWriteNowLocked(now)) {
            mService.mHandler.post(new ActivityManagerService.ProcStatsRunnable(mService,
                    mService.mProcessStats));
        }

        // Run this after making sure all procstates are updated.
        mService.mProcessStats.updateTrackingAssociationsLocked(mAdjSeq, now);

        if (DEBUG_OOM_ADJ) {
            final long duration = SystemClock.uptimeMillis() - now;
            if (false) {
                Slog.d(TAG_OOM_ADJ, "Did OOM ADJ in " + duration + "ms",
                        new RuntimeException("here").fillInStackTrace());
            } else {
                Slog.d(TAG_OOM_ADJ, "Did OOM ADJ in " + duration + "ms");
            }
        }
        if (startProfiling) {
            mService.mOomAdjProfiler.oomAdjEnded();
            Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
        }
    }

11.1 assignCachedAdjIfNecessary()

    /*
    *该函数是将lru list中的cache的进程按照一定的跨距逐个分配到[CACHED_APP_MIN_ADJ, CACHED_APP_MAX_ADJ]区间中
    *根据proc_state为empty和其他cached,对其进行分配
    */
    private void assignCachedAdjIfNecessary(ArrayList<ProcessRecord> lruList) {
        final int numLru = lruList.size();

        // 首先,根据进程当前状态为每个进程更新oom adj
        int curCachedAdj = ProcessList.CACHED_APP_MIN_ADJ;
        int nextCachedAdj = curCachedAdj + (ProcessList.CACHED_APP_IMPORTANCE_LEVELS * 2);
        int curCachedImpAdj = 0;
        int curEmptyAdj = ProcessList.CACHED_APP_MIN_ADJ + ProcessList.CACHED_APP_IMPORTANCE_LEVELS;
        int nextEmptyAdj = curEmptyAdj + (ProcessList.CACHED_APP_IMPORTANCE_LEVELS * 2);

        final int emptyProcessLimit = mConstants.CUR_MAX_EMPTY_PROCESSES;
        final int cachedProcessLimit = mConstants.CUR_MAX_CACHED_PROCESSES
                - emptyProcessLimit;

        //计算出槽的数量,再将cache进程和empty进程分别平均分配到这些槽中(slots)
        //  CACHED_APP_MIN_ADJ ~ CACHED_APP_MAX_ADJ 之间交错分配cached和empty进程
        //  mNumNonCachedProcs 是除cached进程外的进程数,mNumCachedHiddenProcs是cached进程个数
        int numEmptyProcs = numLru - mNumNonCachedProcs - mNumCachedHiddenProcs;
        if (numEmptyProcs > cachedProcessLimit) { //空进程数大于cache进程阈值
            //确保低内存杀进程的时候以杀empty为主,尽可能保留cache
            numEmptyProcs = cachedProcessLimit;
        }

        //cachedFactor和emptyFactor分别表示每个slot中包括的进程个数
        int cachedFactor = (mNumCachedHiddenProcs > 0 ? (mNumCachedHiddenProcs + mNumSlots - 1) : 1)
                / mNumSlots;
        if (cachedFactor < 1) cachedFactor = 1;

        int emptyFactor = (numEmptyProcs + mNumSlots - 1) / mNumSlots;
        if (emptyFactor < 1) emptyFactor = 1;

        int stepCached = -1;
        int stepEmpty = -1;
        int lastCachedGroup = 0;
        int lastCachedGroupImportance = 0;
        int lastCachedGroupUid = 0;

        //遍历lru列表,为每一个app进程更新cache状态
        for (int i = numLru - 1; i >= 0; i--) {
            ProcessRecord app = lruList.get(i);
            // If we haven't yet assigned the final cached adj
            // to the process, do that now.
            if (!app.killedByAm && app.thread != null && app.curAdj
                    >= ProcessList.UNKNOWN_ADJ) {
                switch (app.getCurProcState()) { //三种非empty cache进程
                    case PROCESS_STATE_CACHED_ACTIVITY:
                    case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT:
                    case ActivityManager.PROCESS_STATE_CACHED_RECENT:
                        // Figure out the next cached level, taking into account groups.
                        boolean inGroup = false;
                        if (app.connectionGroup != 0) {
                            if (lastCachedGroupUid == app.uid
                                    && lastCachedGroup == app.connectionGroup) {
                                // This is in the same group as the last process, just tweak
                                // adjustment by importance.
                                if (app.connectionImportance > lastCachedGroupImportance) {
                                    lastCachedGroupImportance = app.connectionImportance;
                                    if (curCachedAdj < nextCachedAdj
                                            && curCachedAdj < ProcessList.CACHED_APP_MAX_ADJ) {
                                        curCachedImpAdj++;
                                    }
                                }
                                inGroup = true;
                            } else {
                                lastCachedGroupUid = app.uid;
                                lastCachedGroup = app.connectionGroup;
                                lastCachedGroupImportance = app.connectionImportance;
                            }
                        }
                        //当前slot数大于factor,分配下一个slot,更新cur和next的cachedadj
                        if (!inGroup && curCachedAdj != nextCachedAdj) {
                            stepCached++;
                            curCachedImpAdj = 0;
                            if (stepCached >= cachedFactor) {
                                stepCached = 0;
                                curCachedAdj = nextCachedAdj;
                                nextCachedAdj += ProcessList.CACHED_APP_IMPORTANCE_LEVELS * 2;
                                if (nextCachedAdj > ProcessList.CACHED_APP_MAX_ADJ) {
                                    nextCachedAdj = ProcessList.CACHED_APP_MAX_ADJ;
                                }
                            }
                        }
                        // This process is a cached process holding activities...
                        // assign it the next cached value for that type, and then
                        // step that cached level.
                        app.setCurRawAdj(curCachedAdj + curCachedImpAdj);
                        app.curAdj = app.modifyRawOomAdj(curCachedAdj + curCachedImpAdj);
                        if (DEBUG_LRU) {
                            Slog.d(TAG_LRU, "Assigning activity LRU #" + i
                                    + " adj: " + app.curAdj + " (curCachedAdj=" + curCachedAdj
                                    + " curCachedImpAdj=" + curCachedImpAdj + ")");
                        }
                        break;
                    default: //empty进程
                        // Figure out the next cached level.
                        if (curEmptyAdj != nextEmptyAdj) {
                            stepEmpty++;
                            if (stepEmpty >= emptyFactor) {
                                stepEmpty = 0;
                                curEmptyAdj = nextEmptyAdj;
                                nextEmptyAdj += ProcessList.CACHED_APP_IMPORTANCE_LEVELS * 2;
                                if (nextEmptyAdj > ProcessList.CACHED_APP_MAX_ADJ) {
                                    nextEmptyAdj = ProcessList.CACHED_APP_MAX_ADJ;
                                }
                            }
                        }
                        // For everything else, assign next empty cached process
                        // level and bump that up.  Note that this means that
                        // long-running services that have dropped down to the
                        // cached level will be treated as empty (since their process
                        // state is still as a service), which is what we want.
                        app.setCurRawAdj(curEmptyAdj);
                        app.curAdj = app.modifyRawOomAdj(curEmptyAdj);
                        if (DEBUG_LRU) {
                            Slog.d(TAG_LRU, "Assigning empty LRU #" + i
                                    + " adj: " + app.curAdj + " (curEmptyAdj=" + curEmptyAdj
                                    + ")");
                        }
                        break;
                }
            }
        }
    }

AMS将所有cache和empty按照一定的机制均分到[900,999]区间中;在这个区间中,每一个分配给cache/empty进程的adj值都被称为一个槽点(slot),实际上是将LRU列表中的所有cache进程按照一定的跨距均分到这些槽点中;

在这个机制里面,cache进程的adj分配起点为900,而empty进程的分配起点为905,两者都是以跨距为10进行均匀分配的;这样就能够将empty进程和cache进程分开,彼此间隔相同的距离。当内存不足时,lmkd进程就会从adj最大值开始,逐步往下查杀进程,不会出现集体被杀或者都不被杀导致内存占用过高的问题。

注意:

临时变量 emptyProcessLimit 记录系统中empty进程的最大值,通常为 cached 最大值的一半,即默认值为32/2 = 16;

临时变量 cachedProcessLimit 记录系统中cached 进程的最大值,即mConstants.CUR_MAX_CACHED_PROCESSES - emptyProcessLimit,CUR_MAX_CACHED_PROCESSES  默认为32,减去 emptyProcessLimit,剩余也是16个;

11.2 updateAndTrimProcessLocked()

    private boolean updateAndTrimProcessLocked(final long now, final long nowElapsed,
            final long oldTime, final ActiveUids activeUids) {
        ArrayList<ProcessRecord> lruList = mProcessList.mLruProcesses;
        final int numLru = lruList.size();


        final int emptyProcessLimit = mConstants.CUR_MAX_EMPTY_PROCESSES;
        final int cachedProcessLimit = mConstants.CUR_MAX_CACHED_PROCESSES
                - emptyProcessLimit;
        int lastCachedGroup = 0;
        int lastCachedGroupUid = 0;
        int numCached = 0;
        int numCachedExtraGroup = 0;
        int numEmpty = 0;
        int numTrimming = 0;

        /*******针对 B service 优化的地方 1*******/
        ProcessRecord selectedAppRecord = null;
        long serviceLastActivity = 0;
        int numBServices = 0;
        /*******针对 B service 优化的地方 1 end*******/

        // 反向遍历 LRU
        for (int i = numLru - 1; i >= 0; i--) {
            ProcessRecord app = lruList.get(i);

            /*******针对 B service 优化的地方 2*******/
            if (mEnableBServicePropagation && app.serviceb
                    && (app.curAdj == ProcessList.SERVICE_B_ADJ)) {
                numBServices++;
                // 遍历正在运行的服务
                for (int s = app.numberOfRunningServices() - 1; s >= 0; s--) {
                    ServiceRecord sr = app.getRunningServiceAt(s);
                    if (DEBUG_OOM_ADJ) Slog.d(TAG,"app.processName = " + app.processName
                            + " serviceb = " + app.serviceb + " s = " + s + " sr.lastActivity = "
                            + sr.lastActivity + " packageName = " + sr.packageName
                            + " processName = " + sr.processName);
                    // 当前时间与上一次activity运行该服务的时间差,lastActivity在创建services时更新
                    // mMinBServiceAgingTime = 5000ms,B_service的最小老化时间阈值
                    if (SystemClock.uptimeMillis() - sr.lastActivity
                            < mMinBServiceAgingTime) {
                        if (DEBUG_OOM_ADJ) {
                            Slog.d(TAG,"Not aged enough!!!");
                        }
                        continue;
                    }
                    // 更新距上一次运行service 的时间最久的app
                    // 当进程为 B_service,在B_service进程数超过阈值(5个)时,
                    // 如果该进程相关联的service 中,有最久未被调用的service,则将该进程设置
                    //    为SelectedAppRecord,将其adj设置为800,lmkd中存储的是900
                    if (serviceLastActivity == 0) {
                        serviceLastActivity = sr.lastActivity;
                        selectedAppRecord = app;
                    } else if (sr.lastActivity < serviceLastActivity) {
                        serviceLastActivity = sr.lastActivity;
                        selectedAppRecord = app;
                    }
                }
            }
            if (DEBUG_OOM_ADJ && selectedAppRecord != null) Slog.d(TAG,
                    "Identified app.processName = " + selectedAppRecord.processName
                    + " app.pid = " + selectedAppRecord.pid);
            /*******针对 B service 优化的地方 2 end*******/

            if (!app.killedByAm && app.thread != null) {
                //  不需要为没有计算的进程应用更新
                if (app.completedAdjSeq == mAdjSeq) {
                    applyOomAdjLocked(app, true, now, nowElapsed);
                }

                // 根据procState 确定进程类型数量
                switch (app.getCurProcState()) {
                    case PROCESS_STATE_CACHED_ACTIVITY: //处理cached 且函数activity的进程
                    case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT:
                        mNumCachedHiddenProcs++; //统计cached进程个数
                        numCached++;
                        if (app.connectionGroup != 0) {
                            if (lastCachedGroupUid == app.info.uid
                                    && lastCachedGroup == app.connectionGroup) {
                                // 如果与上一个进程同一个进程组,
                                //   不希望它与cached 进程数量限制相冲突,只是
                                //   额外增加group count来统计
                                numCachedExtraGroup++;
                            } else {
                                lastCachedGroupUid = app.info.uid;
                                lastCachedGroup = app.connectionGroup;
                            }
                        } else {
                            lastCachedGroupUid = lastCachedGroup = 0;
                        }

                        // 除掉额外计数的cached进程,扔超过limit的,kill
                        if ((numCached - numCachedExtraGroup) > cachedProcessLimit) {
                            app.kill("cached #" + numCached,
                                    ApplicationExitInfo.REASON_OTHER,
                                    ApplicationExitInfo.SUBREASON_TOO_MANY_CACHED,
                                    true);
                        }
                        break;
                    case PROCESS_STATE_CACHED_EMPTY: //处理被cached 的empty进程
                        //当empty进程超过CUR_TRIM_EMPTY_PROCESSES(默认8个),
                        // 并且activity上次活跃超过了30min,kill
                        if (numEmpty > mConstants.CUR_TRIM_EMPTY_PROCESSES
                                && app.lastActivityTime < oldTime) {
                            app.kill("empty for "
                                    + ((oldTime + ProcessList.MAX_EMPTY_TIME - app.lastActivityTime)
                                    / 1000) + "s",
                                    ApplicationExitInfo.REASON_OTHER,
                                    ApplicationExitInfo.SUBREASON_TRIM_EMPTY,
                                    true);
                        } else {
                            numEmpty++;
                            // empty 进程中activity虽然没有超过30min,但总的数量超过了16(默认值),kill
                            if (numEmpty > emptyProcessLimit) {
                                app.kill("empty #" + numEmpty,
                                        ApplicationExitInfo.REASON_OTHER,
                                        ApplicationExitInfo.SUBREASON_TOO_MANY_EMPTY,
                                        true);
                            }
                        }
                        break;
                    default:
                        mNumNonCachedProcs++;
                        break;
                }

                // 如果该进程是isolated,其中没有运行service,并且它不是具有自定义入口点的特殊
                //    进程,那么该进程就不再需要了。
                // 我们强烈地杀掉这些进程因为我们可以根据定义不再重复使用相同的进程,这样能够很好
                //  地避免在不再需要的情况下让代码中的任何代码在它们中运行。
                if (app.isolated && app.numberOfRunningServices() <= 0
                        && app.isolatedEntryPoint == null) {
                    // If this is an isolated process, there are no services
                    // running in it, and it's not a special process with a
                    // custom entry point, then the process is no longer
                    // needed.  We agressively kill these because we can by
                    // definition not re-use the same process again, and it is
                    // good to avoid having whatever code was running in them
                    // left sitting around after no longer needed.
                    app.kill("isolated not needed", ApplicationExitInfo.REASON_OTHER,
                            ApplicationExitInfo.SUBREASON_ISOLATED_NOT_NEEDED, true);
                } else {
                    // 否则就保留这些进程,
                    //更新进程的 uidRecord
                    updateAppUidRecLocked(app);
                }

                if (app.getCurProcState() >= ActivityManager.PROCESS_STATE_HOME
                        && !app.killedByAm) {
                    numTrimming++;
                }
            }
        }

        /*******针对 B service 优化的地方 3*******/
        // 当B_Service 的数量超过上面(mBServiceAppThreshold=5),
        // 且mAllowLowerMemLevel 为true,即为低内存lmkd 杀过进程
        if ((numBServices > mBServiceAppThreshold) && (true == mService.mAllowLowerMemLevel)
                && (selectedAppRecord != null)) {
            // setOomAdj() 方法是将更新后的 adj通知给 lmkd
            ProcessList.setOomAdj(selectedAppRecord.pid, selectedAppRecord.info.uid,
                    ProcessList.CACHED_APP_MAX_ADJ);
            //将最久没运行过的appRecord的adj设为最高值
            selectedAppRecord.setAdj = selectedAppRecord.curAdj;
            if (DEBUG_OOM_ADJ) Slog.d(TAG,"app.processName = " + selectedAppRecord.processName
                        + " app.pid = " + selectedAppRecord.pid + " is moved to higher adj");
        }
        /*******针对 B service 优化的地方 3 end*******/

        mProcessList.incrementProcStateSeqAndNotifyAppsLocked(activeUids);

        //本方法根据cached和empty进程的数量,确定 memFactor;根据memFactor是否为NORMAL等级分别进行处理
        return mService.updateLowMemStateLocked(numCached, numEmpty, numTrimming);
    }

updateAndTrimProcessLocked() には、lmkd に加えて AMS のプロセス強制終了メカニズムである app.kill() メソッドが多数含まれています。この関数は LRU リストを走査し、キャッシュされたプロセスと空のプロセスをそれぞれカウントし、トリム処理を実行します。制限を超えるキャッシュされたプロセスと空のプロセスを確認して強制終了し、メモリを再利用します。

一時変数 emptyProcessLimitと cachedProcessLimitは、それぞれ空のプロセスとキャッシュされたプロセスの数の上限を記録します。assignCachedAdjIfNecessary()関数と同様に、ここでの値は両方ともデフォルトの16です。

さらに、この関数は、コード内のコメントに示されているように、ソース コードに基づいて B_services に 3 つの最適化ポイントを追加します。関連する変数 mMinBServiceAgingTime、mBServiceAppThreshold、および mEnableBServicePropagation はすべて、OomAdjuster.java で定義されたメンバー変数です。詳細なパッチをダウンロードできます。

11.2.1 updateLowMemStateLocked()

frameworks/base/services/core/java/com/android/server/am/AMS.java

/**
*本方法根据cached和empty进程的数量,确定 memFactor;根据memFactor是否为NORMAL等级分别进行处理
* 1、非NORMAL:将memFactor转换为trim level等级,根据当前进程的进程级别分等级处理,确定最新的trim level
* 2、NORMAL:对于重要性比IMPORTANT_BACKGROUND小或没有运行UI的system进程,关闭其从showing UI回收内存的权利,并且将trimlevel提升到不低于UI_HIDDEN
*/
final boolean updateLowMemStateLocked(int numCached, int numEmpty, int numTrimming) {
        final int N = mProcessList.getLruSizeLocked();//lru大小
        final long now = SystemClock.uptimeMillis();
        //内存因子,值越大,级别越高,内存资源越紧张
        int memFactor;
        if (mLowMemDetector != null && mLowMemDetector.isAvailable()) {
        //获取memfactor,此函数根据PSI event返回对应的内存因子级别,通过监听/proc/pressure/memory实现
        // waitforPressure方法是一个jni调用
            memFactor = mLowMemDetector.getMemFactor();
        } else {
        	// R上不在使用
            // 根据cache进程和empty进程的个数得出memfactor,memfactor越大,内存压力越大
            if (numCached <= mConstants.CUR_TRIM_CACHED_PROCESSES//32/6=5
                && numEmpty <= mConstants.CUR_TRIM_EMPTY_PROCESSES) {//8
                final int numCachedAndEmpty = numCached + numEmpty;
                if (numCachedAndEmpty <= ProcessList.TRIM_CRITICAL_THRESHOLD) {//3
                    memFactor = ProcessStats.ADJ_MEM_FACTOR_CRITICAL;
                } else if (numCachedAndEmpty <= ProcessList.TRIM_LOW_THRESHOLD) {//5
                    memFactor = ProcessStats.ADJ_MEM_FACTOR_LOW;
                } else {
                    memFactor = ProcessStats.ADJ_MEM_FACTOR_MODERATE;
                }
            } else {
                memFactor = ProcessStats.ADJ_MEM_FACTOR_NORMAL;
            }
        }
        // We always allow the memory level to go up (better).  We only allow it to go
        // down if we are in a state where that is allowed, *and* the total number of processes
        // has gone down since last time.
        if (DEBUG_OOM_ADJ) Slog.d(TAG_OOM_ADJ, "oom: memFactor=" + memFactor
                + " last=" + mLastMemoryLevel + " allowLow=" + mAllowLowerMemLevel
                + " numProcs=" + mProcessList.getLruSizeLocked() + " last=" + mLastNumProcesses);
        //现在的等级比之前还高,说明内存紧张,不主动降低等级
        if (memFactor > mLastMemoryLevel) {
           //当不允许LowerMemLevel或者LRU进程数有增加时,可以降低等级
            if (!mAllowLowerMemLevel || mProcessList.getLruSizeLocked() >= mLastNumProcesses) {
                memFactor = mLastMemoryLevel;
                if (DEBUG_OOM_ADJ) Slog.d(TAG_OOM_ADJ, "Keeping last mem factor!");
            }
        }
        //内存因子更新了
        if (memFactor != mLastMemoryLevel) {
            EventLogTags.writeAmMemFactor(memFactor, mLastMemoryLevel);
            FrameworkStatsLog.write(FrameworkStatsLog.MEMORY_FACTOR_STATE_CHANGED, memFactor);
        }
        //更新最近一次memorylevel的等级
        mLastMemoryLevel = memFactor;
        mLastNumProcesses = mProcessList.getLruSizeLocked();
        //将内存等级保存到processstats中,如果与之前不等(更新了),返回true
        boolean allChanged = mProcessStats.setMemFactorLocked(
                memFactor, mAtmInternal != null ? !mAtmInternal.isSleeping() : true, now);
        //更新后获取factor
        final int trackerMemFactor = mProcessStats.getMemFactorLocked();
        //下面为两个大判断,memFactor 为NORMAL和不为NORMAL两种情况
         //memFactor 不等于NORMAL时的处理
        if (memFactor != ProcessStats.ADJ_MEM_FACTOR_NORMAL) {
            if (mLowRamStartTime == 0) {
              //进入lowRam状态,记录进入的时间点
                mLowRamStartTime = now;
            }
            int step = 0;
            int fgTrimLevel;
            //将内存因子memFactor转换为ComponentCallbacks2中定义的变量名,
            //就是从memFactor等级转换到 TrimMemlevel
        //TrimMemlevel 值越大越容易被回收
            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;
            }
            //factor为每个槽可以容纳的进程数
            // 三个LowRam状态各自放多少Trimming进程
            int factor = numTrimming/3;
            int minFactor = 2;
            if (mAtmInternal.getHomeProcess() != null) minFactor++;
            if (mAtmInternal.getPreviousProcess() != null) minFactor++;
            if (factor < minFactor) factor = minFactor;
            //80,最高等级,内存压力最大
            int curLevel = ComponentCallbacks2.TRIM_MEMORY_COMPLETE;
            // 对于重要性大于home的进程而言,重要性越高,内存回收等级越低
            // 对于重要性小于home的进程,排在LRU列表越靠后,即越重要回收等级越高
            // 这么安排的理由有两个:
            // 1、此时越不重要的进程,其中运行的组件越少,能够回收的内存不多,不需要高回收等级
            // 2、越不重要的进程越有可能被LMK kill掉,没必要以高等级回收内存
            
 			//反向遍历LRU链表
            for (int i=N-1; i>=0; i--) {
                ProcessRecord app = mProcessList.mLruProcesses.get(i);
                if (allChanged || app.procStateChanged) {
                    setProcessTrackerStateLocked(app, trackerMemFactor, now);
                    app.procStateChanged = false;
                }
                //process_state大于等于HOME进程,没HOME这么重要的进程
                if (app.getCurProcState() >= ActivityManager.PROCESS_STATE_HOME
                        && !app.killedByAm) {
                    if (app.trimMemoryLevel < curLevel && app.thread != null) {
                        try {
                             //加大内存回收
                            app.thread.scheduleTrimMemory(curLevel);
                        } catch (RemoteException e) {
                        }
                    }
                    //调整 trimMemoryLevel 到 curlevel
                    app.trimMemoryLevel = curLevel;
                    step++;
                    //当前factor满了,下一个factor
                    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.getCurProcState() == ActivityManager.PROCESS_STATE_HEAVY_WEIGHT
                        && !app.killedByAm) {//重量级后台进程
                    if (app.trimMemoryLevel < ComponentCallbacks2.TRIM_MEMORY_BACKGROUND
                            && app.thread != null) {
                        try {
                            if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG_OOM_ADJ,
                                    "Trimming memory of heavy-weight " + app.processName
                                    + " to " + ComponentCallbacks2.TRIM_MEMORY_BACKGROUND);
                             //level提到TRIM_MEMORY_BACKGROUND
                            app.thread.scheduleTrimMemory(
                                    ComponentCallbacks2.TRIM_MEMORY_BACKGROUND);
                        } catch (RemoteException e) {
                        }
                    }
                    app.trimMemoryLevel = ComponentCallbacks2.TRIM_MEMORY_BACKGROUND;
                } else {//其他进程级别
                	//级别大于等于重要的后台进程
                    if ((app.getCurProcState() >= ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND
                            || app.systemNoUi) && app.hasPendingUiClean()) {
                        // If this application is now in the background and it
                        // had done UI, then give it the special trim level to
                        // have it free UI resources.
                        final int level = ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN;
                        if (app.trimMemoryLevel < level && app.thread != null) {
                            try {
                               //回收
                                app.thread.scheduleTrimMemory(level);
                            } catch (RemoteException e) {
                            }
                        }
                        app.setPendingUiClean(false);
                    }
                    if (app.trimMemoryLevel < fgTrimLevel && app.thread != null) {
                        try {
                            //关掉showingUI回收
                            app.thread.scheduleTrimMemory(fgTrimLevel);
                        } catch (RemoteException e) {
                        }
                    }
                    app.trimMemoryLevel = fgTrimLevel;
                }
            }
        } else { //memFactor == NORMAL时的处理
            if (mLowRamStartTime != 0) {
               //统计总的LowRam持续时间
                mLowRamTimeSinceLastIdle += now - mLowRamStartTime;
                //NORMAL状态取消LowRam状态和计时
                mLowRamStartTime = 0;
            }
            for (int i=N-1; i>=0; i--) {
                ProcessRecord app = mProcessList.mLruProcesses.get(i);
                if (allChanged || app.procStateChanged) {
                    setProcessTrackerStateLocked(app, trackerMemFactor, now);
                    app.procStateChanged = false;
                }
                //当前内存factor是NORMAL,根据当前进程state和trimmemorylevel,
                // 关掉showingUI回收(只处理比PROCESS_STATE_IMPORTANT_BACKGROUND不重要的进程)
                //PROCESS_STATE_IMPORTANT_BACKGROUND重要的后台进程
                // systemNoUi:系统进程但是没有正在显示的UI;hasPendingUiClean:是否想从showingUI回收内存
                if ((app.getCurProcState() >= ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND
                        || app.systemNoUi) && app.hasPendingUiClean()) {
                     //内存等级小于TRIM_MEMORY_UI_HIDDEN
                    if (app.trimMemoryLevel < ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN
                            && app.thread != null) {
                        try {
                            //调整TrimMemoryLevel到TRIM_MEMORY_UI_HIDDEN
                            app.thread.scheduleTrimMemory(
                                    ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN);
                        } catch (RemoteException e) {
                        }
                    }
                    //清理showingUI:false
                    app.setPendingUiClean(false);
                }
                app.trimMemoryLevel = 0;
            }
        }
        return allChanged;
    }

次の記事: Android oom_adj 更新原則 (2)に続く

おすすめ

転載: blog.csdn.net/jingerppp/article/details/131595511