深入AMS源碼(四)——ActivityManagerService的進程管理

1、AMS中的進程管理

final ArrayList<ProcessRecord> mLruProcesses = new ArrayList<ProcessRecord>(); 

在AMS的內部屬性中使用mLruProcesses集合保存所有的進程信息,AMS將所有進程按照優先級從低到高的順序保存着對應的ProcessRecord信息,即排在前面的進程優先級越低,當系統內存不足時優先被Killer殺死;

在AMS的工作過程中,會不斷調用updateLruProcessLocked()方法進行進程排序,在mLruProcesses()中保存按照以下規則保存數據
在這裏插入圖片描述
在AMS中越重要的進程會放在mLruProcesses集合的最後面,正在使用交互的進程會保存在最後,然後按照其他進程、Service進程、Activity進程的順序重要行逐步增加,Activity進程的重要性最高,爲了區分各個進程的位置,AMS中引入mLruProcessServiceStart和mLruProcessActivityStart變量保存二者的起始位置,在添加時當進程中包含活動則添加到mLruProcessActivityStart之後,如果不包含活動但包含Service服務,則添加到mLruProcessServiceStart之後;

  • updateLruProcessLocked源碼
final void updateLruProcessLocked(ProcessRecord app, boolean activityChange,
            ProcessRecord client) {
        final boolean hasActivity = app.activities.size() > 0 || app.hasClientActivities
                || app.treatLikeActivity || app.recentTasks.size() > 0;//1、
        final boolean hasService = false; 
        if (!activityChange && hasActivity) { // 如果activityChange爲false則無需改變位置
            return;
        }

        mLruSeq++; // 更新編號
        final long now = SystemClock.uptimeMillis();
        app.lastActivityTime = now; // 保存更新的時間

        if (hasActivity) { // 如果包含Activity,
            final int N = mLruProcesses.size();
            if (N > 0 && mLruProcesses.get(N-1) == app) { 
                return;
            }
        } else {
            if (mLruProcessServiceStart > 0 // 不包含Activit但已經存在其他段的最末尾,也無需更新
                    && mLruProcesses.get(mLruProcessServiceStart-1) == app) {
                return;
            }
        }

        int lrui = mLruProcesses.lastIndexOf(app); // 獲取目前位置的index
        if (app.persistent && lrui >= 0) {
            return;
        }
        if (lrui >= 0) { 
            if (lrui < mLruProcessActivityStart) { // 如果index小於mLruProcessActivityStart,則Activity段前移一位
                mLruProcessActivityStart--;
            }
            if (lrui < mLruProcessServiceStart) {//如果index小於mLruProcessServiceStart,則Activity段前移一位
                mLruProcessServiceStart--;
            }
            mLruProcesses.remove(lrui); //移除原來的app信息
        }

        int nextIndex; // 
        if (hasActivity) {
            final int N = mLruProcesses.size();
            if ((app.activities.size() == 0 || app.recentTasks.size() > 0)
                    && mLruProcessActivityStart < (N - 1)) {
                mLruProcesses.add(N - 1, app); // 如果進程不存在活動,但recentTasks存在任務則添加到最後位置
                final int uid = app.info.uid;
                for (int i = N - 2; i > mLruProcessActivityStart; i--) {
                    ProcessRecord subProc = mLruProcesses.get(i);
                    if (subProc.info.uid == uid) { // 遍歷集合中進程,匹配uid相等的進程
                        if (mLruProcesses.get(i - 1).info.uid != uid) {//處理其他進程,將該用戶進程前移,其他進程後移
                            ProcessRecord tmp = mLruProcesses.get(i);
                            mLruProcesses.set(i, mLruProcesses.get(i - 1));
                            mLruProcesses.set(i - 1, tmp);
                            i--;
                        }
                    } else {
                        break;
                    }
                }
            } else {
                mLruProcesses.add(app); // 直接添加進程信息
            }
            nextIndex = mLruProcessServiceStart;
        } else if (hasService) { 存在Service服務
            mLruProcesses.add(mLruProcessActivityStart, app); // 保存在Service服務的開始位置
            nextIndex = mLruProcessServiceStart;
            mLruProcessActivityStart++; // mLruProcessActivityStart後移
        } else  {
            int index = mLruProcessServiceStart;
            if (client != null) {
                int clientIndex = mLruProcesses.lastIndexOf(client);//獲取當前客戶端最高級的位置
                if (clientIndex <= lrui) {
                    clientIndex = lrui; // 如果最高級小則賦值最高級爲lrui
                }
                if (clientIndex >= 0 && index > clientIndex) {
                    index = clientIndex; 
                }
            }
            mLruProcesses.add(index, app); // 保存在頭部位置
            nextIndex = index-1;
            mLruProcessActivityStart++;
            mLruProcessServiceStart++;
        }

        for (int j=app.connections.size()-1; j>=0; j--) {
            ConnectionRecord cr = app.connections.valueAt(j);
            if (cr.binding != null && !cr.serviceDead && cr.binding.service != null
                    && cr.binding.service.app != null
                    && cr.binding.service.app.lruSeq != mLruSeq
                    && !cr.binding.service.app.persistent) {
                nextIndex = updateLruProcessInternalLocked(cr.binding.service.app, now, nextIndex,
                        "service connection", cr, app);
            }
        }
        for (int j=app.conProviders.size()-1; j>=0; j--) {
            ContentProviderRecord cpr = app.conProviders.get(j).provider;
            if (cpr.proc != null && cpr.proc.lruSeq != mLruSeq && !cpr.proc.persistent) {
                nextIndex = updateLruProcessInternalLocked(cpr.proc, now, nextIndex,
                        "provider reference", cpr, app);
            }
        }
    }

