多多色-多人伦交性欧美在线观看-多人伦精品一区二区三区视频-多色视频-免费黄色视屏网站-免费黄色在线

國內(nèi)最全I(xiàn)T社區(qū)平臺 聯(lián)系我們 | 收藏本站
阿里云優(yōu)惠2
您當(dāng)前位置:首頁 > php開源 > 綜合技術(shù) > Android 7.0 ActivityManagerService(9) 進(jìn)程管理相關(guān)流程分析(3) computeOomAdjLocked

Android 7.0 ActivityManagerService(9) 進(jìn)程管理相關(guān)流程分析(3) computeOomAdjLocked

來源:程序員人生   發(fā)布時間:2017-02-24 11:18:42 閱讀次數(shù):4758次

這1篇博客,我們來分析1下AMS進(jìn)程管理流程中,負(fù)責(zé)計算進(jìn)程oom_adj值的computeOomAdjLocked函數(shù)。

從難度上來說,computeOomAdjLocked函數(shù)比updateOomAdjLocked函數(shù)簡單,由于它的職責(zé)更明確和單1。
但是,由于Android定義的oom_adj種類龐雜,使得這個函數(shù)的分支很多,細(xì)節(jié)顯得極為的繁瑣。
因此從功利的角度來看,大家知道這個函數(shù)的用處和大概脈絡(luò)便可。

不過對1個框架工程師而言,瀏覽源碼的耐心可能比寫代碼的能力更重要,因此我們還是耐著性子將代碼看完。
“RTFSC”,畢竟大神是這么告知我們的。

computeOomAdjLocked函數(shù)的代碼很長,
因此在這篇博客中,我們還分段進(jìn)行研究,然后試著進(jìn)行總結(jié)。

1、computeOomAdjLocked Part-I

private final int computeOomAdjLocked(ProcessRecord app, int cachedAdj, ProcessRecord TOP_APP,
        boolean doingAll, long now) { //之前的博客中提到過,updateOomAdjLocked函數(shù)每次更新oom_adj時,都會分配1個序號 //此處就是根據(jù)序號判斷是不是已處理過命令 if (mAdjSeq == app.adjSeq) { // This adjustment has already been computed. return app.curRawAdj;
    } //ProcessRecord對應(yīng)的ActivityThread不存在了 //修改其中的1些變量,此時的oom_adj為CACHED_APP_MAX_ADJ, //其意義我們在前1篇博客中已提到過 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);
    } //初始化1些變量 //這些變量的具體用處,在篇博客中我們不關(guān)注 //大家只用留意1下ProcessRecord的schedGroup、procState和oom_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(); //這個判斷沒啥意義,ProcessRecord中只有初始化時為maxAdj賦值 //maxAdj取值為UNKNOWN_ADJ,即最大的1001 if (app.maxAdj <= ProcessList.FOREGROUND_APP_ADJ) { //這部份代碼就是修改app的curSchedGroup,并將oom_adj設(shè)置為maxAdj //實際進(jìn)程中,應(yīng)當(dāng)是不會履行的的 ...................... } //保存當(dāng)前TOP Activity的狀態(tài) final int PROCESS_STATE_CUR_TOP = mTopProcessState; ...................... }

以上代碼就是computeOomAdjLocked函數(shù)的第1部份。
從代碼不難看出,這部份內(nèi)容的主要目的是:
1、根據(jù)參數(shù)及進(jìn)程的狀態(tài),決定是不是需要進(jìn)行后續(xù)的計算;
2、初始化1些變量。

2、computeOomAdjLocked Part-II
在第2部份,computeOomAdjLocked開始干“正事兒”了:

................. // Determine the importance of the process, starting with most // important to least, and assign an appropriate OOM adjustment. // 上面的這段注釋為全部computeOomAdjLocked函數(shù)“代言” int adj;
int schedGroup;
int procState;
boolean foregroundActivities = false;
BroadcastQueue queue; //若進(jìn)程包括正在前臺顯示的Activity if (app == TOP_APP) { // The last app on the list is the foreground app. adj = ProcessList.FOREGROUND_APP_ADJ; //單獨的1種schedGroup schedGroup = ProcessList.SCHED_GROUP_TOP_APP;
    app.adjType = "top-activity"; //當(dāng)前處理的是包括前臺Activity的進(jìn)程時,才會將該值置為true foregroundActivities = true;
    procState = PROCESS_STATE_CUR_TOP;
} else if (app.instrumentationClass != null) { //處理正在進(jìn)行測試的進(jìn)程 // 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) { //處理正在處理廣播的進(jìn)程 // 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; //根據(jù)處理廣播的Queue,決定調(diào)度策略 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) { //處理Service正在運行的進(jìn)程 // 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;

    procState = ActivityManager.PROCESS_STATE_SERVICE;
} else { //其它進(jìn)程,在后續(xù)進(jìn)程中再進(jìn)1步處理 // 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,即參數(shù)傳入的UNKNOW_ADJ adj = cachedAdj;
    procState = ActivityManager.PROCESS_STATE_CACHED_EMPTY;

    app.cached = true;
    app.empty = true;
    app.adjType = "cch-empty";
} ..................

以上代碼可以看做是computeOomAdjLocked的第2部份,從這部份代碼可以看出:
1、包括前臺Activity的進(jìn)程、運行測試類的進(jìn)程、處理廣播的進(jìn)程及包括正在運行服務(wù)的進(jìn)程,
其oom_adj均被賦值為FOREGROUND_APP_ADJ,即從LMK的角度來看,它們的重要性是1致的。
但這些進(jìn)程的procState不同,因而從AMS主動回收內(nèi)存的角度來看,它們的重要性不同。

另外,這些進(jìn)程的schedGroup不同。
之前的博客分析過,Process.java中提供了接口,可以調(diào)用Linux提供的接口函數(shù)設(shè)置schedGroup,使得進(jìn)程具有不同的調(diào)度策略。
從獲得CPU資源的能力來看,SCHED_GROUP_TOP_APP應(yīng)當(dāng)強于SCHED_GROUP_DEFAULT,
最后才輪到SCHED_GROUP_BACKGROUND。

2、對其它種類的進(jìn)程,這部份代碼先將它們的oom_adj設(shè)置為UNKNOW_ADJ,
proc_state置為PROCESS_STATE_CACHED_EMPTY,在后續(xù)流程中再作進(jìn)1步處理。

3、computeOomAdjLocked Part-III
這1部份代碼主要處理包括Activity,但是Activity不在前臺的進(jìn)程。

注意到這些進(jìn)程包括之條件到的正在處理廣播、服務(wù)或測試的進(jìn)程,和oom_adj暫時為UNKNOW_ADJ的進(jìn)程。
不過只有UNKNOW_ADJ對應(yīng)的進(jìn)程,才有可能進(jìn)行實際的更新。

