Merge "Keep app in high memory adjust if moving from TOP to FGS" into pi-dev

This commit is contained in:
TreeHugger Robot
2018-09-28 00:50:39 +00:00
committed by Android (Google) Code Review
7 changed files with 77 additions and 4 deletions

View File

@@ -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

View File

@@ -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) {

View File

@@ -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) {

View File

@@ -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;

View File

@@ -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);
}

View File

@@ -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;

View File

@@ -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();