解讀Android進(jìn)程優(yōu)先級(jí)ADJ算法

一、概述

1.1 進(jìn)程

Android框架對(duì)進(jìn)程創(chuàng)建與管理進(jìn)行了封裝,對(duì)于APP開發(fā)者只需知道Android四大組件的使用。當(dāng)Activity, Service, ContentProvider, BroadcastReceiver任一組件啟動(dòng)時(shí),當(dāng)其所承載的進(jìn)程存在則直接使用,不存在則由框架代碼自動(dòng)調(diào)用startProcessLocked創(chuàng)建進(jìn)程。一個(gè)APP可以擁有多個(gè)進(jìn)程,多個(gè)APP也可以運(yùn)行在同一個(gè)進(jìn)程,通過配置Android:process屬性來決定。所以說對(duì)APP來說進(jìn)程幾乎是透明的,但了解進(jìn)程對(duì)于深刻理解Android系統(tǒng)是至關(guān)關(guān)鍵的。

1.2 優(yōu)先級(jí)

Android系統(tǒng)的設(shè)計(jì)理念正是希望應(yīng)用進(jìn)程能盡量長(zhǎng)時(shí)間地存活,以提升用戶體驗(yàn)。應(yīng)用首次打開比較慢,這個(gè)過程有進(jìn)程創(chuàng)建以及Application等信息的初始化,所以應(yīng)用在啟動(dòng)之后,即便退到后臺(tái)并非立刻殺死,而是存活一段時(shí)間,這樣下次再使用則會(huì)非???。對(duì)于APP同樣希望自身盡可能存活更長(zhǎng)的時(shí)間,甚至探索各種?;詈诳萍肌N飿O必反,系統(tǒng)處于低內(nèi)存的狀態(tài)下,手機(jī)性能會(huì)有所下降;系統(tǒng)繼續(xù)放任所有進(jìn)程一直存活,系統(tǒng)內(nèi)存很快就會(huì)枯竭而亡,那么需要合理地進(jìn)程回收機(jī)制。

到底該回收哪個(gè)進(jìn)程呢?系統(tǒng)根據(jù)進(jìn)程的組件狀態(tài)來決定每個(gè)進(jìn)程的優(yōu)先級(jí)值A(chǔ)DJ,系統(tǒng)根據(jù)一定策略先殺優(yōu)先級(jí)最低的進(jìn)程,然后逐步殺優(yōu)先級(jí)更低的進(jìn)程,依此類推,以回收預(yù)期的可用系統(tǒng)資源,從而保證系統(tǒng)正常運(yùn)轉(zhuǎn)。

談到優(yōu)先級(jí),可能有些人會(huì)想到Linux進(jìn)程本身有nice值,這個(gè)能決定CPU資源調(diào)度的優(yōu)先級(jí);而本文介紹Android系統(tǒng)中的ADJ,主要決定在什么場(chǎng)景下什么類型的進(jìn)程可能會(huì)被殺,影響的是進(jìn)程存活時(shí)間。ADJ與nice值兩者定位不同,不過也有一定的聯(lián)系,優(yōu)先級(jí)很高的進(jìn)程,往往也是用戶不希望被殺的進(jìn)程,是具有有一定正相關(guān)性。

1.3 ADJ級(jí)別

從Android 7.0開始,ADJ采用100、200、300;在這之前的版本ADJ采用數(shù)字1、2、3,這樣的調(diào)整可以更進(jìn)一步地細(xì)化進(jìn)程的優(yōu)先級(jí),比如在VISIBLE_APP_ADJ(100)與PERCEPTIBLE_APP_ADJ(200)之間,可以有ADJ=101、102級(jí)別的進(jìn)程。

  • 省去lmk對(duì)oom_score_adj的計(jì)算過程,Android 7.0之前的版本,oom_score_adj= oom_adj * 1000/17; 而Android 7.0開始,oom_score_adj= oom_adj,不用再經(jīng)過一次轉(zhuǎn)換。

1.4 LMK

為了防止剩余內(nèi)存過低,Android在內(nèi)核空間有l(wèi)owmemorykiller(簡(jiǎn)稱LMK),LMK是通過注冊(cè)shrinker來觸發(fā)低內(nèi)存回收的,這個(gè)機(jī)制并不太優(yōu)雅,可能會(huì)拖慢Shrinkers內(nèi)存掃描速度,已從內(nèi)核4.12中移除,后續(xù)會(huì)采用用戶空間的LMKD + memory cgroups機(jī)制,這里先不展開LMK講解。

進(jìn)程剛啟動(dòng)時(shí)ADJ等于INVALID_ADJ,當(dāng)執(zhí)行完attachApplication(),該該進(jìn)程的curAdj和setAdj不相等,則會(huì)觸發(fā)執(zhí)行setOomAdj()將該進(jìn)程的節(jié)點(diǎn)/proc/pid/oom_score_adj寫入oomadj值。下圖參數(shù)為Android原生閾值,當(dāng)系統(tǒng)剩余空閑內(nèi)存低于某閾值(比如147MB),則從ADJ大于或等于相應(yīng)閾值(比如900)的進(jìn)程中,選擇ADJ值最大的進(jìn)程,如果存在多個(gè)ADJ相同的進(jìn)程,則選擇內(nèi)存最大的進(jìn)程。 如下是64位機(jī)器,LMK默認(rèn)閾值圖:


在updateOomLevels()過程,會(huì)根據(jù)手機(jī)屏幕尺寸或內(nèi)存大小來調(diào)整scale,默認(rèn)大多數(shù)手機(jī)內(nèi)存都大于700MB,則scale等于1。對(duì)于64位手機(jī),閾值會(huì)更大些,具體如下。

private void updateOomLevels(int displayWidth, int displayHeight, boolean write) {
    ...
    for (int i=0; i<mOomAdj.length; i++) {
        int low = mOomMinFreeLow[i];
        int high = mOomMinFreeHigh[i];
        if (is64bit) {
            if (i == 4) high = (high*3)/2;
            else if (i == 5) high = (high*7)/4;
        }
        mOomMinFree[i] = (int)(low + ((high-low)*scale));
    }
}

二、解讀ADJ