.................. // Examine all activities if not already foreground. if (!foregroundActivities && activitiesSize > 0) { //之前分析updateOomAdjLocked的第1部份時,簡單提到過rankTaskLayersIfNeeded函數(shù) //該函數(shù)會更新包括Activity的Task的rankLayer //依照顯示層次從上到下,rankLayer逐步增加,對應(yīng)的最大值就是VISIBLE_APP_LAYER_MAX int minLayer = ProcessList.VISIBLE_APP_LAYER_MAX; //順次輪詢進(jìn)程中的Activity for (int j = 0; j < activitiesSize; j++) {
        final ActivityRecord r = app.activities.get(j); ................... //如果進(jìn)程包括可見Activity,即該進(jìn)程是個可見進(jìn)程 if (r.visible) { // App has a visible activity; only upgrade adjustment. if (adj > ProcessList.VISIBLE_APP_ADJ) { //adj大于VISIBLE_APP_ADJ時,才更新對應(yīng)的adj //之條件到的正在處理廣播、服務(wù)或測試的進(jìn)程,adj為FOREGROUND,是小于VISIBLE_APP_ADJ //因此不會在此更新 adj = ProcessList.VISIBLE_APP_ADJ;
                app.adjType = "visible";
            } if (procState > PROCESS_STATE_CUR_TOP) { //與oom_adj類似,在條件滿足時,更新procState procState = PROCESS_STATE_CUR_TOP;
            } //正在處理廣播、服務(wù)或測試的進(jìn)程,如果它們的調(diào)度策略為BACKGROUND //但又包括了可見Activity時,調(diào)度策略變更加DEFAULT 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) { //更新ranklayer minLayer = layer;
                 }
            } //發(fā)現(xiàn)可見Activity時,直接可以結(jié)束循環(huán) break;
        } else if (r.state == ActivityState.PAUSING || r.state == ActivityState.PAUSED) { //如果進(jìn)程包括處于PAUSING或PAUSED狀態(tài)的Activity時 //將其oom_adj調(diào)劑為“用戶可發(fā)覺”的的等級,這個等級還是很高的 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; //注意其實不會break } else if (r.state == ActivityState.STOPPING) { //包括處于Stopping狀態(tài)Activity的進(jìn)程,其oom_adj也被置為PERCEPTIBLE_APP_ADJ if (adj > ProcessList.PERCEPTIBLE_APP_ADJ) {
                adj = ProcessList.PERCEPTIBLE_APP_ADJ;
                app.adjType = "stopping";
            } ................ // 這類進(jìn)程將被看做潛伏的cached或empty進(jìn)程 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 { //只是含有cached-activity的進(jìn)程,僅調(diào)劑procState if (procState > ActivityManager.PROCESS_STATE_CACHED_ACTIVITY) {
                procState = ActivityManager.PROCESS_STATE_CACHED_ACTIVITY;
                app.adjType = "cch-act";
            }
        } if (adj == ProcessList.VISIBLE_APP_ADJ) { //不同可見進(jìn)程的oom_adj有1定的差異,處在下層的oom_adj越大 //即越老的Activity所在進(jìn)程,重要性越低 adj += minLayer;
        }
    }
} ..................

從上面的代碼可以看出,computeOomAdjLocked的第3部份處理包括Activity的進(jìn)程時,
進(jìn)程終究的oom_adj將由其中最要的Activity決定。
即進(jìn)程中存在可見Activity時,進(jìn)程的oom_adj就為VISIBLE_APP_ADJ;
否則,若進(jìn)程中存在處于PAUSING、PAUSED或STOPPING狀態(tài)的Activity時,進(jìn)程的oom_adj就為PERCEPTIBLE_APP_ADJ;
其余的進(jìn)程還是UNKNOW_ADJ。

4、computeOomAdjLocked Part-IV
computeOomAdjLocked的第4部份主要用于處理1些特殊的進(jìn)程。

............... if (adj > ProcessList.PERCEPTIBLE_APP_ADJ || procState > ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE) { //進(jìn)程包括前臺服務(wù)或被強迫在前臺運行時 //oom_adj被調(diào)劑為PERCEPTIBLE_APP_ADJ,只是procState略有不同 if (app.foregroundServices) { // 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;
    }
} //AMS的HeavyWeight進(jìn)程單獨處理 if (app == mHeavyWeightProcess) { 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;
    }
} //home進(jìn)程特殊處理 if (app == mHomeProcess) { 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;
    }
} //前臺進(jìn)程之前的1個進(jìn)程 if (app == mPreviousProcess && app.activities.size() > 0) { 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.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; //處理正在進(jìn)行backup工作的進(jìn)程 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) { .............. 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;
    }
} ..................