在updateLruProcessLocked()中主要執行流程:

  1. 判斷進程中是否包含活動,如果activityChange爲false則無需改變位置
  2. 如果當前進程存在活動信息,則判斷當前進程是不是在集合的最後一位,如果是則無需變換位置
  3. 從集合中取出進程本身的位置index,判斷mLruProcessActivityStart和mLruProcessServiceStart在移除進程後是否需要前移,並從集合中移除進程對象
  4. 如果進程中包含Activity,則直接添加進程到集合最後,但如果不包含活動只是recentTasks存在執行的任務則替換爲集合的最後一個,然後遍歷集合,這裏遍歷的目的是爲了集合進程的公平性,在一個用戶的進程被插在最後時,該用戶的其他進程需要前移,其他用戶的進程需要後移;
  5. 對於Service服務則直接保存在服務段的首位,然後後移mLruProcessActivityStart位置
  6. 對於其他進程則保存在頭部位置,但保存的原則就是不能超過其客戶端爲優先級
  7. 最後調用updateLruProcessInternalLocked()更新綁定服務進程和包含ContentProvider的進程信息

關於AMS中進程的管理就分析結束了,簡單來說就是AMS會自動更新集合中進程 的位置,從而區分進程的區域和優先級部分,下面一起看下Android 中的進程管理機制;

2、Android與Linux協作內存管理

Android的內存管理實際是通過與Linux協作完成的,Linux通過OOM KIller機制通知Android端執行內存釋放操作,關於OOM機制主要包含以下特點:

  1. 在Android中運行一個叫OOM進程,該進程啓動後首先會向Linux內核中註冊成爲OOM Killer
  2. 當內核內存管理模塊檢測到內存低時會通知OOM進程,然後OOM Killer執行內存釋放
  3. Android在啓動一個新的進程時,AMS會把該進程的oom_adj值告訴 OOM Killer,oom_adj值表示進程的優先級(Android中 0 ~ 15)值越低則越重要,所謂的前臺進程、後臺進程、空進程最後都會反應在oom_adj值上;
  4. OOM Killer收到內存釋放的消息後,按照預先設置的優先級開始強制退出低優先級的進程

2.1、AMS進程的優先級(在OOM 中設置 oom_adj的值)