接下來,解讀每個(gè)ADJ值都對(duì)應(yīng)著怎樣條件的進(jìn)程,包括正在運(yùn)行的組件以及這些組件的狀態(tài)幾何。這里重點(diǎn)介紹上圖標(biāo)紅的ADJ級(jí)別所對(duì)應(yīng)的進(jìn)程。

Android系統(tǒng)中計(jì)算各進(jìn)程ADJ算法的核心方法:

  • updateOomAdjLocked:更新adj,當(dāng)目標(biāo)進(jìn)程為空或者被殺則返回false;否則返回true;
  • computeOomAdjLocked:計(jì)算adj,返回計(jì)算后RawAdj值;
  • applyOomAdjLocked:應(yīng)用adj,當(dāng)需要?dú)⒌裟繕?biāo)進(jìn)程則返回false;否則返回true。

當(dāng)Android四大組件狀態(tài)改變時(shí)會(huì)updateOomAdjLocked()來同步更新相應(yīng)進(jìn)程的ADJ優(yōu)先級(jí)。這里需要說明一下,當(dāng)同一個(gè)進(jìn)程有多個(gè)決定其優(yōu)先級(jí)的組件狀態(tài)時(shí),取優(yōu)先級(jí)最高的ADJ作為最終的ADJ。另外,進(jìn)程會(huì)通過設(shè)置maxAdj來限定ADJ的上限。

關(guān)于分析進(jìn)程ADJ相關(guān)信息,常用命令如下:

  • dumpsys meminfo,
  • dumpsys activity o
  • dumpsys activity p

2.0 ADJ<0的進(jìn)程

  • NATIVE_ADJ(-1000):是由init進(jìn)程fork出來的Native進(jìn)程,并不受system管控;
  • SYSTEM_ADJ(-900):是指system_server進(jìn)程;
  • PERSISTENT_PROC_ADJ(-800): 是指在AndroidManifest.xml中申明android:persistent=”true”的系統(tǒng)(即帶有FLAG_SYSTEM標(biāo)記)進(jìn)程,persistent進(jìn)程一般情況并不會(huì)被殺,即便被殺或者發(fā)生Crash系統(tǒng)會(huì)立即重新拉起該進(jìn)程。
  • PERSISTENT_SERVICE_ADJ(-700):是由startIsolatedProcess()方式啟動(dòng)的進(jìn)程,或者是由system_server或者persistent進(jìn)程所綁定(并且?guī)в蠦IND_ABOVE_CLIENT或者BIND_IMPORTANT)的服務(wù)進(jìn)程

再來說一下其他優(yōu)先級(jí):

  • BACKUP_APP_ADJ(300):執(zhí)行bindBackupAgent()過程的進(jìn)程
  • HEAVY_WEIGHT_APP_ADJ(400): realStartActivityLocked()過程,當(dāng)應(yīng)用的privateFlags標(biāo)識(shí)PRIVATE_FLAG_CANT_SAVE_STATE的進(jìn)程;
  • HOME_APP_ADJ(600):當(dāng)類型為ACTIVITY_TYPE_HOME的應(yīng)用,比如桌面APP
  • PREVIOUS_APP_ADJ(700):用戶上一個(gè)使用的APP進(jìn)程

SYSTEM_ADJ(-900)

SYSTEM_ADJ: 僅指system_server進(jìn)程。在執(zhí)行SystemServer的startBootstrapServices()過程會(huì)調(diào)用AMS.setSystemProcess(),將system_server進(jìn)程的maxAdj設(shè)置成SYSTEM_ADJ,源碼如下:

public void setSystemProcess() {
    ...
    ApplicationInfo info = mContext.getPackageManager().getApplicationInfo(
            "android", STOCK_PM_FLAGS | MATCH_SYSTEM_ONLY);
    mSystemThread.installSystemApplicationInfo(info, getClass().getClassLoader());
    synchronized (this) {
        ProcessRecord app = newProcessRecordLocked(info, info.processName, false, 0);
        app.persistent = true;
        app.pid = MY_PID;
        app.maxAdj = ProcessList.SYSTEM_ADJ;
        app.makeActive(mSystemThread.getApplicationThread(), mProcessStats);
        synchronized (mPidsSelfLocked) {
            mPidsSelfLocked.put(app.pid, app);
        }
        updateLruProcessLocked(app, false, null);
        updateOomAdjLocked();
    }
    ...
}

但system_server的ADJ并非等于-900,而是-800?是由于startPersistentApps()過程直接把其adj重新被設(shè)置為-800,這算是一個(gè)小BUG,但 其實(shí)目前來說對(duì)于ADJ<0的進(jìn)程,LMK不會(huì)殺,兩者沒有什么區(qū)別。

PERSISTENT_PROC_ADJ(-800)

PERSISTENT_PROC_ADJ:在AndroidManifest.xml中申明android:persistent=”true”的系統(tǒng)(即帶有FLAG_SYSTEM標(biāo)記)進(jìn)程,稱之為persistent進(jìn)程。對(duì)于persistent進(jìn)程常規(guī)情況都不會(huì)被殺,一旦被殺或者發(fā)生Crash,進(jìn)程會(huì)立即重啟。

AMS.addAppLocked()或AMS.newProcessRecordLocked()過程會(huì)賦值:

場(chǎng)景1: newProcessRecordLocked

final ProcessRecord newProcessRecordLocked(ApplicationInfo info, String customProcess, boolean isolated, int isolatedUid) {
  String proc = customProcess != null ? customProcess : info.processName;
  final int userId = UserHandle.getUserId(info.uid);
  int uid = info.uid;
  ...
  final ProcessRecord r = new ProcessRecord(stats, info, proc, uid);
  if (!mBooted && !mBooting
          && userId == UserHandle.USER_SYSTEM
          && (info.flags & PERSISTENT_MASK) == PERSISTENT_MASK) {
      r.persistent = true;
      r.maxAdj = ProcessList.PERSISTENT_PROC_ADJ;
  }
  if (isolated && isolatedUid != 0) {
      r.maxAdj = ProcessList.PERSISTENT_SERVICE_ADJ;
  }
  return r;
}

在每一次進(jìn)程啟動(dòng)的時(shí)候都會(huì)判斷該進(jìn)程是否persistent進(jìn)程,如果是則會(huì)設(shè)置maxAdj=PERSISTENT_PROC_ADJ。 system_server進(jìn)程應(yīng)該也是persistent進(jìn)程?