至此,我們應(yīng)當(dāng)可以看出computeOomAdjLocked處理1個進(jìn)程時,依照重要性由高到底的順序,
逐漸判斷該進(jìn)程是不是滿足對應(yīng)的條件。
雖然計算1個進(jìn)程的oom_adj時,會經(jīng)過上述所有的判斷,但當(dāng)1個進(jìn)程已滿足重要性較高的條件時,
后續(xù)的判斷實際上不會更改它已取得的oom_adj。

上面4部份的邏輯基本上以下圖所示:

大圖鏈接

后續(xù)的處理邏輯,依然滿足上述規(guī)則。
只是在斟酌含有Service和Provider的進(jìn)程時,整體流程顯得極為復(fù)雜,
融入上圖的本錢太高,因此就不再畫圖了。

5、computeOomAdjLocked Part-V
computeOomAdjLocked的第5部份,主要是處理包括服務(wù)的進(jìn)程。
這1部份代碼寫的比較繁瑣,復(fù)雜度應(yīng)當(dāng)超過了前4部份的和,
因此我們進(jìn)1步分段說明。

1、Unbounded Service的處理
當(dāng)進(jìn)程中包括Unbounded Service時,進(jìn)程的oom_adj先依照Unbounded Service的處理方式進(jìn)行調(diào)劑。

................. //順次處理進(jìn)程中的每個Service 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); //Service被已Unbounded Service的方式啟動過 if (s.startRequested) {
        app.hasStartedServices = true; //調(diào)劑procState if (procState > ActivityManager.PROCESS_STATE_SERVICE) {
            procState = ActivityManager.PROCESS_STATE_SERVICE;
        } if (app.hasShownUi && app != mHomeProcess) { // If this process has shown some UI, let it immediately // go to the LRU list because it may be pretty heavy with // UI stuff.  We'll tag it with a label just to help // debug and understand what is going on. // 唯一含有服務(wù)且顯示過UI的進(jìn)程,由于其占用內(nèi)存可能較多,因此需要盡早回收 // 故此處不調(diào)劑其oom_adj if (adj > ProcessList.SERVICE_ADJ) {
                app.adjType = "cch-started-ui-services";
            }
        } else { if (now < (s.lastActivity + ActiveServices.MAX_SERVICE_INACTIVITY)) { //MAX_SERVICE_INACTIVITY為activity啟動service后,系統(tǒng)最多保存Service的時間 // This service has seen some activity within // recent memory, so we will keep its process ahead // of the background processes. //此時進(jìn)程的oom_adj就能夠被調(diào)劑為后臺服務(wù)對應(yīng)的SERVICE_ADJ //adj大于500的進(jìn)程均會受此判斷的影響 if (adj > ProcessList.SERVICE_ADJ) {
                    adj = ProcessList.SERVICE_ADJ;
                    app.adjType = "started-services";
                    app.cached = false;
                }
            } //處理Service存在超時的情況,可見超時時也不會調(diào)劑oom_adj // If we have let the service slide into the background // state, still have some text describing what it is doing // even though the service no longer has an impact. if (adj > ProcessList.SERVICE_ADJ) {
                app.adjType = "cch-started-services";
            }
        }
    } .................

從上面的代碼可以看出,當(dāng)進(jìn)程中含有Unbounded Service時,
如果進(jìn)程之前沒有啟動過UI,且Unbounded Service存活的時間沒有超時,
進(jìn)程的oom_ad才能被調(diào)劑為SERVICE_ADJ;否則進(jìn)程的oom_adj依然是UNKNOW_ADJ或其它大于500的值。

2、Bounded Service的處理
這部份代碼緊接著上述流程。
即進(jìn)程將先依照Unbounded Service的方式調(diào)劑oom_adj,
然后再依照Bounded Service的方式進(jìn)1步調(diào)劑。

固然,若Service僅為Unbounded Service或Bounded Service中的1種時,
computeOomAdjLocked函數(shù)的第5部份,只會依照1種方式調(diào)劑oom_adj。