在AMS執行過程中會不斷的更新進程的優先級,主要體現是根據進程條件設置進程中對應的adj信息,然後將賦值的adj更新到OOM機制中改變進程的等級信息,Android中區分進程的原則

  • 前臺進程 :ForeGround進程表示當前用戶正在交互的進程,需要滿足以下條件
  1. 具備正在可交互的前臺Activity
  2. 包含和前臺交互Activity綁定的Service服務
  3. 含有一個正在運行的前臺服務,即Service中調用了startForGround()
  4. Service正在執行系列的生命週期(onxxx())方法
  5. Receiver執行onReceive()
  • 可視進程:Visiable進程表示當前對用戶可見的進程,滿足以下條件
  1. 具備可視的Activit,這裏的可視指的是調用了onPause()之後處於可見但不交互的狀態
  2. 具備服務於可視Activity的Service服務
  • 服務進程
  1. 具備正常調用startService()啓動運行的Service服務,但不具備上面兩個條件,沒有和前臺或可視的Activity交互,只是服務自己在執行數據處理
  • 後臺進程
  1. 不滿足上面的三個進程條件,但具備與用戶不可見的Activity,即執行過onStop()之後的活動界面
  • 後臺空進程:沒有任何運行組件的進程

2.2、updateOomAdjLocked()

在前面的ActivityManagerService的內存管理分析知道,程序在activityIdleInternalLocked()的最後調用了trimApplications()執行進程的管理

final void trimApplicationsLocked() {
        for (i=mRemovedProcesses.size()-1; i>=0; i--) { // 1、刪除mRemoveProcess進程中的數據
12210      final ProcessRecord app = mRemovedProcesses.get(i); // 獲取進程app
12211      if (app.activities.size() == 0&& app.curReceiver == null && app.services.size() == 0) {//確定進程爲空
12218                    if (app.pid > 0 && app.pid != MY_PID) {
12219                        app.kill("empty", false); // 直接殺死進程
12220                    } else {
12222                        app.thread.scheduleExit(); // 執行進程退出
12226                    }
12227                    cleanUpApplicationRecordLocked(app, false, -1);
12228                    mRemovedProcesses.remove(i); // 移除進程信息
12235                }
12236            }
    updateOomAdjLocked() //2、爲所有的進程更新 oom adj 的值
}

trimApplications()中直接調用 trimApplicationsLocked()方法,執行刪除mRemovedProcesses集合中保存的進程,mRemovedProcesses主要保存即將被清除的進程,一般mRemoveProcess集合中數據來源:

  1. 當進程被crash後會將該進程添加到集合中;
  2. 當程序出現ANR時且用戶點擊關閉程序時,將進程添加到集合中;
  3. 程序調用AMS.killBackgroundProcess()時,系統並不會直接殺死進程而是會將進程先添加到集合中;

程序遍歷mRemovedProcesses集合中的進程信息,然後判斷當前進程是否爲空進程,然後分別執行進程殺死和進程退出操作,最後從集合中清除進程信息,在清除mRemovedProcesses中進程後,調用updateOomAdjLocked()判斷系統是否支持OOM Killer,並更新所有進程的優先級和管理進程,在查看源碼之前先介紹下ProcessRecord類

  1. ProcessRecord內部屬性與OOM相關的變量
curAdj:進程當前的adj值,反應了進程的優先級
setAdj:上一個設置的adj的值
curRawAdj:第一次對app評級後計算的adj的值,
setRawAdj:刪一個curRawAdj設置的值
maxAdj:OOM的最大調整值

2.3、優先級計算和進程管理

updateOomAdjLocked()第二部分,主要計算每個進程的優先級,即oom_adj的值,如果底層Linux包含OOM Killer返回true,否則返回false;