場(chǎng)景2:addAppLocked

final ProcessRecord addAppLocked(ApplicationInfo info, String customProcess, boolean isolated, String abiOverride) {
    ProcessRecord app;
    if (!isolated) {
        app = getProcessRecordLocked(customProcess != null ? customProcess : info.processName,
                info.uid, true);
    } else {
        app = null;
    }

    if (app == null) {
        app = newProcessRecordLocked(info, customProcess, isolated, 0);
        updateLruProcessLocked(app, false, null);
        updateOomAdjLocked();
    }
    ...

    if ((info.flags & PERSISTENT_MASK) == PERSISTENT_MASK) {
        app.persistent = true;
        app.maxAdj = ProcessList.PERSISTENT_PROC_ADJ;
    }
    if (app.thread == null && mPersistentStartingProcesses.indexOf(app) < 0) {
        mPersistentStartingProcesses.add(app);
        startProcessLocked(app, "added application",
                customProcess != null ? customProcess : app.processName, abiOverride);
    }
    return app;
}

開機(jī)過程會(huì)先啟動(dòng)persistent進(jìn)程,并賦予maxAdj為PERSISTENT_PROC_ADJ,調(diào)用鏈:

startOtherServices()
  AMS.systemReady
    AMS.startPersistentApps
      AMS.addAppLocked

PERSISTENT_SERVICE_ADJ(-700)

PERSISTENT_SERVICE_ADJ: startIsolatedProcess()方式啟動(dòng)的進(jìn)程,或者是由system_server或者persistent進(jìn)程所綁定的服務(wù)進(jìn)程。

場(chǎng)景1:newProcessRecordLocked

final ProcessRecord newProcessRecordLocked(ApplicationInfo info, String customProcess, boolean isolated, int isolatedUid) {
  String proc = customProcess != null ? customProcess : info.processName;
  final int userId = UserHandle.getUserId(info.uid);
  int uid = info.uid;
  ...
  final ProcessRecord r = new ProcessRecord(stats, info, proc, uid);
  if (!mBooted && !mBooting
          && userId == UserHandle.USER_SYSTEM
          && (info.flags & PERSISTENT_MASK) == PERSISTENT_MASK) {
      r.persistent = true;
      r.maxAdj = ProcessList.PERSISTENT_PROC_ADJ;
  }
  if (isolated && isolatedUid != 0) { //startIsolatedProcess
      r.maxAdj = ProcessList.PERSISTENT_SERVICE_ADJ;
  }
  return r;
}

調(diào)用鏈:

startOtherServices
  WebViewUpdateService.prepareWebViewInSystemServer
    WebViewUpdateServiceImpl.prepareWebViewInSystemServer
      WebViewUpdater.prepareWebViewInSystemServer
        WebViewUpdater.onWebViewProviderChanged
          SystemImpl.onWebViewProviderChanged
            WebViewFactory.onWebViewProviderChanged
              WebViewLibraryLoader.prepareNativeLibraries
                WebViewLibraryLoader.createRelros
                  WebViewLibraryLoader.createRelroFile
                    AMS.startIsolatedProcess

BACKUP_APP_ADJ(300)

if (mBackupTarget != null && app == mBackupTarget.app) {
    if (adj > ProcessList.BACKUP_APP_ADJ) {
        adj = ProcessList.BACKUP_APP_ADJ;
        if (procState > ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND) {
            procState = ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND;
        }
        app.adjType = "backup";
        app.cached = false;
    }
    if (procState > ActivityManager.PROCESS_STATE_BACKUP) {
        procState = ActivityManager.PROCESS_STATE_BACKUP;
        app.adjType = "backup";
    }
}

  • 執(zhí)行bindBackupAgent()過程,設(shè)置mBackupTarget值;
  • 執(zhí)行clearPendingBackup()或unbindBackupAgent()過程,置空mBackupTarget值;

HEAVY_WEIGHT_APP_ADJ(400)

  • realStartActivityLocked()過程,當(dāng)應(yīng)用的privateFlags標(biāo)識(shí)PRIVATE_FLAG_CANT_SAVE_STATE,設(shè)置mHeavyWeightProcess值;
  • finishHeavyWeightApp(), 置空mHeavyWeightProcess值;

HOME_APP_ADJ(600)

當(dāng)類型為ACTIVITY_TYPE_HOME的應(yīng)用啟動(dòng)后會(huì)設(shè)置mHomeProcess,比如桌面APP。

PREVIOUS_APP_ADJ(700)

場(chǎng)景1:用戶上一個(gè)使用的包含UI的進(jìn)程,為了給用戶在兩個(gè)APP之間更好的切換體驗(yàn),將上一個(gè)進(jìn)程ADJ設(shè)置到PREVIOUS_APP_ADJ的檔次。 當(dāng)activityStoppedLocked()過程會(huì)更新上一個(gè)應(yīng)用。

if (app == mPreviousProcess && app.activities.size() > 0) {
    if (adj > ProcessList.PREVIOUS_APP_ADJ) {
        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;
        app.adjType = "previous";
    }
}

場(chǎng)景2: 當(dāng)provider進(jìn)程,上一次使用時(shí)間不超過20S的情況下,優(yōu)先級(jí)不低于PREVIOUS_APP_ADJ。provider進(jìn)程這個(gè)是Android 7.0以后新增的邏輯 ,這樣做的好處是在內(nèi)存比較低的情況下避免擁有provider的進(jìn)程出現(xiàn)顛簸,也就是啟動(dòng)后殺,然后又被拉。

if (app.lastProviderTime > 0 &&
        (app.lastProviderTime+mConstants.CONTENT_PROVIDER_RETAIN_TIME) > now) {
    if (adj > ProcessList.PREVIOUS_APP_ADJ) {
        adj = ProcessList.PREVIOUS_APP_ADJ;
        schedGroup = ProcessList.SCHED_GROUP_BACKGROUND;
        app.cached = false;
        app.adjType = "recent-provider";
    }
    if (procState > ActivityManager.PROCESS_STATE_LAST_ACTIVITY) {
        procState = ActivityManager.PROCESS_STATE_LAST_ACTIVITY;
        app.adjType = "recent-provider";
    }
}

2.1 FOREGROUND_APP_ADJ(0)