Bounded Service的處理方式,遠(yuǎn)比Unbounded Service復(fù)雜,依賴于客戶真?zhèn)€oom_adj和綁定服務(wù)時使用的flag。

.................... //如果該Service還被客戶端Bounded,即是Bounded 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--) {
        ArrayList<ConnectionRecord> clist = s.connections.valueAt(conni); //客戶端可以通過1個Connection以不同的參數(shù)綁定Service //因此,1個Service可以對應(yīng)多個Connection,1個Connection又對應(yīng)多個ConnectionRecord //這里順次處理每個ConnectionRecord for (int i = 0;
                i < clist.size() && (adj > ProcessList.FOREGROUND_APP_ADJ || schedGroup == ProcessList.SCHED_GROUP_BACKGROUND || procState > ActivityManager.PROCESS_STATE_TOP);
                i++) {
            ConnectionRecord cr = clist.get(i); if (cr.binding.client == app) { // Binding to ourself is not interesting. continue;
            } //當(dāng)BIND_WAIVE_PRIORITY為1時,客戶端就不會影響服務(wù)端 //if中的流程就能夠略去;否則,客戶端就會影響服務(wù)端 if ((cr.flags&Context.BIND_WAIVE_PRIORITY) == 0) {
                ProcessRecord client = cr.binding.client; //計算出客戶端進(jìn)程的oom_adj //由此可看出Android oom_adj的計算多么麻煩 //要是客戶端進(jìn)程中,又有個服務(wù)進(jìn)程被綁定,那末將再計算其客戶端進(jìn)程的oom_adj?! int clientAdj = computeOomAdjLocked(client, cachedAdj,
                        TOP_APP, doingAll, now);

                int clientProcState = client.curProcState; if (clientProcState >= ActivityManager.PROCESS_STATE_CACHED_ACTIVITY) { // If the other app is cached for any reason, for purposes here // we are going to consider it empty.  The specific cached state // doesn't propagate except under certain conditions. clientProcState = ActivityManager.PROCESS_STATE_CACHED_EMPTY;
                } String adjType = null; //BIND_ALLOW_OOM_MANAGEMENT置為1時,先依照通常的處理方式,調(diào)劑服務(wù)端進(jìn)程的adjType if ((cr.flags&Context.BIND_ALLOW_OOM_MANAGEMENT) != 0) { //與前面分析Unbounded Service基本1致,若進(jìn)程顯示過UI或Service超時 //會將clientAdj修改成當(dāng)前進(jìn)程的adj,即不需要斟酌客戶端進(jìn)程了 if (app.hasShownUi && app != mHomeProcess) { if (adj > clientAdj) {
                            adjType = "cch-bound-ui-services";
                        }
                        app.cached = false;
                        clientAdj = adj;
                        clientProcState = procState;
                    } else { if (now >= (s.lastActivity + ActiveServices.MAX_SERVICE_INACTIVITY)) { if (adj > clientAdj) {
                                adjType = "cch-bound-services";
                            }
                            clientAdj = adj;
                        }
                    }
                } //根據(jù)情況,依照clientAdj調(diào)劑當(dāng)前進(jìn)程的adj if (adj > clientAdj) { // If this process has recently shown UI, and // the process that is binding to it is less // important than being visible, then we don't // care about the binding as much as we care // about letting this process get into the LRU // list to be killed and restarted if needed for // memory. // 上面的注釋很清楚 if (app.hasShownUi && app != mHomeProcess && clientAdj > ProcessList.PERCEPTIBLE_APP_ADJ) {
                        adjType = "cch-bound-ui-services";
                    } else { //以下的流程表明,client和flag將同時影響Service進(jìn)程的adj if ((cr.flags&(Context.BIND_ABOVE_CLIENT |Context.BIND_IMPORTANT)) != 0) { //從這里再次可以看出,Service重要性小于等于Client adj = clientAdj >= ProcessList.PERSISTENT_SERVICE_ADJ ? clientAdj : ProcessList.PERSISTENT_SERVICE_ADJ; //BIND_NOT_VISIBLE表示不將服務(wù)端當(dāng)作visible進(jìn)程看待 //因而,即便客戶真?zhèn)€adj小于PERCEPTIBLE_APP_ADJ,service也只能取到PERCEPTIBLE_APP_ADJ } else if ((cr.flags&Context.BIND_NOT_VISIBLE) != 0 && clientAdj < ProcessList.PERCEPTIBLE_APP_ADJ && adj > ProcessList.PERCEPTIBLE_APP_ADJ) {
                            adj = ProcessList.PERCEPTIBLE_APP_ADJ;
                        } else if (clientAdj >= ProcessList.PERCEPTIBLE_APP_ADJ) {
                            adj = clientAdj;
                        } else { if (adj > ProcessList.VISIBLE_APP_ADJ) {
                                adj = Math.max(clientAdj, ProcessList.VISIBLE_APP_ADJ);
                            }
                        } if (!client.cached) {
                            app.cached = false;
                        }
                        adjType = "service";
                    }
                } if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) { //進(jìn)1步更具client調(diào)劑當(dāng)前進(jìn)程的procState、schedGroup等 ................... } else { ................... } ................. if (procState > clientProcState) {
                    procState = clientProcState;
                } //其它參數(shù)的賦值 ................. } if ((cr.flags&Context.BIND_TREAT_LIKE_ACTIVITY) != 0) {
                app.treatLikeActivity = true;
            } //取出ConnectionRecord所在的Activity final ActivityRecord a = cr.activity; //BIND_ADJUST_WITH_ACTIVITY值為1時,表示服務(wù)端可以根據(jù)客戶端Activity的oom_adj作出相應(yīng)的調(diào)劑 if ((cr.flags&Context.BIND_ADJUST_WITH_ACTIVITY) != 0) { if (a != null && adj > ProcessList.FOREGROUND_APP_ADJ && (a.visible || a.state == ActivityState.RESUMED || a.state == ActivityState.PAUSING)) { //BIND_ADJUST_WITH_ACTIVITY置為1,且綁定的activity可見或在前臺時, //Service進(jìn)程的oom_adj可以變成FOREGROUND_APP_ADJ adj = ProcessList.FOREGROUND_APP_ADJ; //BIND_NOT_FOREGROUND為0時,才準(zhǔn)予調(diào)劑Service進(jìn)程的調(diào)度優(yōu)先級 if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) { if ((cr.flags&Context.BIND_IMPORTANT) != 0) {
                        schedGroup = ProcessList.SCHED_GROUP_TOP_APP;
                    } else {
                        schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
                    }
                } //改變其它參數(shù) app.cached = false;
                app.adjType = "service";
                app.adjTypeCode = ActivityManager.RunningAppProcessInfo .REASON_SERVICE_IN_USE;
                app.adjSource = a;
                app.adjSourceProcState = procState;
                app.adjTarget = s.name;
            }
        }
    }
} ....................

