Android computeOomAdjLocked概览

1.1 computeOomAdjLocked计算Adj概览图

computeOomAdjLocked

2.1 computeOomAdjLocked 计算进程Adj分析

final ActivityRecord TOP_ACT = resumedAppLocked(); // 2.2
final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;

private final int computeOomAdjLocked(ProcessRecord app, int cachedAdj, ProcessRecord TOP_APP,
            boolean doingAll, long now) {
    if (mAdjSeq == app.adjSeq) {
        // This adjustment has already been computed.
        return app.curRawAdj;
    }

    if (app.thread == null) {
        app.adjSeq = mAdjSeq;
        app.curSchedGroup = ProcessList.SCHED_GROUP_BACKGROUND;
        app.curProcState = ActivityManager.PROCESS_STATE_CACHED_EMPTY;
        return (app.curAdj=app.curRawAdj=ProcessList.CACHED_APP_MAX_ADJ);
    }

    app.adjTypeCode = ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN;
    app.adjSource = null;
    app.adjTarget = null;
    app.empty = false;
    app.cached = false;

    final int activitiesSize = app.activities.size();
    // the process running the current foreground app adj 比前台进程高
    if (app.maxAdj <= ProcessList.FOREGROUND_APP_ADJ) {
        // The max adjustment doesn't allow this app to be anything
        // below foreground, so it is not worth doing work for it.
        app.adjType = "fixed";
        app.adjSeq = mAdjSeq;
        app.curRawAdj = app.maxAdj;
        app.foregroundActivities = false;
        app.curSchedGroup = ProcessList.SCHED_GROUP_DEFAULT;
        app.curProcState = ActivityManager.PROCESS_STATE_PERSISTENT;
        // System processes can do UI, and when they do we want to have
        // them trim their memory after the user leaves the UI.  To
        // facilitate this, here we need to determine whether or not it
        // is currently showing UI.
        app.systemNoUi = true;
        if (app == TOP_APP) {
            app.systemNoUi = false;
            app.curSchedGroup = ProcessList.SCHED_GROUP_TOP_APP;
            app.adjType = "pers-top-activity";
        } else if (app.hasTopUi) {
            app.systemNoUi = false;
            app.curSchedGroup = ProcessList.SCHED_GROUP_TOP_APP;
            app.adjType = "pers-top-ui";
        } else if (activitiesSize > 0) {
            for (int j = 0; j < activitiesSize; j++) {
                final ActivityRecord r = app.activities.get(j);
                if (r.visible) {
                    app.systemNoUi = false;
                }
            }
        }
        if (!app.systemNoUi) {// 存在Ui的情况
        // Process is a persistent system process and is doing UI
            app.curProcState = ActivityManager.PROCESS_STATE_PERSISTENT_UI;
        }
        return (app.curAdj=app.maxAdj);
    }

    app.systemNoUi = false;

    final int PROCESS_STATE_CUR_TOP = mTopProcessState;

    // 前台进程top app(launcher), instrumentationClass 正在执行的广播 service
    // Determine the importance of the process, starting with most
    // important to least, and assign an appropriate OOM adjustment.
    int adj;
    int schedGroup;
    int procState;
    boolean foregroundActivities = false;
    BroadcastQueue queue;
    if (app == TOP_APP) {
        // The last app on the list is the foreground app.
        adj = ProcessList.FOREGROUND_APP_ADJ;
        schedGroup = ProcessList.SCHED_GROUP_TOP_APP;
        app.adjType = "top-activity";
        foregroundActivities = true;
        procState = PROCESS_STATE_CUR_TOP;
        if(app == mHomeProcess) {
            mHomeKilled = false;
            mHomeProcessName = mHomeProcess.processName;
        }
    } else if (app.instrumentationClass != null) {
        // Don't want to kill running instrumentation.
        adj = ProcessList.FOREGROUND_APP_ADJ;
        schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
        app.adjType = "instrumentation";
        procState = ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE;
    } else if ((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.
        adj = ProcessList.FOREGROUND_APP_ADJ;
        schedGroup = (queue == mFgBroadcastQueue)
                ? ProcessList.SCHED_GROUP_DEFAULT : ProcessList.SCHED_GROUP_BACKGROUND;
        app.adjType = "broadcast";
        procState = ActivityManager.PROCESS_STATE_RECEIVER;
    } else if (app.executingServices.size() > 0) {
        // An app that is currently executing a service callback also
        // counts as being in the foreground.
        adj = ProcessList.FOREGROUND_APP_ADJ;
        schedGroup = app.execServicesFg ?
                ProcessList.SCHED_GROUP_DEFAULT : ProcessList.SCHED_GROUP_BACKGROUND;
        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 = ProcessList.SCHED_GROUP_BACKGROUND;
        // 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";

        if (mHomeKilled && app.processName.equals(mHomeProcessName)) {
            adj = ProcessList.PERSISTENT_PROC_ADJ;
            schedGroup = Process.THREAD_GROUP_DEFAULT;
            app.cached = false;
            app.empty = false;
            app.adjType = "top-activity";
        }
    }

    // Examine all activities if not already foreground. 非前台Activity
    if (!foregroundActivities && activitiesSize > 0) {
        int minLayer = ProcessList.VISIBLE_APP_LAYER_MAX;
        for (int j = 0; j < activitiesSize; j++) {
            final ActivityRecord r = app.activities.get(j);
            if (r.app != app) {
                Log.e(TAG, "Found activity " + r + " in proc activity list using " + r.app
                        + " instead of expected " + app);
                if (r.app == null || (r.app.uid == app.uid)) {
                    // Only fix things up when they look sane
                    r.app = app;
                } else {
                    continue;
                }
            }
            if (r.visible) { // Activity可见
                // App has a visible activity; only upgrade adjustment.
                if (adj > ProcessList.VISIBLE_APP_ADJ) {
                    adj = ProcessList.VISIBLE_APP_ADJ;
                    app.adjType = "visible";
                }
                if (procState > PROCESS_STATE_CUR_TOP) {
                    procState = PROCESS_STATE_CUR_TOP;
                }
                schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
                app.cached = false;
                app.empty = false;
                foregroundActivities = true;
                if (r.task != null && minLayer > 0) {
                    final int layer = r.task.mLayerRank;
                    if (layer >= 0 && minLayer > layer) {
                        minLayer = layer;
                    }
                }
                break;
            } else if (r.state == ActivityState.PAUSING || r.state == ActivityState.PAUSED) { // 处于暂停或已经暂停
                if (adj > ProcessList.PERCEPTIBLE_APP_ADJ) {
                    adj = ProcessList.PERCEPTIBLE_APP_ADJ;
                    app.adjType = "pausing";
                }
                if (procState > PROCESS_STATE_CUR_TOP) {
                    procState = PROCESS_STATE_CUR_TOP;
                }
                schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
                app.cached = false;
                app.empty = false;
                foregroundActivities = true;
            } else if (r.state == ActivityState.STOPPING) { 
                if (adj > ProcessList.PERCEPTIBLE_APP_ADJ) {
                    adj = ProcessList.PERCEPTIBLE_APP_ADJ;
                    app.adjType = "stopping";
                }
                // For the process state, we will at this point consider the
                // process to be cached.  It will be cached either as an activity
                // or empty depending on whether the activity is finishing.  We do
                // this so that we can treat the process as cached for purposes of
                // memory trimming (determing current memory level, trim command to
                // send to process) since there can be an arbitrary number of stopping
                // processes and they should soon all go into the cached state.
                if (!r.finishing) {
                    if (procState > ActivityManager.PROCESS_STATE_LAST_ACTIVITY) {
                        procState = ActivityManager.PROCESS_STATE_LAST_ACTIVITY;
                    }
                }
                app.cached = false;
                app.empty = false;
                foregroundActivities = true;
            } else {
                if (procState > ActivityManager.PROCESS_STATE_CACHED_ACTIVITY) {
                    procState = ActivityManager.PROCESS_STATE_CACHED_ACTIVITY;
                    app.adjType = "cch-act";
                }
            }
        }
        if (adj == ProcessList.VISIBLE_APP_ADJ) {
            adj += minLayer;
        }
    }

    if (adj > ProcessList.PERCEPTIBLE_APP_ADJ
            || procState > ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE) {
        if (app.foregroundServices) { // 前台service
            // The user is aware of this app, so make it visible.
            adj = ProcessList.PERCEPTIBLE_APP_ADJ;
            procState = ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE;
            app.cached = false;
            app.adjType = "fg-service";
            schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
        } else if (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 = ProcessList.SCHED_GROUP_DEFAULT;
        }
    }

    if (app == mHeavyWeightProcess) { // 解析init.rc启动的进程 AudioFlinger等
        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.cached = false;
            app.adjType = "heavy";
        }
        if (procState > ActivityManager.PROCESS_STATE_HEAVY_WEIGHT) {
            procState = ActivityManager.PROCESS_STATE_HEAVY_WEIGHT;
        }
    }

    if (app == mHomeProcess) { 
    // This is the process holding the activity the user last visited that is in a different process from the one they are currently in.
        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.cached = false;
            app.adjType = "home";
        }
        if (procState > ActivityManager.PROCESS_STATE_HOME) {
            procState = ActivityManager.PROCESS_STATE_HOME;
        }
    }
    // The time at which the previous process was last visible 前一个可见
    if (app == mPreviousProcess && app.activities.size() > 0) {
        if (adj > ProcessList.PREVIOUS_APP_ADJ) { // qian
            // 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.cached = false;
            app.adjType = "previous";
        }
        if (procState > ActivityManager.PROCESS_STATE_LAST_ACTIVITY) {
            procState = ActivityManager.PROCESS_STATE_LAST_ACTIVITY;
        }
    }

    // By default, we use the computed adjustment.  It may be changed if
    // there are applications dependent on our services or providers, but
    // this gives us a baseline and makes sure we don't get into an
    // infinite recursion.
    app.adjSeq = mAdjSeq;
    app.curRawAdj = adj;
    app.hasStartedServices = false;

    //备份进程
    if (mBackupTarget != null && app == mBackupTarget.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 > ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND) {
                procState = ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND;
            }
            app.adjType = "backup";
            app.cached = false;
        }
        if (procState > ActivityManager.PROCESS_STATE_BACKUP) {
            procState = ActivityManager.PROCESS_STATE_BACKUP;
        }
    }
    ...
    // service contentprovider相关的adj计算
}

2.2 ActivityStackSupervisor::resumedAppLocked 获取Top_app

ActivityRecord resumedAppLocked() {
    ActivityStack stack = mFocusedStack; // 焦点ActivityStack
    if (stack == null) {
        return null;
    }
    ActivityRecord resumedActivity = stack.mResumedActivity; // 当前正在运行的Activity
    if (resumedActivity == null || resumedActivity.app == null) {
        resumedActivity = stack.mPausingActivity;// 当前正在暂停的Activity
        if (resumedActivity == null || resumedActivity.app == null) {
            resumedActivity = stack.topRunningActivityLocked(); // 遍历ArrayList<TaskRecord>查询
        }
    }
    return resumedActivity;
}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,029评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,395评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,570评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,535评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,650评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,850评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,006评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,747评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,207评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,536评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,683评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,342评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,964评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,772评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,004评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,401评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,566评论 2 349

推荐阅读更多精彩内容