場(chǎng)景1:滿足以下任一條件的進(jìn)程都屬于FOREGROUND_APP_ADJ(0)優(yōu)先級(jí):

  • 正處于resumed狀態(tài)的Activity
  • 正執(zhí)行一個(gè)生命周期回調(diào)的Service(比如執(zhí)行onCreate,onStartCommand,onDestroy等)
  • 正執(zhí)行onReceive()的BroadcastReceiver
  • 通過startInstrumentation()啟動(dòng)的進(jìn)程

源碼如下:

if (PROCESS_STATE_CUR_TOP == ActivityManager.PROCESS_STATE_TOP && app == TOP_APP) {
    adj = ProcessList.FOREGROUND_APP_ADJ;
    schedGroup = ProcessList.SCHED_GROUP_TOP_APP;
    app.adjType = "top-activity";
    foregroundActivities = true;
    procState = PROCESS_STATE_CUR_TOP;
} else if (app.instr != null) {
    adj = ProcessList.FOREGROUND_APP_ADJ;
    schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
    app.adjType = "instrumentation";
    procState = ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE;
} else if (isReceivingBroadcastLocked(app, mTmpBroadcastQueue)) {
    adj = ProcessList.FOREGROUND_APP_ADJ;
    schedGroup = (mTmpBroadcastQueue.contains(mFgBroadcastQueue))
            ? ProcessList.SCHED_GROUP_DEFAULT : ProcessList.SCHED_GROUP_BACKGROUND;
    app.adjType = "broadcast";
    procState = ActivityManager.PROCESS_STATE_RECEIVER;
} else if (app.executingServices.size() > 0) {
    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;
} else if (app == TOP_APP) {
    adj = ProcessList.FOREGROUND_APP_ADJ;
    schedGroup = ProcessList.SCHED_GROUP_BACKGROUND;
    app.adjType = "top-sleeping";
    foregroundActivities = true;
    procState = PROCESS_STATE_CUR_TOP;
} else {
    schedGroup = ProcessList.SCHED_GROUP_BACKGROUND;
    adj = cachedAdj;
    procState = ActivityManager.PROCESS_STATE_CACHED_EMPTY;
    app.cached = true;
    app.empty = true;
    app.adjType = "cch-empty";
}

場(chǎng)景2: 當(dāng)客戶端進(jìn)程activity里面調(diào)用bindService()方法時(shí)flags帶有BIND_ADJUST_WITH_ACTIVITY參數(shù),并且該activity處于可見狀態(tài),則當(dāng)前服務(wù)進(jìn)程也屬于前臺(tái)進(jìn)程,源碼如下:

for (int is = app.services.size()-1; is >= 0; is--) {
    ServiceRecord s = app.services.valueAt(is);
    for (int conni = s.connections.size()-1; conni >= 0; conni--) {
        ArrayList<ConnectionRecord> clist = s.connections.valueAt(conni);
        for (int i = 0; i < clist.size(); i++) {
            ConnectionRecord cr = clist.get(i);
            if ((cr.flags&Context.BIND_WAIVE_PRIORITY) == 0) {
              ...
            }

            final ActivityRecord a = cr.activity;
            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)) {
                    adj = ProcessList.FOREGROUND_APP_ADJ;
                    if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
                        if ((cr.flags&Context.BIND_IMPORTANT) != 0) {
                            schedGroup = ProcessList.SCHED_GROUP_TOP_APP_BOUND;
                        } else {
                            schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
                        }
                    }
                    app.cached = false;
                    app.adjType = "service";
                    app.adjTypeCode = ActivityManager.RunningAppProcessInfo
                            .REASON_SERVICE_IN_USE;
                    app.adjSource = a;
                    app.adjSourceProcState = procState;
                    app.adjTarget = s.name;
                }
            }
        }
    }
}

provider客戶端

場(chǎng)景3: 對(duì)于provider進(jìn)程,還有以下兩個(gè)條件能成為前臺(tái)進(jìn)程:

  • 當(dāng)Provider的客戶端進(jìn)程ADJ<=FOREGROUND_APP_ADJ時(shí),則Provider進(jìn)程ADJ等于FOREGROUND_APP_ADJ
  • 當(dāng)Provider有外部(非框架)進(jìn)程依賴,也就是調(diào)用了getContentProviderExternal()方法,則ADJ至少等于FOREGROUND_APP_ADJ
for (int provi = app.pubProviders.size()-1; provi >= 0; provi--) {
    ContentProviderRecord cpr = app.pubProviders.valueAt(provi);
    //根據(jù)client來調(diào)整provider進(jìn)程的adj和procState
    for (int i = cpr.connections.size()-1; i >= 0; i--) {
        ContentProviderConnection conn = cpr.connections.get(i);
        ProcessRecord client = conn.client;
        int clientAdj = computeOomAdjLocked(client, cachedAdj, TOP_APP, doingAll, now);
        if (adj > clientAdj) {
            if (app.hasShownUi && app != mHomeProcess
                    && clientAdj > ProcessList.PERCEPTIBLE_APP_ADJ) {
                ...
            } else {
                adj = clientAdj > ProcessList.FOREGROUND_APP_ADJ
                        ? clientAdj : ProcessList.FOREGROUND_APP_ADJ;
                adjType = "provider";
            }
            app.cached &= client.cached;
        }
        ...
    }
    //根據(jù)provider外部依賴情況來調(diào)整adj和schedGroup
    if (cpr.hasExternalProcessHandles()) {
         if (adj > ProcessList.FOREGROUND_APP_ADJ) {
             adj = ProcessList.FOREGROUND_APP_ADJ;
             schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
             app.cached = false;
             app.adjType = "ext-provider";
             app.adjTarget = cpr.name;
         }
     }
}

2.2 VISIBLE_APP_ADJ(100)

可見進(jìn)程:當(dāng)ActivityRecord的visible=true,也就是Activity可見的進(jìn)程。

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.visible) {
            if (adj > ProcessList.VISIBLE_APP_ADJ) {
                adj = ProcessList.VISIBLE_APP_ADJ;
                app.adjType = "vis-activity";
            }
            if (procState > PROCESS_STATE_CUR_TOP) {
                procState = PROCESS_STATE_CUR_TOP;
                app.adjType = "vis-activity";
            }
            schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
            app.cached = false;
            app.empty = false;
            foregroundActivities = true;
            final TaskRecord task = r.getTask();
            if (task != null && minLayer > 0) {
                final int layer = task.mLayerRank;
                if (layer >= 0 && minLayer > layer) {
                    minLayer = layer;
                }
            }
            break;
        }
        ...
    }
    if (adj == ProcessList.VISIBLE_APP_ADJ) {
        adj += minLayer;
    }
}

