diff --git a/services/core/java/com/android/server/am/ActivityManagerConstants.java b/services/core/java/com/android/server/am/ActivityManagerConstants.java index 44f475f925174..9d4174dfcc16f 100644 --- a/services/core/java/com/android/server/am/ActivityManagerConstants.java +++ b/services/core/java/com/android/server/am/ActivityManagerConstants.java @@ -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 @@ -192,6 +193,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; @@ -534,6 +536,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. @@ -1171,6 +1176,9 @@ final class ActivityManagerConstants extends ContentObserver { case KEY_ENABLE_WAIT_FOR_FINISH_ATTACH_APPLICATION: updateEnableWaitForFinishAttachApplication(); break; + case KEY_MAX_PREVIOUS_TIME: + updateMaxPreviousTime(); + break; default: break; } @@ -1825,6 +1833,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 +1841,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, diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java index 32db33d3047d2..baa2f8e46dd89 100644 --- a/services/core/java/com/android/server/am/OomAdjuster.java +++ b/services/core/java/com/android/server/am/OomAdjuster.java @@ -2018,25 +2018,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); + } } } }