final void updateOomAdjLocked() {
    final ActivityRecord TOP_ACT = resumedAppLocked(); // 1、獲取最頂部的resume的ActivityRecord對象
    final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;// 2、獲取頂部活動所在的進程
    final int N = mLruProcesses.size();
    
for (int i=mActiveUids.size()-1; i>=0; i--) {
    final UidRecord uidRec = mActiveUids.valueAt(i);
    uidRec.reset(); // 復位所有的UidRecord對象,UidRecord主要保存每個用戶的最高優先級進程
}

final int emptyProcessLimit = mConstants.CUR_MAX_EMPTY_PROCESSES; //獲取允許空進程的數量,此處返回16
final int cachedProcessLimit = mConstants.CUR_MAX_CACHED_PROCESSES - emptyProcessLimit; //獲取允許的後臺進程數16
//爲後臺進程、空進程開闢位置,此處計算結果爲(906-900+1)/2 = 3
int numSlots = (ProcessList.CACHED_APP_MAX_ADJ //
                - ProcessList.CACHED_APP_MIN_ADJ + 1) / 2;
int numEmptyProcs = N - mNumNonCachedProcs - mNumCachedHiddenProcs; // 計算當前系統中空進程的數量
int emptyFactor = numEmptyProcs/numSlots;// 計算每個slot中保存的進程數量

 int curCachedAdj = ProcessList.CACHED_APP_MIN_ADJ; // 後臺進程的adj= 900
        int nextCachedAdj = curCachedAdj+1; // 下一個位置+1
        int curEmptyAdj = ProcessList.CACHED_APP_MIN_ADJ; // 空進程adj=900
        int nextEmptyAdj = curEmptyAdj+2; // 下一個位置+2

for (int i=N-1; i>=0; i--) {
    ProcessRecord app = mLruProcesses.get(i); // 遍歷所有的進程ProcessRecord ,計算oom_adj的值
    if (!app.killedByAm && app.thread != null) {
        computeOomAdjLocked(app, ProcessList.UNKNOWN_ADJ, TOP_APP, true, now); 
          if (app.curAdj >= ProcessList.UNKNOWN_ADJ) {
                    switch (app.curProcState) {
                        case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY:
                        case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT:
                        case ActivityManager.PROCESS_STATE_CACHED_RECENT:
                            app.curRawAdj = curCachedAdj; //賦值後臺進程
                            app.curAdj = app.modifyRawOomAdj(curCachedAdj);
                            if (curCachedAdj != nextCachedAdj) { 
                                stepCached++; // 累計當前adj值中保存的進程數
                                if (stepCached >= cachedFactor) { // 超過每個slot數量後使用下一個next slot位置
                                    stepCached = 0;
                                    curCachedAdj = nextCachedAdj;
                                    nextCachedAdj += 2;
                                    if (nextCachedAdj > ProcessList.CACHED_APP_MAX_ADJ) {
                                        nextCachedAdj = ProcessList.CACHED_APP_MAX_ADJ;
                                    }
                                }
                            }
                            break;
                        default:
                            app.curRawAdj = curEmptyAdj; // 賦值空進程
                            app.curAdj = app.modifyRawOomAdj(curEmptyAdj);
                            break;
                    }
                }
     }
  }
}