從Android P開始,進(jìn)一步細(xì)化ADJ級(jí)別,增加了VISIBLE_APP_LAYER_MAX(99),是指VISIBLE_APP_ADJ(100)跟PERCEPTIBLE_APP_ADJ(200)之間有99個(gè)槽,則可見級(jí)別ADJ的取值范圍為[100,199]。 算法會(huì)根據(jù)其所在task的mLayerRank來調(diào)整其ADJ,100加上mLayerRank就等于目標(biāo)ADJ,layer越大,則ADJ越小。

關(guān)于TaskRecord的mLayerRank的計(jì)算方式是在updateOomAdjLocked()過程調(diào)用ASS的rankTaskLayersIfNeeded()方法,如下:

[-> ActivityStackSupervisor.java]
void rankTaskLayersIfNeeded() {
    if (!mTaskLayersChanged) {
        return;
    }
    mTaskLayersChanged = false;
    for (int displayNdx = 0; displayNdx < mActivityDisplays.size(); displayNdx++) {
        final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
        int baseLayer = 0;
        for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
            final ActivityStack stack = display.getChildAt(stackNdx);
            baseLayer += stack.rankTaskLayers(baseLayer);
        }
    }
}

[-> ActivityStack.java]
final int rankTaskLayers(int baseLayer) {
    int layer = 0;
    for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
        final TaskRecord task = mTaskHistory.get(taskNdx);
        ActivityRecord r = task.topRunningActivityLocked();
        if (r == null || r.finishing || !r.visible) {
            task.mLayerRank = -1;
        } else {
            task.mLayerRank = baseLayer + layer++;
        }
    }
    return layer;
}

當(dāng)TaskRecord頂部的ActivityRecord為空或者結(jié)束或者不可見時(shí),則設(shè)置該TaskRecord的mLayerRank等于-1; 每個(gè)ActivityDisplay的baseLayer都是從0開始,從最上面的TaskRecord開始,第一個(gè)ADJ=100,從上至下依次加1,直到199為上限。

service客戶端

ServiceRecord的成員變量startRequested=true,是指被顯式調(diào)用了startService()方法。當(dāng)service被stop或kill會(huì)將其置為false。

一般情況下,即便客戶端進(jìn)程處于前臺(tái)進(jìn)程(ADJ=0)級(jí)別,服務(wù)進(jìn)程只會(huì)提升到可見(ADJ=1)級(jí)別。以下flags是由調(diào)用bindService()過程所傳遞的flags來決定的。

作為工程師很多時(shí)候可能還是想看看源碼,show me the code。但是關(guān)于ADJ計(jì)算這一塊源碼場(chǎng)景computeOomAdjLocked(),Google真心寫得比較亂,為了更清晰地說明客戶端進(jìn)程如何影響服務(wù)進(jìn)程,在保證不失去原意的情況下重寫了這塊部分邏輯:

這個(gè)過程主要根據(jù)service本身、client端情況以及activity狀態(tài)分別來調(diào)整adj和schedGroup

for (int is = app.services.size()-1; is >= 0; is--) {
    ServiceRecord s = app.services.valueAt(is);
    if (s.startRequested) {
        ... // 根據(jù)service本身調(diào)整adj和adjType
    }
    for (int conni = s.connections.size()-1; conni >= 0; conni--) {
        ArrayList<ConnectionRecord> clist = s.connections.valueAt(conni);
        for (int i = 0; i < clist.size(); i++) {
            ConnectionRecord cr = clist.get(i);
            //根據(jù)client端來調(diào)整adj
            if ((cr.flags&Context.BIND_WAIVE_PRIORITY) == 0) {
                if (adj > clientAdj) {
                    if (app.hasShownUi && app != mHomeProcess
                            && clientAdj > ProcessList.PERCEPTIBLE_APP_ADJ) {
                        ...
                    } else {
                        int newAdj = clientAdj;
                        if ((cr.flags&(Context.BIND_ABOVE_CLIENT
                                |Context.BIND_IMPORTANT)) != 0) {
                            if(clientAdj < ProcessList.PERSISTENT_SERVICE_ADJ) {
                                newAdj = PERSISTENT_SERVICE_ADJ;
                            }
                        } else if ((cr.flags&Context.BIND_NOT_VISIBLE) != 0) {
                            if(clientAdj < ProcessList.PERCEPTIBLE_APP_ADJ) {
                                newAdj = PERCEPTIBLE_APP_ADJ;
                            }
                        } else {
                            if (clientAdj < ProcessList.VISIBLE_APP_ADJ) {
                                newAdj = VISIBLE_APP_ADJ;
                            }
                        }

                        if (adj > newAdj) {
                            adj = newAdj;
                            adjType = "service";
                        }
                    }
                }
            }
            final ActivityRecord a = cr.activity;
            // 根據(jù)client的activity來調(diào)整adj和schedGroup
            if ((cr.flags&Context.BIND_ADJUST_WITH_ACTIVITY) != 0) {
                ...
            }
        }
    }
}

上段代碼說明服務(wù)端進(jìn)程優(yōu)先級(jí)(adj)不會(huì)低于客戶端進(jìn)程優(yōu)先級(jí)(newAdj),而newAdj的上限受限于flags,具體服務(wù)端進(jìn)程受客戶端進(jìn)程影響的ADJ上限如下:

  • BIND_ABOVE_CLIENT或BIND_IMPORTANT的情況下,ADJ上限為PERSISTENT_SERVICE_ADJ;
  • BIND_NOT_VISIBLE的情況下, ADJ上限為PERCEPTIBLE_APP_ADJ;
  • 否則,一般情況下,ADJ上限為VISIBLE_APP_ADJ;

