Merge changes I5bab7728,Ie386672c,I04940599 into udc-dev
* changes: Freezer: release AM lock while checking /proc/locks OomAdjuster: use oom_adj_score tiers for cached apps Reland OomAdjuster: demote previous process to cached after configurable timeout
This commit is contained in:
@@ -129,6 +129,7 @@ final class ActivityManagerConstants extends ContentObserver {
|
||||
static final String KEY_KILL_BG_RESTRICTED_CACHED_IDLE = "kill_bg_restricted_cached_idle";
|
||||
static final String KEY_KILL_BG_RESTRICTED_CACHED_IDLE_SETTLE_TIME =
|
||||
"kill_bg_restricted_cached_idle_settle_time";
|
||||
static final String KEY_MAX_PREVIOUS_TIME = "max_previous_time";
|
||||
/**
|
||||
* Note this key is on {@link DeviceConfig#NAMESPACE_ACTIVITY_MANAGER_COMPONENT_ALIAS}.
|
||||
* @see #mEnableComponentAlias
|
||||
@@ -145,6 +146,9 @@ final class ActivityManagerConstants extends ContentObserver {
|
||||
*/
|
||||
static final String KEY_NETWORK_ACCESS_TIMEOUT_MS = "network_access_timeout_ms";
|
||||
|
||||
static final String KEY_USE_TIERED_CACHED_ADJ = "use_tiered_cached_adj";
|
||||
static final String KEY_TIERED_CACHED_ADJ_DECAY_TIME = "tiered_cached_adj_decay_time";
|
||||
|
||||
private static final int DEFAULT_MAX_CACHED_PROCESSES = 32;
|
||||
private static final boolean DEFAULT_PRIORITIZE_ALARM_BROADCASTS = true;
|
||||
private static final long DEFAULT_FGSERVICE_MIN_SHOWN_TIME = 2*1000;
|
||||
@@ -192,6 +196,7 @@ final class ActivityManagerConstants extends ContentObserver {
|
||||
private static final float DEFAULT_FGS_START_DENIED_LOG_SAMPLE_RATE = 1; // 100%
|
||||
private static final long DEFAULT_PROCESS_KILL_TIMEOUT_MS = 10 * 1000;
|
||||
private static final long DEFAULT_NETWORK_ACCESS_TIMEOUT_MS = 200; // 0.2 sec
|
||||
private static final long DEFAULT_MAX_PREVIOUS_TIME = 60 * 1000; // 60s
|
||||
|
||||
static final long DEFAULT_BACKGROUND_SETTLE_TIME = 60 * 1000;
|
||||
static final long DEFAULT_KILL_BG_RESTRICTED_CACHED_IDLE_SETTLE_TIME_MS = 60 * 1000;
|
||||
@@ -199,6 +204,9 @@ final class ActivityManagerConstants extends ContentObserver {
|
||||
|
||||
static final int DEFAULT_MAX_SERVICE_CONNECTIONS_PER_PROCESS = 3000;
|
||||
|
||||
private static final boolean DEFAULT_USE_TIERED_CACHED_ADJ = false;
|
||||
private static final long DEFAULT_TIERED_CACHED_ADJ_DECAY_TIME = 60 * 1000;
|
||||
|
||||
/**
|
||||
* Same as {@link TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_NOT_ALLOWED}
|
||||
*/
|
||||
@@ -534,6 +542,9 @@ final class ActivityManagerConstants extends ContentObserver {
|
||||
public long TOP_TO_ALMOST_PERCEPTIBLE_GRACE_DURATION =
|
||||
DEFAULT_TOP_TO_ALMOST_PERCEPTIBLE_GRACE_DURATION;
|
||||
|
||||
// How long a process can remain at previous oom_adj before dropping to cached
|
||||
public static long MAX_PREVIOUS_TIME = DEFAULT_MAX_PREVIOUS_TIME;
|
||||
|
||||
/**
|
||||
* The minimum time we allow between crashes, for us to consider this
|
||||
* application to be bad and stop its services and reject broadcasts.
|
||||
@@ -1006,6 +1017,12 @@ final class ActivityManagerConstants extends ContentObserver {
|
||||
public volatile long mShortFgsAnrExtraWaitDuration =
|
||||
DEFAULT_SHORT_FGS_ANR_EXTRA_WAIT_DURATION;
|
||||
|
||||
/** @see #KEY_USE_TIERED_CACHED_ADJ */
|
||||
public boolean USE_TIERED_CACHED_ADJ = DEFAULT_USE_TIERED_CACHED_ADJ;
|
||||
|
||||
/** @see #KEY_TIERED_CACHED_ADJ_DECAY_TIME */
|
||||
public long TIERED_CACHED_ADJ_DECAY_TIME = DEFAULT_TIERED_CACHED_ADJ_DECAY_TIME;
|
||||
|
||||
private final OnPropertiesChangedListener mOnDeviceConfigChangedListener =
|
||||
new OnPropertiesChangedListener() {
|
||||
@Override
|
||||
@@ -1171,6 +1188,13 @@ final class ActivityManagerConstants extends ContentObserver {
|
||||
case KEY_ENABLE_WAIT_FOR_FINISH_ATTACH_APPLICATION:
|
||||
updateEnableWaitForFinishAttachApplication();
|
||||
break;
|
||||
case KEY_MAX_PREVIOUS_TIME:
|
||||
updateMaxPreviousTime();
|
||||
break;
|
||||
case KEY_USE_TIERED_CACHED_ADJ:
|
||||
case KEY_TIERED_CACHED_ADJ_DECAY_TIME:
|
||||
updateUseTieredCachedAdj();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -1825,6 +1849,7 @@ final class ActivityManagerConstants extends ContentObserver {
|
||||
DEFAULT_LOW_SWAP_THRESHOLD_PERCENT);
|
||||
}
|
||||
|
||||
|
||||
private void updateTopToFgsGraceDuration() {
|
||||
TOP_TO_FGS_GRACE_DURATION = DeviceConfig.getLong(
|
||||
DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
|
||||
@@ -1832,6 +1857,13 @@ final class ActivityManagerConstants extends ContentObserver {
|
||||
DEFAULT_TOP_TO_FGS_GRACE_DURATION);
|
||||
}
|
||||
|
||||
private void updateMaxPreviousTime() {
|
||||
MAX_PREVIOUS_TIME = DeviceConfig.getLong(
|
||||
DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
|
||||
KEY_MAX_PREVIOUS_TIME,
|
||||
DEFAULT_MAX_PREVIOUS_TIME);
|
||||
}
|
||||
|
||||
private void updateMinAssocLogDuration() {
|
||||
MIN_ASSOC_LOG_DURATION = DeviceConfig.getLong(
|
||||
DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, KEY_MIN_ASSOC_LOG_DURATION,
|
||||
@@ -1908,6 +1940,17 @@ final class ActivityManagerConstants extends ContentObserver {
|
||||
DEFAULT_ENABLE_WAIT_FOR_FINISH_ATTACH_APPLICATION);
|
||||
}
|
||||
|
||||
private void updateUseTieredCachedAdj() {
|
||||
USE_TIERED_CACHED_ADJ = DeviceConfig.getBoolean(
|
||||
DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
|
||||
KEY_USE_TIERED_CACHED_ADJ,
|
||||
DEFAULT_USE_TIERED_CACHED_ADJ);
|
||||
TIERED_CACHED_ADJ_DECAY_TIME = DeviceConfig.getLong(
|
||||
DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
|
||||
KEY_TIERED_CACHED_ADJ_DECAY_TIME,
|
||||
DEFAULT_TIERED_CACHED_ADJ_DECAY_TIME);
|
||||
}
|
||||
|
||||
@NeverCompile // Avoid size overhead of debugging code.
|
||||
void dump(PrintWriter pw) {
|
||||
pw.println("ACTIVITY MANAGER SETTINGS (dumpsys activity settings) "
|
||||
@@ -2092,6 +2135,11 @@ final class ActivityManagerConstants extends ContentObserver {
|
||||
pw.print(" "); pw.print(KEY_SHORT_FGS_ANR_EXTRA_WAIT_DURATION);
|
||||
pw.print("="); pw.println(mShortFgsAnrExtraWaitDuration);
|
||||
|
||||
pw.print(" "); pw.print(KEY_USE_TIERED_CACHED_ADJ);
|
||||
pw.print("="); pw.println(USE_TIERED_CACHED_ADJ);
|
||||
pw.print(" "); pw.print(KEY_TIERED_CACHED_ADJ_DECAY_TIME);
|
||||
pw.print("="); pw.println(TIERED_CACHED_ADJ_DECAY_TIME);
|
||||
|
||||
pw.println();
|
||||
if (mOverrideMaxCachedProcesses >= 0) {
|
||||
pw.print(" mOverrideMaxCachedProcesses="); pw.println(mOverrideMaxCachedProcesses);
|
||||
|
||||
@@ -1921,9 +1921,26 @@ public final class CachedAppOptimizer {
|
||||
public void handleMessage(Message msg) {
|
||||
switch (msg.what) {
|
||||
case SET_FROZEN_PROCESS_MSG:
|
||||
{
|
||||
ProcessRecord proc = (ProcessRecord) msg.obj;
|
||||
int pid = proc.getPid();
|
||||
final String name = proc.processName;
|
||||
synchronized (mAm) {
|
||||
freezeProcess((ProcessRecord) msg.obj);
|
||||
freezeProcess(proc);
|
||||
}
|
||||
try {
|
||||
// post-check to prevent deadlock
|
||||
mProcLocksReader.handleBlockingFileLocks(this);
|
||||
} catch (Exception e) {
|
||||
Slog.e(TAG_AM, "Unable to check file locks for "
|
||||
+ name + "(" + pid + "): " + e);
|
||||
synchronized (mAm) {
|
||||
synchronized (mProcLock) {
|
||||
unfreezeAppLSP(proc, OomAdjuster.OOM_ADJ_REASON_NONE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case REPORT_UNFREEZE_MSG:
|
||||
int pid = msg.arg1;
|
||||
@@ -2057,16 +2074,6 @@ public final class CachedAppOptimizer {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
try {
|
||||
// post-check to prevent deadlock
|
||||
mProcLocksReader.handleBlockingFileLocks(this);
|
||||
} catch (Exception e) {
|
||||
Slog.e(TAG_AM, "Unable to check file locks for " + name + "(" + pid + "): " + e);
|
||||
synchronized (mProcLock) {
|
||||
unfreezeAppLSP(proc, OomAdjuster.OOM_ADJ_REASON_NONE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void reportUnfreeze(int pid, int frozenDuration, String processName,
|
||||
@@ -2123,22 +2130,25 @@ public final class CachedAppOptimizer {
|
||||
if (DEBUG_FREEZER) {
|
||||
Slog.d(TAG_AM, "Blocking file lock found: " + pids);
|
||||
}
|
||||
synchronized (mProcLock) {
|
||||
int pid = pids.get(0);
|
||||
ProcessRecord app = mFrozenProcesses.get(pid);
|
||||
ProcessRecord pr;
|
||||
if (app != null) {
|
||||
for (int i = 1; i < pids.size(); i++) {
|
||||
int blocked = pids.get(i);
|
||||
synchronized (mAm.mPidsSelfLocked) {
|
||||
pr = mAm.mPidsSelfLocked.get(blocked);
|
||||
}
|
||||
if (pr != null && pr.mState.getCurAdj() < ProcessList.CACHED_APP_MIN_ADJ) {
|
||||
Slog.d(TAG_AM, app.processName + " (" + pid + ") blocks "
|
||||
+ pr.processName + " (" + blocked + ")");
|
||||
// Found at least one blocked non-cached process
|
||||
unfreezeAppLSP(app, OomAdjuster.OOM_ADJ_REASON_NONE);
|
||||
break;
|
||||
synchronized (mAm) {
|
||||
synchronized (mProcLock) {
|
||||
int pid = pids.get(0);
|
||||
ProcessRecord app = mFrozenProcesses.get(pid);
|
||||
ProcessRecord pr;
|
||||
if (app != null) {
|
||||
for (int i = 1; i < pids.size(); i++) {
|
||||
int blocked = pids.get(i);
|
||||
synchronized (mAm.mPidsSelfLocked) {
|
||||
pr = mAm.mPidsSelfLocked.get(blocked);
|
||||
}
|
||||
if (pr != null
|
||||
&& pr.mState.getCurAdj() < ProcessList.CACHED_APP_MIN_ADJ) {
|
||||
Slog.d(TAG_AM, app.processName + " (" + pid + ") blocks "
|
||||
+ pr.processName + " (" + blocked + ")");
|
||||
// Found at least one blocked non-cached process
|
||||
unfreezeAppLSP(app, OomAdjuster.OOM_ADJ_REASON_NONE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1073,135 +1073,165 @@ public class OomAdjuster {
|
||||
@GuardedBy({"mService", "mProcLock"})
|
||||
private void assignCachedAdjIfNecessary(ArrayList<ProcessRecord> lruList) {
|
||||
final int numLru = lruList.size();
|
||||
if (mConstants.USE_TIERED_CACHED_ADJ) {
|
||||
final long now = SystemClock.uptimeMillis();
|
||||
for (int i = numLru - 1; i >= 0; i--) {
|
||||
ProcessRecord app = lruList.get(i);
|
||||
final ProcessStateRecord state = app.mState;
|
||||
final ProcessCachedOptimizerRecord opt = app.mOptRecord;
|
||||
if (!app.isKilledByAm() && app.getThread() != null && state.getCurAdj()
|
||||
>= UNKNOWN_ADJ) {
|
||||
final ProcessServiceRecord psr = app.mServices;
|
||||
int targetAdj = CACHED_APP_MIN_ADJ;
|
||||
|
||||
// First update the OOM adjustment for each of the
|
||||
// application processes based on their current state.
|
||||
int curCachedAdj = CACHED_APP_MIN_ADJ;
|
||||
int nextCachedAdj = curCachedAdj + (CACHED_APP_IMPORTANCE_LEVELS * 2);
|
||||
int curCachedImpAdj = 0;
|
||||
int curEmptyAdj = CACHED_APP_MIN_ADJ + CACHED_APP_IMPORTANCE_LEVELS;
|
||||
int nextEmptyAdj = curEmptyAdj + (CACHED_APP_IMPORTANCE_LEVELS * 2);
|
||||
if (opt != null && opt.isFreezeExempt()) {
|
||||
// BIND_WAIVE_PRIORITY and the like get oom_adj 900
|
||||
targetAdj += 0;
|
||||
} else if ((state.getSetAdj() >= CACHED_APP_MIN_ADJ)
|
||||
&& (state.getLastStateTime()
|
||||
+ mConstants.TIERED_CACHED_ADJ_DECAY_TIME) < now) {
|
||||
// Older cached apps get 950
|
||||
targetAdj += 50;
|
||||
} else {
|
||||
// Newer cached apps get 910
|
||||
targetAdj += 10;
|
||||
}
|
||||
state.setCurRawAdj(targetAdj);
|
||||
state.setCurAdj(psr.modifyRawOomAdj(targetAdj));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// First update the OOM adjustment for each of the
|
||||
// application processes based on their current state.
|
||||
int curCachedAdj = CACHED_APP_MIN_ADJ;
|
||||
int nextCachedAdj = curCachedAdj + (CACHED_APP_IMPORTANCE_LEVELS * 2);
|
||||
int curCachedImpAdj = 0;
|
||||
int curEmptyAdj = CACHED_APP_MIN_ADJ + CACHED_APP_IMPORTANCE_LEVELS;
|
||||
int nextEmptyAdj = curEmptyAdj + (CACHED_APP_IMPORTANCE_LEVELS * 2);
|
||||
|
||||
final int emptyProcessLimit = mConstants.CUR_MAX_EMPTY_PROCESSES;
|
||||
final int cachedProcessLimit = mConstants.CUR_MAX_CACHED_PROCESSES
|
||||
- emptyProcessLimit;
|
||||
// Let's determine how many processes we have running vs.
|
||||
// how many slots we have for background processes; we may want
|
||||
// to put multiple processes in a slot of there are enough of
|
||||
// them.
|
||||
int numEmptyProcs = numLru - mNumNonCachedProcs - mNumCachedHiddenProcs;
|
||||
if (numEmptyProcs > cachedProcessLimit) {
|
||||
// If there are more empty processes than our limit on cached
|
||||
// processes, then use the cached process limit for the factor.
|
||||
// This ensures that the really old empty processes get pushed
|
||||
// down to the bottom, so if we are running low on memory we will
|
||||
// have a better chance at keeping around more cached processes
|
||||
// instead of a gazillion empty processes.
|
||||
numEmptyProcs = cachedProcessLimit;
|
||||
}
|
||||
int cachedFactor = (mNumCachedHiddenProcs > 0 ? (mNumCachedHiddenProcs + mNumSlots - 1) : 1)
|
||||
/ mNumSlots;
|
||||
if (cachedFactor < 1) cachedFactor = 1;
|
||||
final int emptyProcessLimit = mConstants.CUR_MAX_EMPTY_PROCESSES;
|
||||
final int cachedProcessLimit = mConstants.CUR_MAX_CACHED_PROCESSES
|
||||
- emptyProcessLimit;
|
||||
// Let's determine how many processes we have running vs.
|
||||
// how many slots we have for background processes; we may want
|
||||
// to put multiple processes in a slot of there are enough of
|
||||
// them.
|
||||
int numEmptyProcs = numLru - mNumNonCachedProcs - mNumCachedHiddenProcs;
|
||||
if (numEmptyProcs > cachedProcessLimit) {
|
||||
// If there are more empty processes than our limit on cached
|
||||
// processes, then use the cached process limit for the factor.
|
||||
// This ensures that the really old empty processes get pushed
|
||||
// down to the bottom, so if we are running low on memory we will
|
||||
// have a better chance at keeping around more cached processes
|
||||
// instead of a gazillion empty processes.
|
||||
numEmptyProcs = cachedProcessLimit;
|
||||
}
|
||||
int cachedFactor = (mNumCachedHiddenProcs > 0
|
||||
? (mNumCachedHiddenProcs + mNumSlots - 1) : 1)
|
||||
/ mNumSlots;
|
||||
if (cachedFactor < 1) cachedFactor = 1;
|
||||
|
||||
int emptyFactor = (numEmptyProcs + mNumSlots - 1) / mNumSlots;
|
||||
if (emptyFactor < 1) emptyFactor = 1;
|
||||
int emptyFactor = (numEmptyProcs + mNumSlots - 1) / mNumSlots;
|
||||
if (emptyFactor < 1) emptyFactor = 1;
|
||||
|
||||
int stepCached = -1;
|
||||
int stepEmpty = -1;
|
||||
int lastCachedGroup = 0;
|
||||
int lastCachedGroupImportance = 0;
|
||||
int lastCachedGroupUid = 0;
|
||||
int stepCached = -1;
|
||||
int stepEmpty = -1;
|
||||
int lastCachedGroup = 0;
|
||||
int lastCachedGroupImportance = 0;
|
||||
int lastCachedGroupUid = 0;
|
||||
|
||||
for (int i = numLru - 1; i >= 0; i--) {
|
||||
ProcessRecord app = lruList.get(i);
|
||||
final ProcessStateRecord state = app.mState;
|
||||
// If we haven't yet assigned the final cached adj
|
||||
// to the process, do that now.
|
||||
if (!app.isKilledByAm() && app.getThread() != null && state.getCurAdj()
|
||||
|
||||
for (int i = numLru - 1; i >= 0; i--) {
|
||||
ProcessRecord app = lruList.get(i);
|
||||
final ProcessStateRecord state = app.mState;
|
||||
// If we haven't yet assigned the final cached adj
|
||||
// to the process, do that now.
|
||||
if (!app.isKilledByAm() && app.getThread() != null && state.getCurAdj()
|
||||
>= UNKNOWN_ADJ) {
|
||||
final ProcessServiceRecord psr = app.mServices;
|
||||
switch (state.getCurProcState()) {
|
||||
case PROCESS_STATE_CACHED_ACTIVITY:
|
||||
case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT:
|
||||
case ActivityManager.PROCESS_STATE_CACHED_RECENT:
|
||||
// Figure out the next cached level, taking into account groups.
|
||||
boolean inGroup = false;
|
||||
final int connectionGroup = psr.getConnectionGroup();
|
||||
if (connectionGroup != 0) {
|
||||
final int connectionImportance = psr.getConnectionImportance();
|
||||
if (lastCachedGroupUid == app.uid
|
||||
final ProcessServiceRecord psr = app.mServices;
|
||||
switch (state.getCurProcState()) {
|
||||
case PROCESS_STATE_CACHED_ACTIVITY:
|
||||
case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT:
|
||||
case ActivityManager.PROCESS_STATE_CACHED_RECENT:
|
||||
// Figure out the next cached level, taking into account groups.
|
||||
boolean inGroup = false;
|
||||
final int connectionGroup = psr.getConnectionGroup();
|
||||
if (connectionGroup != 0) {
|
||||
final int connectionImportance = psr.getConnectionImportance();
|
||||
if (lastCachedGroupUid == app.uid
|
||||
&& lastCachedGroup == connectionGroup) {
|
||||
// This is in the same group as the last process, just tweak
|
||||
// adjustment by importance.
|
||||
if (connectionImportance > lastCachedGroupImportance) {
|
||||
lastCachedGroupImportance = connectionImportance;
|
||||
if (curCachedAdj < nextCachedAdj
|
||||
// This is in the same group as the last process, just tweak
|
||||
// adjustment by importance.
|
||||
if (connectionImportance > lastCachedGroupImportance) {
|
||||
lastCachedGroupImportance = connectionImportance;
|
||||
if (curCachedAdj < nextCachedAdj
|
||||
&& curCachedAdj < CACHED_APP_MAX_ADJ) {
|
||||
curCachedImpAdj++;
|
||||
curCachedImpAdj++;
|
||||
}
|
||||
}
|
||||
inGroup = true;
|
||||
} else {
|
||||
lastCachedGroupUid = app.uid;
|
||||
lastCachedGroup = connectionGroup;
|
||||
lastCachedGroupImportance = connectionImportance;
|
||||
}
|
||||
}
|
||||
if (!inGroup && curCachedAdj != nextCachedAdj) {
|
||||
stepCached++;
|
||||
curCachedImpAdj = 0;
|
||||
if (stepCached >= cachedFactor) {
|
||||
stepCached = 0;
|
||||
curCachedAdj = nextCachedAdj;
|
||||
nextCachedAdj += CACHED_APP_IMPORTANCE_LEVELS * 2;
|
||||
if (nextCachedAdj > CACHED_APP_MAX_ADJ) {
|
||||
nextCachedAdj = CACHED_APP_MAX_ADJ;
|
||||
}
|
||||
}
|
||||
inGroup = true;
|
||||
} else {
|
||||
lastCachedGroupUid = app.uid;
|
||||
lastCachedGroup = connectionGroup;
|
||||
lastCachedGroupImportance = connectionImportance;
|
||||
}
|
||||
}
|
||||
if (!inGroup && curCachedAdj != nextCachedAdj) {
|
||||
stepCached++;
|
||||
curCachedImpAdj = 0;
|
||||
if (stepCached >= cachedFactor) {
|
||||
stepCached = 0;
|
||||
curCachedAdj = nextCachedAdj;
|
||||
nextCachedAdj += CACHED_APP_IMPORTANCE_LEVELS * 2;
|
||||
if (nextCachedAdj > CACHED_APP_MAX_ADJ) {
|
||||
nextCachedAdj = CACHED_APP_MAX_ADJ;
|
||||
// This process is a cached process holding activities...
|
||||
// assign it the next cached value for that type, and then
|
||||
// step that cached level.
|
||||
state.setCurRawAdj(curCachedAdj + curCachedImpAdj);
|
||||
state.setCurAdj(psr.modifyRawOomAdj(curCachedAdj + curCachedImpAdj));
|
||||
if (DEBUG_LRU) {
|
||||
Slog.d(TAG_LRU, "Assigning activity LRU #" + i
|
||||
+ " adj: " + state.getCurAdj()
|
||||
+ " (curCachedAdj=" + curCachedAdj
|
||||
+ " curCachedImpAdj=" + curCachedImpAdj + ")");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// Figure out the next cached level.
|
||||
if (curEmptyAdj != nextEmptyAdj) {
|
||||
stepEmpty++;
|
||||
if (stepEmpty >= emptyFactor) {
|
||||
stepEmpty = 0;
|
||||
curEmptyAdj = nextEmptyAdj;
|
||||
nextEmptyAdj += CACHED_APP_IMPORTANCE_LEVELS * 2;
|
||||
if (nextEmptyAdj > CACHED_APP_MAX_ADJ) {
|
||||
nextEmptyAdj = CACHED_APP_MAX_ADJ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// This process is a cached process holding activities...
|
||||
// assign it the next cached value for that type, and then
|
||||
// step that cached level.
|
||||
state.setCurRawAdj(curCachedAdj + curCachedImpAdj);
|
||||
state.setCurAdj(psr.modifyRawOomAdj(curCachedAdj + curCachedImpAdj));
|
||||
if (DEBUG_LRU) {
|
||||
Slog.d(TAG_LRU, "Assigning activity LRU #" + i
|
||||
+ " adj: " + state.getCurAdj()
|
||||
+ " (curCachedAdj=" + curCachedAdj
|
||||
+ " curCachedImpAdj=" + curCachedImpAdj + ")");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// Figure out the next cached level.
|
||||
if (curEmptyAdj != nextEmptyAdj) {
|
||||
stepEmpty++;
|
||||
if (stepEmpty >= emptyFactor) {
|
||||
stepEmpty = 0;
|
||||
curEmptyAdj = nextEmptyAdj;
|
||||
nextEmptyAdj += CACHED_APP_IMPORTANCE_LEVELS * 2;
|
||||
if (nextEmptyAdj > CACHED_APP_MAX_ADJ) {
|
||||
nextEmptyAdj = CACHED_APP_MAX_ADJ;
|
||||
}
|
||||
// For everything else, assign next empty cached process
|
||||
// level and bump that up. Note that this means that
|
||||
// long-running services that have dropped down to the
|
||||
// cached level will be treated as empty (since their process
|
||||
// state is still as a service), which is what we want.
|
||||
state.setCurRawAdj(curEmptyAdj);
|
||||
state.setCurAdj(psr.modifyRawOomAdj(curEmptyAdj));
|
||||
if (DEBUG_LRU) {
|
||||
Slog.d(TAG_LRU, "Assigning empty LRU #" + i
|
||||
+ " adj: " + state.getCurAdj()
|
||||
+ " (curEmptyAdj=" + curEmptyAdj
|
||||
+ ")");
|
||||
}
|
||||
}
|
||||
// For everything else, assign next empty cached process
|
||||
// level and bump that up. Note that this means that
|
||||
// long-running services that have dropped down to the
|
||||
// cached level will be treated as empty (since their process
|
||||
// state is still as a service), which is what we want.
|
||||
state.setCurRawAdj(curEmptyAdj);
|
||||
state.setCurAdj(psr.modifyRawOomAdj(curEmptyAdj));
|
||||
if (DEBUG_LRU) {
|
||||
Slog.d(TAG_LRU, "Assigning empty LRU #" + i
|
||||
+ " adj: " + state.getCurAdj() + " (curEmptyAdj=" + curEmptyAdj
|
||||
+ ")");
|
||||
}
|
||||
break;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private long mNextNoKillDebugMessageTime;
|
||||
|
||||
private double mLastFreeSwapPercent = 1.00;
|
||||
@@ -2018,25 +2048,37 @@ public class OomAdjuster {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (state.getCachedIsPreviousProcess() && state.getCachedHasActivities()) {
|
||||
if (adj > 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 = PREVIOUS_APP_ADJ;
|
||||
schedGroup = SCHED_GROUP_BACKGROUND;
|
||||
state.setCached(false);
|
||||
state.setAdjType("previous");
|
||||
if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
|
||||
reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise adj to prev: " + app);
|
||||
}
|
||||
}
|
||||
if (procState > PROCESS_STATE_LAST_ACTIVITY) {
|
||||
// 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. However, we don't want to keep the
|
||||
// process in this privileged state indefinitely. Eventually, allow the
|
||||
// app to be demoted to cached.
|
||||
if ((state.getSetProcState() == PROCESS_STATE_LAST_ACTIVITY
|
||||
&& (state.getLastStateTime() + mConstants.MAX_PREVIOUS_TIME) < now)) {
|
||||
procState = PROCESS_STATE_LAST_ACTIVITY;
|
||||
state.setAdjType("previous");
|
||||
schedGroup = SCHED_GROUP_BACKGROUND;
|
||||
state.setAdjType("previous-expired");
|
||||
adj = CACHED_APP_MIN_ADJ;
|
||||
if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
|
||||
reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise procstate to prev: " + app);
|
||||
reportOomAdjMessageLocked(TAG_OOM_ADJ, "Expire prev adj: " + app);
|
||||
}
|
||||
} else {
|
||||
if (adj > PREVIOUS_APP_ADJ) {
|
||||
adj = PREVIOUS_APP_ADJ;
|
||||
schedGroup = SCHED_GROUP_BACKGROUND;
|
||||
state.setCached(false);
|
||||
state.setAdjType("previous");
|
||||
if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
|
||||
reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise adj to prev: " + app);
|
||||
}
|
||||
}
|
||||
if (procState > PROCESS_STATE_LAST_ACTIVITY) {
|
||||
procState = PROCESS_STATE_LAST_ACTIVITY;
|
||||
state.setAdjType("previous");
|
||||
if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
|
||||
reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise procstate to prev: " + app);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -143,8 +143,8 @@ public class MockingOomAdjusterTests {
|
||||
private static final String MOCKAPP5_PROCESSNAME = "test #5";
|
||||
private static final String MOCKAPP5_PACKAGENAME = "com.android.test.test5";
|
||||
private static final int MOCKAPP2_UID_OTHER = MOCKAPP2_UID + UserHandle.PER_USER_RANGE;
|
||||
private static final int FIRST_CACHED_ADJ = ProcessList.CACHED_APP_MIN_ADJ
|
||||
+ ProcessList.CACHED_APP_IMPORTANCE_LEVELS;
|
||||
private static int sFirstCachedAdj = ProcessList.CACHED_APP_MIN_ADJ
|
||||
+ ProcessList.CACHED_APP_IMPORTANCE_LEVELS;
|
||||
private static Context sContext;
|
||||
private static PackageManagerInternal sPackageManagerInternal;
|
||||
private static ActivityManagerService sService;
|
||||
@@ -208,6 +208,9 @@ public class MockingOomAdjusterTests {
|
||||
new ActiveUids(sService, false));
|
||||
sService.mOomAdjuster.mAdjSeq = 10000;
|
||||
sService.mWakefulness = new AtomicInteger(PowerManagerInternal.WAKEFULNESS_AWAKE);
|
||||
if (sService.mConstants.USE_TIERED_CACHED_ADJ) {
|
||||
sFirstCachedAdj = ProcessList.CACHED_APP_MIN_ADJ + 10;
|
||||
}
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
@@ -834,7 +837,7 @@ public class MockingOomAdjusterTests {
|
||||
updateOomAdj(client, app);
|
||||
doReturn(null).when(sService).getTopApp();
|
||||
|
||||
assertProcStates(app, PROCESS_STATE_SERVICE, FIRST_CACHED_ADJ, SCHED_GROUP_BACKGROUND);
|
||||
assertProcStates(app, PROCESS_STATE_SERVICE, sFirstCachedAdj, SCHED_GROUP_BACKGROUND);
|
||||
}
|
||||
|
||||
@SuppressWarnings("GuardedBy")
|
||||
@@ -882,7 +885,7 @@ public class MockingOomAdjusterTests {
|
||||
sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
|
||||
updateOomAdj(app);
|
||||
|
||||
assertProcStates(app, PROCESS_STATE_CACHED_EMPTY, FIRST_CACHED_ADJ, SCHED_GROUP_BACKGROUND);
|
||||
assertProcStates(app, PROCESS_STATE_CACHED_EMPTY, sFirstCachedAdj, SCHED_GROUP_BACKGROUND);
|
||||
}
|
||||
|
||||
@SuppressWarnings("GuardedBy")
|
||||
@@ -1286,7 +1289,7 @@ public class MockingOomAdjusterTests {
|
||||
bindProvider(app, app, null, null, false);
|
||||
updateOomAdj(app);
|
||||
|
||||
assertProcStates(app, PROCESS_STATE_CACHED_EMPTY, FIRST_CACHED_ADJ, SCHED_GROUP_BACKGROUND);
|
||||
assertProcStates(app, PROCESS_STATE_CACHED_EMPTY, sFirstCachedAdj, SCHED_GROUP_BACKGROUND);
|
||||
}
|
||||
|
||||
@SuppressWarnings("GuardedBy")
|
||||
@@ -1301,7 +1304,7 @@ public class MockingOomAdjusterTests {
|
||||
sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
|
||||
updateOomAdj(app, client);
|
||||
|
||||
assertProcStates(app, PROCESS_STATE_CACHED_EMPTY, FIRST_CACHED_ADJ, SCHED_GROUP_BACKGROUND);
|
||||
assertProcStates(app, PROCESS_STATE_CACHED_EMPTY, sFirstCachedAdj, SCHED_GROUP_BACKGROUND);
|
||||
}
|
||||
|
||||
@SuppressWarnings("GuardedBy")
|
||||
@@ -2378,8 +2381,12 @@ public class MockingOomAdjusterTests {
|
||||
MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
|
||||
final int userOwner = 0;
|
||||
final int userOther = 1;
|
||||
final int cachedAdj1 = CACHED_APP_MIN_ADJ + ProcessList.CACHED_APP_IMPORTANCE_LEVELS;
|
||||
final int cachedAdj2 = cachedAdj1 + ProcessList.CACHED_APP_IMPORTANCE_LEVELS * 2;
|
||||
final int cachedAdj1 = sService.mConstants.USE_TIERED_CACHED_ADJ
|
||||
? CACHED_APP_MIN_ADJ + 10
|
||||
: CACHED_APP_MIN_ADJ + ProcessList.CACHED_APP_IMPORTANCE_LEVELS;
|
||||
final int cachedAdj2 = sService.mConstants.USE_TIERED_CACHED_ADJ
|
||||
? CACHED_APP_MIN_ADJ + 10
|
||||
: cachedAdj1 + ProcessList.CACHED_APP_IMPORTANCE_LEVELS * 2;
|
||||
doReturn(userOwner).when(sService.mUserController).getCurrentUserId();
|
||||
|
||||
final ArrayList<ProcessRecord> lru = sService.mProcessList.getLruProcessesLOSP();
|
||||
|
||||
Reference in New Issue
Block a user