for (int i=N-1; i>=0; i--) {
            ProcessRecord app = mLruProcesses.get(i);
            if (!app.killedByAm && app.thread != null) {
                applyOomAdjLocked(app, true, now, nowElapsed); // 更新進程的adj值
                switch (app.curProcState) {
                    case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY:
                    case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT:
                        mNumCachedHiddenProcs++;
                        numCached++; // 計算後臺進程
                        if (numCached > cachedProcessLimit) { // 如果後臺進程超過上限則殺掉進程
                            app.kill("cached #" + numCached, true);
                        }
                        break;
                    case ActivityManager.PROCESS_STATE_CACHED_EMPTY:
                    //系統內部會定義一個允許保留空進程的數量且不需要執行回收的,當超過此數量則執行殺死
                        if (numEmpty > mConstants.CUR_TRIM_EMPTY_PROCESSES 
                                && app.lastActivityTime < oldTime) {//並且當前進程空閒時間超過設置要求的時間30min
                            app.kill("empty for "
                                    + ((oldTime + ProcessList.MAX_EMPTY_TIME - app.lastActivityTime)
                                    / 1000) + "s", true);
                        } else {
                            numEmpty++;
                            if (numEmpty > emptyProcessLimit) {// 空進程超過限制殺掉進程,此處設置爲16
                                app.kill("empty #" + numEmpty, true);
                            }
                        }
                        break;
                    default:
                        mNumNonCachedProcs++;
                        break;
                }
                //對於單獨進程的空進程,直接殺死進程
                if (app.isolated && app.services.size() <= 0 && app.isolatedEntryPoint == null) {
                    app.kill("isolated not needed", true);
                } else {
                    final UidRecord uidRec = app.uidRecord;
                    if (uidRec != null) {
                        uidRec.ephemeral = app.info.isInstantApp();
                        if (uidRec.curProcState > app.curProcState) { // 更新用戶的最高優先級
                            uidRec.curProcState = app.curProcState;
                        }
                    }
                }
                if (app.curProcState >= ActivityManager.PROCESS_STATE_HOME
                        && !app.killedByAm) {
                    numTrimming++; // 統計優先級低於Home進程的,表明此更加進程不重要
                }
            }
        }

在updateOomAdjLocked()中主要是計算進程的優先級,同時決定進程的生死,主要任務如下:

  1. 根據系統設置的常量計算系統允許的空進程、後臺進程的數量,設置空進程、後臺進程的adj值
  2. 遍歷所有的後臺進程,調用computeOomAdjLocked()計算進程值;
  3. 對於不能計算的則直接判斷是後臺進程還是空進程
  4. 調用applyOomAdjLocked()將進程的等級更新到OOM中
  5. 倒敘遍歷所有進程信息統計後臺進程數量,如果超過限定值則直接殺死進程,此處也顯示了集合中靠前的進程容易被殺死
  6. 對於空進程如果超過系統允許存在的數量,且空閒時間超過設置的30min,或總數超過設置的上限將殺死進程
  7. 對於單獨進程的空進程,直接殺死進程
  8. 統計優先級低於Home進程的數量,保存在numTrimming中

2.4、通知進程釋放內存

  final int numCachedAndEmpty = numCached + numEmpty; // 計算後臺進程和空進程數量之和,確定內存等級
        int memFactor;
        //如果後臺進程小於5,空進程小於8
        if (numCached <= mConstants.CUR_TRIM_CACHED_PROCESSES
                && numEmpty <= mConstants.CUR_TRIM_EMPTY_PROCESSES) {
            if (numCachedAndEmpty <= ProcessList.TRIM_CRITICAL_THRESHOLD) {//總計小於等於 3
                memFactor = ProcessStats.ADJ_MEM_FACTOR_CRITICAL; // 設置爲CRITICAL級別
            } else if (numCachedAndEmpty <= ProcessList.TRIM_LOW_THRESHOLD) { //總計不超過5
                memFactor = ProcessStats.ADJ_MEM_FACTOR_LOW; // 設置爲Low級別
            } else {
                memFactor = ProcessStats.ADJ_MEM_FACTOR_MODERATE; // 設置爲MODERATE級別
            }
        } else {
            memFactor = ProcessStats.ADJ_MEM_FACTOR_NORMAL; // 設置爲normal級別
        }