由此,可見當(dāng)bindService過程帶有BIND_ABOVE_CLIENT或者BIND_IMPORTANT flags的同時(shí),客戶端進(jìn)程ADJ小于或等于PERSISTENT_SERVICE_ADJ的情況下,該進(jìn)程則為PERSISTENT_SERVICE_ADJ。另外,即便是啟動(dòng)過Activity的進(jìn)程,當(dāng)客戶端進(jìn)程ADJ<=200時(shí),還是可以提升該服務(wù)進(jìn)程的優(yōu)先級(jí)。

2.3 PERCEPTIBLE_APP_ADJ(200)

可感知進(jìn)程:當(dāng)該進(jìn)程存在不可見的Activity,但Activity正處于PAUSING、PAUSED、STOPPING狀態(tài),則為PERCEPTIBLE_APP_ADJ

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.visible) {
            ...
        } else if (r.state == ActivityState.PAUSING || r.state == ActivityState.PAUSED) {
            if (adj > ProcessList.PERCEPTIBLE_APP_ADJ) {
                adj = ProcessList.PERCEPTIBLE_APP_ADJ;
                app.adjType = "pause-activity";
            }
            if (procState > PROCESS_STATE_CUR_TOP) {
                procState = PROCESS_STATE_CUR_TOP;
                app.adjType = "pause-activity";
            }
            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 = "stop-activity";
            }

            if (!r.finishing) {
                if (procState > ActivityManager.PROCESS_STATE_LAST_ACTIVITY) {
                    procState = ActivityManager.PROCESS_STATE_LAST_ACTIVITY;
                    app.adjType = "stop-activity";
                }
            }
            app.cached = false;
            app.empty = false;
            foregroundActivities = true;
        }
    }
}

滿足以下任一條件的進(jìn)程也屬于可感知進(jìn)程:

  • foregroundServices非空:前臺(tái)服務(wù)進(jìn)程,執(zhí)行startForegroundService()方法
  • app.forcingToImportant非空:執(zhí)行setProcessImportant()方法,比如Toast彈出過程。
  • hasOverlayUi非空:非activity的UI位于屏幕最頂層,比如顯示類型TYPE_APPLICATION_OVERLAY的窗口
if (adj > ProcessList.PERCEPTIBLE_APP_ADJ
        || procState > ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE) {
    if (app.foregroundServices) {
        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.hasOverlayUi) {
        adj = ProcessList.PERCEPTIBLE_APP_ADJ;
        procState = ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND;
        app.cached = false;
        app.adjType = "has-overlay-ui";
        schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
    }
}

if (adj > ProcessList.PERCEPTIBLE_APP_ADJ
        || procState > ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND) {
    if (app.forcingToImportant != null) {
        adj = ProcessList.PERCEPTIBLE_APP_ADJ;
        procState = ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND;
        app.cached = false;
        app.adjType = "force-imp";
        app.adjSource = app.forcingToImportant;
        schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
    }
}

2.4 SERVICE_ADJ(500)

服務(wù)進(jìn)程:沒有啟動(dòng)過Activity,并且30分鐘之內(nèi)活躍過的服務(wù)進(jìn)程。 startRequested為true,則代表執(zhí)行startService()且沒有stop的進(jìn)程。

for (int is = app.services.size()-1; is >= 0; is--) {
    ServiceRecord s = app.services.valueAt(is);
    if (s.startRequested) {
        app.hasStartedServices = true;
        if (procState > ActivityManager.PROCESS_STATE_SERVICE) {
            procState = ActivityManager.PROCESS_STATE_SERVICE;
            app.adjType = "started-services";
        }
        if (app.hasShownUi && app != mHomeProcess) {
            if (adj > ProcessList.SERVICE_ADJ) {
                app.adjType = "cch-started-ui-services";
            }
        } else {
            if (now < (s.lastActivity + mConstants.MAX_SERVICE_INACTIVITY)) {
                if (adj > ProcessList.SERVICE_ADJ) {
                    adj = ProcessList.SERVICE_ADJ;
                    app.adjType = "started-services";
                    app.cached = false;
                }
            }
        }
    }
    for (int conni = s.connections.size()-1; conni >= 0; conni--) {
        ... //根據(jù)client情況來調(diào)整adj
    }
}

2.5 SERVICE_B_ADJ(800)

進(jìn)程由SERVICE_ADJ(500)降低到SERVICE_B_ADJ(800),有以下兩種情況:

  • A類Service占比過高:當(dāng)A類Service個(gè)數(shù) > Service總數(shù)的1/3時(shí),則加入到B類Service。換句話說,B Service的個(gè)數(shù)至少是A Service的2倍。
  • 內(nèi)存緊張&&A類Service占用內(nèi)存較高:當(dāng)系統(tǒng)內(nèi)存緊張級(jí)別(mLastMemoryLevel)高于ADJ_MEM_FACTOR_NORMAL,且該應(yīng)用所占內(nèi)存lastPss大于或等于CACHED_APP_MAX_ADJ級(jí)別所對(duì)應(yīng)的內(nèi)存閾值的1/3(默認(rèn)值閾值約等于110MB)。

源碼如下:

if (adj == ProcessList.SERVICE_ADJ) {
    if (doingAll) {
        app.serviceb = mNewNumAServiceProcs > (mNumServiceProcs/3);
        mNewNumServiceProcs++;
        if (!app.serviceb) {
            if (mLastMemoryLevel > ProcessStats.ADJ_MEM_FACTOR_NORMAL
                    && app.lastPss >= mProcessList.getCachedRestoreThresholdKb()) {
                app.serviceHighRam = true;
                app.serviceb = true;
            } else {
                mNewNumAServiceProcs++;
            }
        } else {
            app.serviceHighRam = false;
        }
    }
    if (app.serviceb) {
        adj = ProcessList.SERVICE_B_ADJ;
    }
}

ADJ_MEM_FACTOR

這里順便一下,內(nèi)存因子ADJ_MEM_FACTOR共有4個(gè)級(jí)別,當(dāng)前處于哪個(gè)內(nèi)存因子級(jí)別,取決于當(dāng)前進(jìn)程中cached進(jìn)程和空進(jìn)程的個(gè)數(shù)。

