Merge "Keep app in high memory adjust if moving from TOP to FGS" into pi-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
311f0f5da5
@@ -325,6 +325,15 @@ public abstract class Context {
|
||||
*/
|
||||
public static final int BIND_ADJUST_WITH_ACTIVITY = 0x0080;
|
||||
|
||||
/**
|
||||
* Flag for {@link #bindService}: If binding from something better than perceptible,
|
||||
* still set the adjust below perceptible. This would be used for bound services that can
|
||||
* afford to be evicted when under extreme memory pressure, but should be restarted as soon
|
||||
* as possible.
|
||||
* @hide
|
||||
*/
|
||||
public static final int BIND_ADJUST_BELOW_PERCEPTIBLE = 0x0100;
|
||||
|
||||
/**
|
||||
* @hide Flag for {@link #bindService}: allows binding to a service provided
|
||||
* by an instant app. Note that the caller may not have access to the instant
|
||||
|
||||
@@ -67,6 +67,7 @@ final class ActivityManagerConstants extends ContentObserver {
|
||||
static final String KEY_BOUND_SERVICE_CRASH_RESTART_DURATION = "service_crash_restart_duration";
|
||||
static final String KEY_BOUND_SERVICE_CRASH_MAX_RETRY = "service_crash_max_retry";
|
||||
static final String KEY_PROCESS_START_ASYNC = "process_start_async";
|
||||
static final String KEY_TOP_TO_FGS_GRACE_DURATION = "top_to_fgs_grace_duration";
|
||||
|
||||
private static final int DEFAULT_MAX_CACHED_PROCESSES = 32;
|
||||
private static final long DEFAULT_BACKGROUND_SETTLE_TIME = 60*1000;
|
||||
@@ -95,7 +96,7 @@ final class ActivityManagerConstants extends ContentObserver {
|
||||
private static final long DEFAULT_BOUND_SERVICE_CRASH_RESTART_DURATION = 30*60_000;
|
||||
private static final int DEFAULT_BOUND_SERVICE_CRASH_MAX_RETRY = 16;
|
||||
private static final boolean DEFAULT_PROCESS_START_ASYNC = true;
|
||||
|
||||
private static final long DEFAULT_TOP_TO_FGS_GRACE_DURATION = 15 * 1000;
|
||||
|
||||
// Maximum number of cached processes we will allow.
|
||||
public int MAX_CACHED_PROCESSES = DEFAULT_MAX_CACHED_PROCESSES;
|
||||
@@ -207,6 +208,10 @@ final class ActivityManagerConstants extends ContentObserver {
|
||||
// Indicates if the processes need to be started asynchronously.
|
||||
public boolean FLAG_PROCESS_START_ASYNC = DEFAULT_PROCESS_START_ASYNC;
|
||||
|
||||
// Allow app just moving from TOP to FOREGROUND_SERVICE to stay in a higher adj value for
|
||||
// this long.
|
||||
public long TOP_TO_FGS_GRACE_DURATION = DEFAULT_TOP_TO_FGS_GRACE_DURATION;
|
||||
|
||||
// Indicates whether the activity starts logging is enabled.
|
||||
// Controlled by Settings.Global.ACTIVITY_STARTS_LOGGING_ENABLED
|
||||
boolean mFlagActivityStartsLoggingEnabled;
|
||||
@@ -348,6 +353,8 @@ final class ActivityManagerConstants extends ContentObserver {
|
||||
DEFAULT_BOUND_SERVICE_CRASH_MAX_RETRY);
|
||||
FLAG_PROCESS_START_ASYNC = mParser.getBoolean(KEY_PROCESS_START_ASYNC,
|
||||
DEFAULT_PROCESS_START_ASYNC);
|
||||
TOP_TO_FGS_GRACE_DURATION = mParser.getDurationMillis(KEY_TOP_TO_FGS_GRACE_DURATION,
|
||||
DEFAULT_TOP_TO_FGS_GRACE_DURATION);
|
||||
|
||||
updateMaxCachedProcesses();
|
||||
}
|
||||
@@ -423,6 +430,8 @@ final class ActivityManagerConstants extends ContentObserver {
|
||||
pw.println(MAX_SERVICE_INACTIVITY);
|
||||
pw.print(" "); pw.print(KEY_BG_START_TIMEOUT); pw.print("=");
|
||||
pw.println(BG_START_TIMEOUT);
|
||||
pw.print(" "); pw.print(KEY_TOP_TO_FGS_GRACE_DURATION); pw.print("=");
|
||||
pw.println(TOP_TO_FGS_GRACE_DURATION);
|
||||
|
||||
pw.println();
|
||||
if (mOverrideMaxCachedProcesses >= 0) {
|
||||
|
||||
@@ -23390,6 +23390,19 @@ public class ActivityManagerService extends IActivityManager.Stub
|
||||
}
|
||||
}
|
||||
|
||||
// If the app was recently in the foreground and moved to a foreground service status,
|
||||
// allow it to get a higher rank in memory for some time, compared to other foreground
|
||||
// services so that it can finish performing any persistence/processing of in-memory state.
|
||||
if (app.foregroundServices && adj > ProcessList.PERCEPTIBLE_RECENT_FOREGROUND_APP_ADJ
|
||||
&& (app.lastTopTime + mConstants.TOP_TO_FGS_GRACE_DURATION > now
|
||||
|| app.setProcState <= ActivityManager.PROCESS_STATE_TOP)) {
|
||||
adj = ProcessList.PERCEPTIBLE_RECENT_FOREGROUND_APP_ADJ;
|
||||
app.adjType = "fg-service-act";
|
||||
if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
|
||||
reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise to recent fg: " + app);
|
||||
}
|
||||
}
|
||||
|
||||
if (adj > ProcessList.PERCEPTIBLE_APP_ADJ
|
||||
|| procState > ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND) {
|
||||
if (app.forcingToImportant != null) {
|
||||
@@ -23654,6 +23667,10 @@ public class ActivityManagerService extends IActivityManager.Stub
|
||||
schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
|
||||
procState = ActivityManager.PROCESS_STATE_PERSISTENT;
|
||||
}
|
||||
} else if ((cr.flags & Context.BIND_ADJUST_BELOW_PERCEPTIBLE) != 0
|
||||
&& clientAdj < ProcessList.PERCEPTIBLE_APP_ADJ
|
||||
&& adj > ProcessList.PERCEPTIBLE_APP_ADJ + 1) {
|
||||
newAdj = ProcessList.PERCEPTIBLE_APP_ADJ + 1;
|
||||
} else if ((cr.flags&Context.BIND_NOT_VISIBLE) != 0
|
||||
&& clientAdj < ProcessList.PERCEPTIBLE_APP_ADJ
|
||||
&& adj > ProcessList.PERCEPTIBLE_APP_ADJ) {
|
||||
@@ -24624,6 +24641,8 @@ public class ActivityManagerService extends IActivityManager.Stub
|
||||
// Must be called before updating setProcState
|
||||
maybeUpdateUsageStatsLocked(app, nowElapsed);
|
||||
|
||||
maybeUpdateLastTopTime(app, now);
|
||||
|
||||
app.setProcState = app.curProcState;
|
||||
if (app.setProcState >= ActivityManager.PROCESS_STATE_HOME) {
|
||||
app.notCachedSinceIdle = false;
|
||||
@@ -24848,6 +24867,13 @@ public class ActivityManagerService extends IActivityManager.Stub
|
||||
}
|
||||
}
|
||||
|
||||
private void maybeUpdateLastTopTime(ProcessRecord app, long nowUptime) {
|
||||
if (app.setProcState <= ActivityManager.PROCESS_STATE_TOP
|
||||
&& app.curProcState > ActivityManager.PROCESS_STATE_TOP) {
|
||||
app.lastTopTime = nowUptime;
|
||||
}
|
||||
}
|
||||
|
||||
private final void setProcessTrackerStateLocked(ProcessRecord proc, int memFactor, long now) {
|
||||
if (proc.thread != null) {
|
||||
if (proc.baseProcessTracker != null) {
|
||||
|
||||
@@ -104,6 +104,11 @@ public final class ProcessList {
|
||||
static final int VISIBLE_APP_ADJ = 100;
|
||||
static final int VISIBLE_APP_LAYER_MAX = PERCEPTIBLE_APP_ADJ - VISIBLE_APP_ADJ - 1;
|
||||
|
||||
// This is a process that was recently TOP and moved to FGS. Continue to treat it almost
|
||||
// like a foreground app for a while.
|
||||
// @see TOP_TO_FGS_GRACE_PERIOD
|
||||
static final int PERCEPTIBLE_RECENT_FOREGROUND_APP_ADJ = 50;
|
||||
|
||||
// This is the process running the current foreground app. We'd really
|
||||
// rather not kill it!
|
||||
static final int FOREGROUND_APP_ADJ = 0;
|
||||
|
||||
@@ -163,6 +163,7 @@ final class ProcessRecord {
|
||||
long lastRequestedGc; // When we last asked the app to do a gc
|
||||
long lastLowMemory; // When we last told the app that memory is low
|
||||
long lastProviderTime; // The last time someone else was using a provider in this process.
|
||||
long lastTopTime; // The last time the process was in the TOP state or greater.
|
||||
boolean reportLowMemory; // Set to true when waiting to report low mem
|
||||
boolean empty; // Is this an empty background process?
|
||||
boolean cached; // Is this a cached process?
|
||||
@@ -380,6 +381,11 @@ final class ProcessRecord {
|
||||
TimeUtils.formatDuration(lastProviderTime, nowUptime, pw);
|
||||
pw.println();
|
||||
}
|
||||
if (lastTopTime > 0) {
|
||||
pw.print(prefix); pw.print("lastTopTime=");
|
||||
TimeUtils.formatDuration(lastTopTime, nowUptime, pw);
|
||||
pw.println();
|
||||
}
|
||||
if (hasStartedServices) {
|
||||
pw.print(prefix); pw.print("hasStartedServices="); pw.println(hasStartedServices);
|
||||
}
|
||||
|
||||
@@ -175,6 +175,10 @@ abstract public class ManagedServices {
|
||||
}
|
||||
}
|
||||
|
||||
protected int getBindFlags() {
|
||||
return BIND_AUTO_CREATE | BIND_FOREGROUND_SERVICE | BIND_ALLOW_WHITELIST_MANAGEMENT;
|
||||
}
|
||||
|
||||
protected void onServiceRemovedLocked(ManagedServiceInfo removed) { }
|
||||
|
||||
private ManagedServiceInfo newServiceInfo(IInterface service,
|
||||
@@ -1022,9 +1026,9 @@ abstract public class ManagedServices {
|
||||
}
|
||||
};
|
||||
if (!mContext.bindServiceAsUser(intent,
|
||||
serviceConnection,
|
||||
BIND_AUTO_CREATE | BIND_FOREGROUND_SERVICE | BIND_ALLOW_WHITELIST_MANAGEMENT,
|
||||
new UserHandle(userid))) {
|
||||
serviceConnection,
|
||||
getBindFlags(),
|
||||
new UserHandle(userid))) {
|
||||
mServicesBinding.remove(servicesBindingTag);
|
||||
Slog.w(TAG, "Unable to bind " + getCaption() + " service: " + intent);
|
||||
return;
|
||||
|
||||
@@ -33,6 +33,10 @@ import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_PEEK;
|
||||
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_SCREEN_OFF;
|
||||
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_SCREEN_ON;
|
||||
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_STATUS_BAR;
|
||||
import static android.content.Context.BIND_ADJUST_BELOW_PERCEPTIBLE;
|
||||
import static android.content.Context.BIND_ALLOW_WHITELIST_MANAGEMENT;
|
||||
import static android.content.Context.BIND_AUTO_CREATE;
|
||||
import static android.content.Context.BIND_FOREGROUND_SERVICE;
|
||||
import static android.content.pm.PackageManager.FEATURE_LEANBACK;
|
||||
import static android.content.pm.PackageManager.FEATURE_TELEVISION;
|
||||
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
|
||||
@@ -6520,6 +6524,16 @@ public class NotificationManagerService extends SystemService {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getBindFlags() {
|
||||
// Most of the same flags as the base, but also add BIND_ADJUST_BELOW_PERCEPTIBLE
|
||||
// because too many 3P apps could be kept in memory as notification listeners and
|
||||
// cause extreme memory pressure.
|
||||
// TODO: Change the binding lifecycle of NotificationListeners to avoid this situation.
|
||||
return BIND_AUTO_CREATE | BIND_FOREGROUND_SERVICE
|
||||
| BIND_ADJUST_BELOW_PERCEPTIBLE | BIND_ALLOW_WHITELIST_MANAGEMENT;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Config getConfig() {
|
||||
Config c = new Config();
|
||||
|
||||
Reference in New Issue
Block a user