以上就是計算含有Service的進(jìn)程的oom_adj的全部進(jìn)程。
從代碼來看當(dāng)進(jìn)程僅含有Unbounded Service時,全部計算進(jìn)程比較單純,只要進(jìn)程沒有顯示過UI,且Service的存在沒有超時時,
進(jìn)程的oom_adj就被調(diào)劑為SERVICE_ADJ。
當(dāng)進(jìn)程含有的是Bounded Service時,全部計算的復(fù)雜度就飆升了,
它將斟酌到Bound時使用的flag及客戶真?zhèn)€情況,綜合調(diào)劑進(jìn)程的oom_adj。

不過正由于Bounded Service的處理流程依賴于大量的flag,而這些flag基本很少用到,
因此個人懷疑這些代碼都是些實驗性質(zhì)的代碼。手機真正運行時,使用的頻率可能其實不高。

從另外一個角度來看,這么設(shè)計仿佛也是公道的。
當(dāng)1個進(jìn)程中的Service被許多客戶端需求時,確切應(yīng)當(dāng)給這個進(jìn)程機會,提高自己的重要性。
不知道如此細(xì)粒度的處理,Google是如何進(jìn)行測試,并得到有效結(jié)論的?雖不明,但覺厲啊。

6、computeOomAdjLocked Part-VI
computeOomAdjLocked的第6部份主要是處理含有ContentProvider的進(jìn)程。
由于ContentProvider也有客戶端,因此一樣需要根據(jù)客戶端進(jìn)程調(diào)劑當(dāng)前進(jìn)程的oom_adj。