mLastMemoryLevel = memFactor; // 保存最新等級

        if (memFactor != ProcessStats.ADJ_MEM_FACTOR_NORMAL) { //當內存不爲normal時,需要執行內存回收
        if (mLowRamStartTime == 0) {
                mLowRamStartTime = now; // 保存低內存時間
            }
        }
        switch (memFactor) { //根據內存狀況,設置fgTrimLevel等級
                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;
            }
            for (int i=N-1; i>=0; i--) {
                ProcessRecord app = mLruProcesses.get(i);
                 if (app.curProcState >= ActivityManager.PROCESS_STATE_HOME
                        && !app.killedByAm) { // 處理優先級低於Home進程的,調用scheduleTrimMemory()方法執行內存回收
                         app.thread.scheduleTrimMemory(curLevel);
                 }else if (app.curProcState == ActivityManager.PROCESS_STATE_HEAVY_WEIGHT
                        && !app.killedByAm) { // 處理優先級爲HEAVY_WEIGHT
                    if (app.trimMemoryLevel < ComponentCallbacks2.TRIM_MEMORY_BACKGROUND
                            && app.thread != null) {
                      app.thread.scheduleTrimMemory(
                                    ComponentCallbacks2.TRIM_MEMORY_BACKGROUND);
                            }
                  }else { // 處理後臺進程
                    if ((app.curProcState >= ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND
                            || app.systemNoUi) && app.pendingUiClean) {
                        final int level = ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN;
                        if (app.trimMemoryLevel < level && app.thread != null) {
                            try {
                                app.thread.scheduleTrimMemory(level);
                            } catch (RemoteException e) {
                            }
                        }
                        app.pendingUiClean = false;
                    }
                    if (app.trimMemoryLevel < fgTrimLevel && app.thread != null) {
                        try {
                            app.thread.scheduleTrimMemory(fgTrimLevel);
                        } catch (RemoteException e) {
                        }
                    }
                    app.trimMemoryLevel = fgTrimLevel;
                }
      }

本部分主要是處理系統內存緊張時,通知運行的進程回收內存的機制:

  1. 首先計算系統中後臺進程和空進程的總數,並根據進程總數、空進程數、後臺進程數設置系統內存等級,空進程數、後臺進程數越少表示系統內存越緊張;
  2. 當內存等級不爲normal時,則表明系統內存緊張需要回收內存,此時需要通知進程釋放內存
  3. 針對不同進程調用app.thread.scheduleTrimMemory()方法執行內存回收,在scheduleTrimMemory()中最終回調到Activity的o nTrimMemory()方法

到此Android系統中對進程的管理就分析結束了,簡單的說就是會不斷計算和更新進程的優先級,然後根據設置的上限條件決定殺死哪些進程保留哪些進程,對於存活的進程Amdroid中也會進行進一步操作,就是通知進程的內存回收,程序根據系統中進程的存活量確定當前內存等級,然後根據進程優先級調用系統的內存回收方法,處理上面的整個流程外,還有一個方法沒有分析就是computeOomAdjLocked(),下面看看它是如何計算進程優先級的;

2.5、computeOomAdjLocked