final int numCachedAndEmpty = numCached + numEmpty;
int memFactor;
if (numCached <= mConstants.CUR_TRIM_CACHED_PROCESSES
        && numEmpty <= mConstants.CUR_TRIM_EMPTY_PROCESSES) {
    if (numCachedAndEmpty <= ProcessList.TRIM_CRITICAL_THRESHOLD) {
        memFactor = ProcessStats.ADJ_MEM_FACTOR_CRITICAL;
    } else if (numCachedAndEmpty <= ProcessList.TRIM_LOW_THRESHOLD) {
        memFactor = ProcessStats.ADJ_MEM_FACTOR_LOW;
    } else {
        memFactor = ProcessStats.ADJ_MEM_FACTOR_MODERATE;
    }
} else {
    memFactor = ProcessStats.ADJ_MEM_FACTOR_NORMAL;
}

ADJ內(nèi)存因子:決定允許后臺(tái)運(yùn)行Jobs的最大上限,以及決定TrimMemory的級(jí)別(包括ThreadedRenderer的回收級(jí)別),再進(jìn)一步來看看內(nèi)存因子:

也就是說

默認(rèn)情況取值如下:

  • 最大緩存進(jìn)程個(gè)數(shù):CUR_MAX_CACHED_PROCESSES = MAX_CACHED_PROCESSES = 32
  • 最大空進(jìn)程個(gè)數(shù): CUR_MAX_EMPTY_PROCESSES = MAX_CACHED_PROCESSES/2 = 16
  • Trim空進(jìn)程上限:CUR_TRIM_EMPTY_PROCESSES = MAX_CACHED_PROCESSES/4 = 8
  • Trim緩存進(jìn)程上限:CUR_TRIM_CACHED_PROCESSES = MAX_CACHED_PROCESSES/6 = 5

當(dāng)mOverrideMaxCachedProcesses有值的情況下,最大緩存進(jìn)程個(gè)數(shù)和最大空進(jìn)程個(gè)數(shù)上限優(yōu)先取mOverrideMaxCachedProcesses,可通過AMS.setProcessLimit(int max)調(diào)整mOverrideMaxCachedProcesses值;Trim的緩存進(jìn)程和空進(jìn)程上限不受mOverrideMaxCachedProcesses影響。

再來看看cached和empty進(jìn)程:

final int emptyProcessLimit = mConstants.CUR_MAX_EMPTY_PROCESSES;
final int cachedProcessLimit = mConstants.CUR_MAX_CACHED_PROCESSES - emptyProcessLimit;
final long oldTime = now - ProcessList.MAX_EMPTY_TIME;

switch (app.curProcState) {
    case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY:
    case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT:
        mNumCachedHiddenProcs++;
        numCached++;
        //默認(rèn)cachedProcessLimit=16
        if (numCached > cachedProcessLimit) {
            app.kill("cached #" + numCached, true);
        }
        break;
    case ActivityManager.PROCESS_STATE_CACHED_EMPTY:
        //默認(rèn)CUR_TRIM_EMPTY_PROCESSES=8, 且滿足30min
        if (numEmpty > mConstants.CUR_TRIM_EMPTY_PROCESSES
                && app.lastActivityTime < oldTime) {
            app.kill("empty for "
                    + ((oldTime + ProcessList.MAX_EMPTY_TIME - app.lastActivityTime)
                    / 1000) + "s", true);
        } else {
            numEmpty++;
            //默認(rèn)cachedProcessLimit=16
            if (numEmpty > emptyProcessLimit) {
                app.kill("empty #" + numEmpty, true);
            }
        }
        break;
    default:
        mNumNonCachedProcs++;
        break;

用于限制empty或cached進(jìn)程的上限為16個(gè),并且empty超過8個(gè)時(shí)會(huì)清理掉30分鐘沒有活躍的進(jìn)程。 cached和empty主要是區(qū)別是否有Activity。

2.6 CACHED_APP_MIN_ADJ(900)

緩存進(jìn)程優(yōu)先級(jí)從CACHED_APP_MIN_ADJ(900)到 CACHED_APP_MAX_ADJ(906)。

ADJ的轉(zhuǎn)換算法:

  • cached: 900, 901, 903, 905
  • empty: 900, 902, 904, 906
final int N = mLruProcesses.size();
//numSlots等于3
int numSlots = (ProcessList.CACHED_APP_MAX_ADJ
        - ProcessList.CACHED_APP_MIN_ADJ + 1) / 2;
//mNumNonCachedProcs是指empty和cached之外的進(jìn)程, mNumCachedHiddenProcs代表的是cached進(jìn)程個(gè)數(shù)
int numEmptyProcs = N - mNumNonCachedProcs - mNumCachedHiddenProcs;
if (numEmptyProcs > cachedProcessLimit) {
    numEmptyProcs = cachedProcessLimit;
}
//emptyFactor和cachedFactor分別代表每個(gè)slot里面包括的進(jìn)程個(gè)數(shù),大于或等于1
int emptyFactor = numEmptyProcs/numSlots;
int cachedFactor = (mNumCachedHiddenProcs > 0 ? mNumCachedHiddenProcs : 1)/numSlots;

mNumNonCachedProcs = 0;
mNumCachedHiddenProcs = 0;

int curCachedAdj = ProcessList.CACHED_APP_MIN_ADJ;
int nextCachedAdj = curCachedAdj+1;
int curEmptyAdj = ProcessList.CACHED_APP_MIN_ADJ;
int nextEmptyAdj = curEmptyAdj+2;

for (int i=N-1; i>=0; i--) {
    ProcessRecord app = mLruProcesses.get(i);
    if (!app.killedByAm && app.thread != null) {
        app.procStateChanged = false;
        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++;
                        if (stepCached >= cachedFactor) {
                            stepCached = 0;
                            curCachedAdj = nextCachedAdj;
                            nextCachedAdj += 2; //每次加2
                            if (nextCachedAdj > ProcessList.CACHED_APP_MAX_ADJ) {
                                nextCachedAdj = ProcessList.CACHED_APP_MAX_ADJ;
                            }
                        }
                    }
                    break;
                default:
                    app.curRawAdj = curEmptyAdj;
                    //ADJ閾值
                    app.curAdj = app.modifyRawOomAdj(curEmptyAdj);
                    if (curEmptyAdj != nextEmptyAdj) {
                        stepEmpty++;
                        if (stepEmpty >= emptyFactor) {
                            stepEmpty = 0;
                            curEmptyAdj = nextEmptyAdj;
                            nextEmptyAdj += 2; //每次加2
                            if (nextEmptyAdj > ProcessList.CACHED_APP_MAX_ADJ) {
                                nextEmptyAdj = ProcessList.CACHED_APP_MAX_ADJ;
                            }
                        }
                    }
                    break;
            }
        }

        applyOomAdjLocked(app, true, now, nowElapsed);
        ...
    }
}