....................
//順次處理進(jìn)程中的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的客戶端
    for (int i = cpr.connections.size()-1; i >= 0 && (adj > ProcessList.FOREGROUND_APP_ADJ
                    || schedGroup == ProcessList.SCHED_GROUP_BACKGROUND
                    || procState > ActivityManager.PROCESS_STATE_TOP); i--) {
        ContentProviderConnection conn = cpr.connections.get(i); ProcessRecord client = conn.client; if (client == app) {
            // Being our own client is not interesting.
            continue; }
        //計算客戶真?zhèn)€oom_adj
        int clientAdj = computeOomAdjLocked(client, cachedAdj, TOP_APP, doingAll, now); int clientProcState = client.curProcState; if (clientProcState >= ActivityManager.PROCESS_STATE_CACHED_ACTIVITY) {
            // If the other app is cached for any reason, for purposes here
            // we are going to consider it empty.
            clientProcState = ActivityManager.PROCESS_STATE_CACHED_EMPTY; }
        //與Unbounded Service的處理基本類似
        if (adj > clientAdj) {
            if (app.hasShownUi && app != mHomeProcess
                    && clientAdj > ProcessList.PERCEPTIBLE_APP_ADJ) {
                app.adjType = "cch-ui-provider"; } else {
                //根據(jù)c
生活不易,碼農(nóng)辛苦
如果您覺得本網(wǎng)站對您的學(xué)習(xí)有所幫助,可以手機掃描二維碼進(jìn)行捐贈
程序員人生
------分隔線----------------------------
分享到:
------分隔線----------------------------
關(guān)閉
程序員人生
主站蜘蛛池模板: 国产精品久久现线拍久青草 | 亚洲精品在线第一页 | 午夜伊人 | www.国产一区二区三区 | 在线播放性xxx欧美 在线播放亚洲美女视频网站 | 久久久亚洲精品国产 | 爱色aⅴ | 久久免费精品一区二区 | 91色久| 一级毛片a免费播放王色 | 国产毛片a级 | 国产在线精品福利91香蕉 | 亚洲免费片 | 日韩专区亚洲精品欧美专区 | 亚洲欧美成人永久第一网站 | 精品久久久久久久一区二区手机版 | 久久精品国产400部免费看 | 欧美另类videos粗暴黑人 | 一级做a爰片久久毛片欧美 一级做a爰片久久毛片人呢 | 国产在线精品福利大全 | 久久91在线 | 欧美黑人性生活 | 国产suv精品 | 国产亚洲综合精品一区二区三区 | 武则天a级片 | 波多野结衣在线不卡 | 不卡视频一区二区三区 | 亚洲精品乱码久久久久久蜜桃欧美 | 欧美特级特黄a大片免费 | 久久久国产成人精品 | 中文字幕无线码中文字幕免费 | 欧美偷 | 最近中文字幕免费mv视频8 | 91在线 | porny | 欧美 | 在线观看www日本免费网站 | 亚洲欧美综合精品成 | free性欧美69| 国产国语一级a毛片高清视频 | 国产免费福利视频一区二区 | 亚洲情人网 | 免费a网站 |