11517        if (app == TOP_APP) {//1、 判斷當前進程是否爲TOP_APP,TOP_APP保存當前正在運行的ProcessRecord對象
11519            adj = FOREGROUND_APP_ADJ; // 設置爲FOREGROUND_APP_ADJ,優先級最高爲0
11520            schedGroup = Process.THREAD_GROUP_DEFAULT;
11521            app.adjType = "top-activity";
11522        } else if (app.instrumentationClass != null) { // 2、是否有自定義的instrumentationClass
11524            adj = FOREGROUND_APP_ADJ; // 設置爲優先級最高0
11525            schedGroup = Process.THREAD_GROUP_DEFAULT;
11526            app.adjType = "instrumentation";
11527        } else if (app.curReceiver != null || // 3、判斷有持久的Activity、Service、Receiver設置爲優先級最高 0
11528                (mPendingBroadcast != null && mPendingBroadcast.curApp == app)) {
11531            adj = FOREGROUND_APP_ADJ;
11532            schedGroup = Process.THREAD_GROUP_DEFAULT;
11533            app.adjType = "broadcast";
11534        } else if (app.executingServices.size() > 0) {
11537            adj = FOREGROUND_APP_ADJ;
11538            schedGroup = Process.THREAD_GROUP_DEFAULT;
11539            app.adjType = "exec-service";
11540        } else if (app.foregroundServices) { // 4、判斷當前是否爲前臺服務,設置優先級爲 1
11542            adj = PERCEPTIBLE_APP_ADJ; 
11543            schedGroup = Process.THREAD_GROUP_DEFAULT;
11544            app.adjType = "foreground-service";
11545        } else if (app.forcingToForeground != null) { //5、判斷用戶是否強制調到前臺,設置優先級1
11547            adj = PERCEPTIBLE_APP_ADJ;
11548            schedGroup = Process.THREAD_GROUP_DEFAULT;
11549            app.adjType = "force-foreground";
11550            app.adjSource = app.forcingToForeground;
11551        } else if (app == mHomeProcess) { //6、判斷是否爲Home進程,設置優先級 4
11559            adj = HOME_APP_ADJ;
11560            schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
11561            app.adjType = "home";
             }else if ((N=app.activities.size()) != 0) {
11568            N = app.activities.size();
11569            for (int j=0; j<N; j++) {
11570                if (app.activities.get(j).visible) {
11572                    app.hidden = false;
11573                    adj = VISIBLE_APP_ADJ;
11574                    schedGroup = Process.THREAD_GROUP_DEFAULT; //7、包含Activity數目大於0,且包含可見的Activity存在,設置1
11575                    app.adjType = "visible";
11576                    break;
11577                }
11578            }
11579        }else {
11582            app.hidden = true;
11583            app.empty = true;
11584            schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
11585            adj = hiddenAdj;  // 8、其他進程設置爲hiddenAdj
11586            app.adjType = "bg-empty";
11587        }
             app.adjSeq = mAdjSeq;
             app.curRawAdj = adj; // 賦值第一次估算的adj
           if (mBackupTarget != null && app == mBackupTarget.app) {//9、判斷是否爲mBackuptarget進程,設置優先級 2
11600            if (adj > BACKUP_APP_ADJ) {
11602                adj = BACKUP_APP_ADJ;
11603                app.adjType = "backup";
11604                app.hidden = false;
11605            }
11606        }
            // 10、判斷app中服務進程(進程中運行Service但不屬於前臺服務)
11608        if (app.services.size() != 0 && (adj > FOREGROUND_APP_ADJ
11609                || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
             Iterator<ServiceRecord> jt = app.services.iterator();
11614            while (jt.hasNext() && adj > FOREGROUND_APP_ADJ) {
11615                ServiceRecord s = jt.next(); //遍歷所有的Service
11616                if (s.startRequested) { // 根據startRequested判斷Service是否啓動,如果啓動過超過待機時間,設置優先級 2
                    adj = SECONDARY_SERVER_ADJ;
     }
  }
               if (cr.binding.client == app) { // 如果Service有綁定的app,則保護app的優先級即可
11649            continue; }
               int clientAdj = computeOomAdjLocked(client, myHiddenAdj, TOP_APP, true); // 遞歸調用第二次估算,以優先級高爲準
                ActivityRecord a = cr.activity; // 判斷是否進程是否包含resume或pause的Activity,設置爲優先級 0
11688           if (a != null && adj > FOREGROUND_APP_ADJ && (a.state == ActivityState.RESUMED
11690           || a.state == ActivityState.PAUSING)) {
11691           adj = FOREGROUND_APP_ADJ;
11692           schedGroup = Process.THREAD_GROUP_DEFAULT;
}
app.curAdj = adj; // 最終的adj
app.curSchedGroup = schedGroup;

關於應用進程優先級的更新細節見代碼註釋,源碼部分很多請讀者自行查看,主要就是根據前臺進程、前臺服務、後臺進程等設置對應的adj的值,在計算完adj之後每個進程都有了各自的優先級順序,將最終計算的結果保存在app.curAdj中,那此時就代表當前進程的優先級了;

本文從源碼的角度分析了AMS是如何管理內存的,主要分析了AMS如何管理應用程序進程管理、OOM Killer機制如何設備中的進程管理,通過對整個內存管理的學習,對系統程序之間的協調運作有了更好的認知,那關於AMS的部分就到此結束了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章