numSlots=3, emptyFactor= 空進(jìn)程個(gè)數(shù)/3, cachedFactor= 緩存進(jìn)程個(gè)數(shù)/3,

再來看看PROCESS_STATE_CACHED_ACTIVITY的定義:

if (!foregroundActivities && activitiesSize > 0) {
    for (int j = 0; j < activitiesSize; j++) {
        final ActivityRecord r = app.activities.get(j);
        if (r.visible) {
            ...
        } else if (r.state == ActivityState.PAUSING || r.state == ActivityState.PAUSED) {
            ...
        } else if (r.state == ActivityState.STOPPING) {
            ...
        } else {
            if (procState > ActivityManager.PROCESS_STATE_CACHED_ACTIVITY) {
                procState = ActivityManager.PROCESS_STATE_CACHED_ACTIVITY;
                app.adjType = "cch-act";
            }
        }
    }
}

foregroundActivities代表當(dāng)前不是前臺(tái)(FOREGROUND_APP_ADJ)進(jìn)程,并且存在Activity的進(jìn)程,當(dāng)該Activity窗口不可見,并且不處于PAUSING(正在)、PAUSED(onPause個(gè))、STOPPING的任一狀態(tài)的情況下,則設(shè)置該進(jìn)程為PROCESS_STATE_CACHED_ACTIVITY。

PROCESS_STATE_CACHED_ACTIVITY_CLIENT的定義:

if (procState >= ActivityManager.PROCESS_STATE_CACHED_EMPTY) {
    if (app.hasClientActivities) {
        procState = ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT;
        app.adjType = "cch-client-act";
    } else if (app.treatLikeActivity) {
        procState = ActivityManager.PROCESS_STATE_CACHED_ACTIVITY;
        app.adjType = "cch-as-act";
    }
}

當(dāng)該進(jìn)程Service的客戶端進(jìn)程存在Activity或者是treatLikeActivity的進(jìn)程,其進(jìn)程狀態(tài)都是cached進(jìn)程。

三、查看進(jìn)程優(yōu)先級(jí)

3.1 CPU調(diào)度優(yōu)先級(jí)

bindService或者startService是否前臺(tái)調(diào)用取決于caller進(jìn)程的調(diào)度組。當(dāng)caller屬于SCHED_GROUP_BACKGROUND則認(rèn)為是后臺(tái)調(diào)用,當(dāng)不屬于SCHED_GROUP_BACKGROUND則認(rèn)為是前臺(tái)調(diào)用。callerFg = callerApp.setSchedGroup != ProcessList.SCHED_GROUP_BACKGROUND;

關(guān)于CPU調(diào)度組:

THREAD_GROUP_TOP_APP

  • SCHED_GROUP_TOP_APP:
    • setRenderThread()過程,根據(jù)屬性sys.use_fifo_ui來決定采用SCHED_FIFO,或者設(shè)置當(dāng)前線程的優(yōu)先級(jí)為-10
    • TOP_APP或者app.hasTopUi,則設(shè)置為該值
  • SCHED_GROUP_TOP_APP_BOUND:
    • 對(duì)于ConnectionRecord帶有BIND_ADJUST_WITH_ACTIVITY和BIND_IMPORTANT,并且沒帶有BIND_NOT_FOREGROUND的情況下, 當(dāng)客戶端進(jìn)程的有可見的Activity,或者處于RESUMED/PAUSING狀態(tài)時(shí),則設(shè)置為該值

當(dāng)進(jìn)程調(diào)度級(jí)別由非TOP切換到TOP級(jí)別,則主線程和rendThread可設(shè)置為SCHED_FIFO或者更高優(yōu)先級(jí);當(dāng)由TOP級(jí)別切換回非TOP級(jí)別,則恢復(fù)原來的調(diào)度策略或優(yōu)先級(jí)。

THREAD_GROUP_DEFAULT

  • SCHED_GROUP_DEFAULT:
    • 默認(rèn)值
    • ADJ <= FOREGROUND_APP_ADJ;
    • 正在接收來自于mFgBroadcastQueue廣播隊(duì)列的廣播;
    • 正在執(zhí)行來自于前臺(tái)調(diào)度進(jìn)程發(fā)起的服務(wù)(execServicesFg=true)
    • Activity處于可見狀態(tài)(visible=true)
    • 具有fg-service或者設(shè)置forcingToImportant的服務(wù)
    • 正在顯示一個(gè)overlay UI(app.hasOverlayUi=true)
    • 當(dāng)ConnectionRecord同時(shí)沒有指定BIND_NOT_FOREGROUND和BIND_IMPORTANT_BACKGROUND、BIND_IMPORTANT情況下, 當(dāng)客戶端進(jìn)程的schedGroup高于服務(wù)進(jìn)程,則設(shè)置為該值
    • 對(duì)于ConnectionRecord帶有BIND_ADJUST_WITH_ACTIVITY,并且沒帶有BIND_NOT_FOREGROUND和BIND_IMPORTANT的情況下, 當(dāng)客戶端進(jìn)程的有可見的Activity,或者處于RESUMED/PAUSING狀態(tài)時(shí),則設(shè)置為該值
    • 當(dāng)ContentProviderConnection所對(duì)應(yīng)的客戶端進(jìn)程的schedGroup高于服務(wù)進(jìn)程,則設(shè)置為該值
    • 當(dāng)cpr.hasExternalProcessHandles為true的情況
    • 最后,當(dāng)maxAdj <= PERCEPTIBLE_APP_ADJ的情況

THREAD_GROUP_BG_NONINTERACTIVE

  • SCHED_GROUP_BACKGROUND:
    • 應(yīng)用已結(jié)束(app.thread == null)
    • 正在接收來自于mBgBroadcastQueue廣播隊(duì)列的廣播;
    • 正在執(zhí)行來自于前臺(tái)調(diào)度進(jìn)程發(fā)起的服務(wù)(execServicesFg=false)
    • TOP_APP,且設(shè)備處于睡眠狀態(tài)
    • 等等

http://gityuan.com/2018/05/19/android-process-adj/

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容