Merge "Do not proactively kill cached/empty processes post boot" into tm-dev
This commit is contained in:
@@ -650,6 +650,38 @@ final class ActivityManagerConstants extends ContentObserver {
|
|||||||
// initialized in the constructor.
|
// initialized in the constructor.
|
||||||
public int CUR_MAX_EMPTY_PROCESSES;
|
public int CUR_MAX_EMPTY_PROCESSES;
|
||||||
|
|
||||||
|
|
||||||
|
/** @see #mNoKillCachedProcessesUntilBootCompleted */
|
||||||
|
private static final String KEY_NO_KILL_CACHED_PROCESSES_UNTIL_BOOT_COMPLETED =
|
||||||
|
"no_kill_cached_processes_until_boot_completed";
|
||||||
|
|
||||||
|
/** @see #mNoKillCachedProcessesPostBootCompletedDurationMillis */
|
||||||
|
private static final String KEY_NO_KILL_CACHED_PROCESSES_POST_BOOT_COMPLETED_DURATION_MILLIS =
|
||||||
|
"no_kill_cached_processes_post_boot_completed_duration_millis";
|
||||||
|
|
||||||
|
/** @see #mNoKillCachedProcessesUntilBootCompleted */
|
||||||
|
private static final boolean DEFAULT_NO_KILL_CACHED_PROCESSES_UNTIL_BOOT_COMPLETED = false;
|
||||||
|
|
||||||
|
/** @see #mNoKillCachedProcessesPostBootCompletedDurationMillis */
|
||||||
|
private static final long
|
||||||
|
DEFAULT_NO_KILL_CACHED_PROCESSES_POST_BOOT_COMPLETED_DURATION_MILLIS = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If true, do not kill excessive cached processes proactively, until user-0 is unlocked.
|
||||||
|
* @see #mNoKillCachedProcessesPostBootCompletedDurationMillis
|
||||||
|
*/
|
||||||
|
volatile boolean mNoKillCachedProcessesUntilBootCompleted =
|
||||||
|
DEFAULT_NO_KILL_CACHED_PROCESSES_UNTIL_BOOT_COMPLETED;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Do not kill excessive cached processes proactively, for this duration after each user is
|
||||||
|
* unlocked.
|
||||||
|
* Note we don't proactively kill extra cached processes after this. The next oomadjuster pass
|
||||||
|
* will naturally do it.
|
||||||
|
*/
|
||||||
|
volatile long mNoKillCachedProcessesPostBootCompletedDurationMillis =
|
||||||
|
DEFAULT_NO_KILL_CACHED_PROCESSES_POST_BOOT_COMPLETED_DURATION_MILLIS;
|
||||||
|
|
||||||
// The number of empty apps at which we don't consider it necessary to do
|
// The number of empty apps at which we don't consider it necessary to do
|
||||||
// memory trimming.
|
// memory trimming.
|
||||||
public int CUR_TRIM_EMPTY_PROCESSES = computeEmptyProcessLimit(MAX_CACHED_PROCESSES) / 2;
|
public int CUR_TRIM_EMPTY_PROCESSES = computeEmptyProcessLimit(MAX_CACHED_PROCESSES) / 2;
|
||||||
@@ -659,6 +691,14 @@ final class ActivityManagerConstants extends ContentObserver {
|
|||||||
public int CUR_TRIM_CACHED_PROCESSES =
|
public int CUR_TRIM_CACHED_PROCESSES =
|
||||||
(MAX_CACHED_PROCESSES - computeEmptyProcessLimit(MAX_CACHED_PROCESSES)) / 3;
|
(MAX_CACHED_PROCESSES - computeEmptyProcessLimit(MAX_CACHED_PROCESSES)) / 3;
|
||||||
|
|
||||||
|
/** @see #mNoKillCachedProcessesUntilBootCompleted */
|
||||||
|
private static final String KEY_MAX_EMPTY_TIME_MILLIS =
|
||||||
|
"max_empty_time_millis";
|
||||||
|
|
||||||
|
private static final long DEFAULT_MAX_EMPTY_TIME_MILLIS = 30 * 60 * 1000;
|
||||||
|
|
||||||
|
volatile long mMaxEmptyTimeMillis = DEFAULT_MAX_EMPTY_TIME_MILLIS;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Packages that can't be killed even if it's requested to be killed on imperceptible.
|
* Packages that can't be killed even if it's requested to be killed on imperceptible.
|
||||||
*/
|
*/
|
||||||
@@ -869,6 +909,15 @@ final class ActivityManagerConstants extends ContentObserver {
|
|||||||
case KEY_DEFER_BOOT_COMPLETED_BROADCAST:
|
case KEY_DEFER_BOOT_COMPLETED_BROADCAST:
|
||||||
updateDeferBootCompletedBroadcast();
|
updateDeferBootCompletedBroadcast();
|
||||||
break;
|
break;
|
||||||
|
case KEY_NO_KILL_CACHED_PROCESSES_UNTIL_BOOT_COMPLETED:
|
||||||
|
updateNoKillCachedProcessesUntilBootCompleted();
|
||||||
|
break;
|
||||||
|
case KEY_NO_KILL_CACHED_PROCESSES_POST_BOOT_COMPLETED_DURATION_MILLIS:
|
||||||
|
updateNoKillCachedProcessesPostBootCompletedDurationMillis();
|
||||||
|
break;
|
||||||
|
case KEY_MAX_EMPTY_TIME_MILLIS:
|
||||||
|
updateMaxEmptyTimeMillis();
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -1288,6 +1337,27 @@ final class ActivityManagerConstants extends ContentObserver {
|
|||||||
DEFAULT_DEFER_BOOT_COMPLETED_BROADCAST);
|
DEFAULT_DEFER_BOOT_COMPLETED_BROADCAST);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void updateNoKillCachedProcessesUntilBootCompleted() {
|
||||||
|
mNoKillCachedProcessesUntilBootCompleted = DeviceConfig.getBoolean(
|
||||||
|
DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
|
||||||
|
KEY_NO_KILL_CACHED_PROCESSES_UNTIL_BOOT_COMPLETED,
|
||||||
|
DEFAULT_NO_KILL_CACHED_PROCESSES_UNTIL_BOOT_COMPLETED);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateNoKillCachedProcessesPostBootCompletedDurationMillis() {
|
||||||
|
mNoKillCachedProcessesPostBootCompletedDurationMillis = DeviceConfig.getLong(
|
||||||
|
DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
|
||||||
|
KEY_NO_KILL_CACHED_PROCESSES_POST_BOOT_COMPLETED_DURATION_MILLIS,
|
||||||
|
DEFAULT_NO_KILL_CACHED_PROCESSES_POST_BOOT_COMPLETED_DURATION_MILLIS);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateMaxEmptyTimeMillis() {
|
||||||
|
mMaxEmptyTimeMillis = DeviceConfig.getLong(
|
||||||
|
DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
|
||||||
|
KEY_MAX_EMPTY_TIME_MILLIS,
|
||||||
|
DEFAULT_MAX_EMPTY_TIME_MILLIS);
|
||||||
|
}
|
||||||
|
|
||||||
private long[] parseLongArray(@NonNull String key, @NonNull long[] def) {
|
private long[] parseLongArray(@NonNull String key, @NonNull long[] def) {
|
||||||
final String val = DeviceConfig.getString(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
|
final String val = DeviceConfig.getString(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
|
||||||
key, null);
|
key, null);
|
||||||
@@ -1562,6 +1632,12 @@ final class ActivityManagerConstants extends ContentObserver {
|
|||||||
pw.print("="); pw.println(mComponentAliasOverrides);
|
pw.print("="); pw.println(mComponentAliasOverrides);
|
||||||
pw.print(" "); pw.print(KEY_DEFER_BOOT_COMPLETED_BROADCAST);
|
pw.print(" "); pw.print(KEY_DEFER_BOOT_COMPLETED_BROADCAST);
|
||||||
pw.print("="); pw.println(mDeferBootCompletedBroadcast);
|
pw.print("="); pw.println(mDeferBootCompletedBroadcast);
|
||||||
|
pw.print(" "); pw.print(KEY_NO_KILL_CACHED_PROCESSES_UNTIL_BOOT_COMPLETED);
|
||||||
|
pw.print("="); pw.println(mNoKillCachedProcessesUntilBootCompleted);
|
||||||
|
pw.print(" "); pw.print(KEY_NO_KILL_CACHED_PROCESSES_POST_BOOT_COMPLETED_DURATION_MILLIS);
|
||||||
|
pw.print("="); pw.println(mNoKillCachedProcessesPostBootCompletedDurationMillis);
|
||||||
|
pw.print(" "); pw.print(KEY_MAX_EMPTY_TIME_MILLIS);
|
||||||
|
pw.print("="); pw.println(mMaxEmptyTimeMillis);
|
||||||
|
|
||||||
pw.println();
|
pw.println();
|
||||||
if (mOverrideMaxCachedProcesses >= 0) {
|
if (mOverrideMaxCachedProcesses >= 0) {
|
||||||
|
|||||||
@@ -750,7 +750,7 @@ public class OomAdjuster {
|
|||||||
}
|
}
|
||||||
final long now = SystemClock.uptimeMillis();
|
final long now = SystemClock.uptimeMillis();
|
||||||
final long nowElapsed = SystemClock.elapsedRealtime();
|
final long nowElapsed = SystemClock.elapsedRealtime();
|
||||||
final long oldTime = now - ProcessList.MAX_EMPTY_TIME;
|
final long oldTime = now - mConstants.mMaxEmptyTimeMillis;
|
||||||
final boolean fullUpdate = processes == null;
|
final boolean fullUpdate = processes == null;
|
||||||
ActiveUids activeUids = uids;
|
ActiveUids activeUids = uids;
|
||||||
ArrayList<ProcessRecord> activeProcesses = fullUpdate ? mProcessList.getLruProcessesLOSP()
|
ArrayList<ProcessRecord> activeProcesses = fullUpdate ? mProcessList.getLruProcessesLOSP()
|
||||||
@@ -1031,15 +1031,25 @@ public class OomAdjuster {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private long mNextNoKillDebugMessageTime;
|
||||||
|
|
||||||
@GuardedBy({"mService", "mProcLock"})
|
@GuardedBy({"mService", "mProcLock"})
|
||||||
private boolean updateAndTrimProcessLSP(final long now, final long nowElapsed,
|
private boolean updateAndTrimProcessLSP(final long now, final long nowElapsed,
|
||||||
final long oldTime, final ActiveUids activeUids) {
|
final long oldTime, final ActiveUids activeUids) {
|
||||||
ArrayList<ProcessRecord> lruList = mProcessList.getLruProcessesLOSP();
|
ArrayList<ProcessRecord> lruList = mProcessList.getLruProcessesLOSP();
|
||||||
final int numLru = lruList.size();
|
final int numLru = lruList.size();
|
||||||
|
|
||||||
final int emptyProcessLimit = mConstants.CUR_MAX_EMPTY_PROCESSES;
|
final boolean doKillExcessiveProcesses = shouldKillExcessiveProcesses(now);
|
||||||
final int cachedProcessLimit = mConstants.CUR_MAX_CACHED_PROCESSES
|
if (!doKillExcessiveProcesses) {
|
||||||
- emptyProcessLimit;
|
if (mNextNoKillDebugMessageTime < now) {
|
||||||
|
Slog.d(TAG, "Not killing cached processes"); // STOPSHIP Remove it b/222365734
|
||||||
|
mNextNoKillDebugMessageTime = now + 5000; // Every 5 seconds
|
||||||
|
}
|
||||||
|
}
|
||||||
|
final int emptyProcessLimit = doKillExcessiveProcesses
|
||||||
|
? mConstants.CUR_MAX_EMPTY_PROCESSES : Integer.MAX_VALUE;
|
||||||
|
final int cachedProcessLimit = doKillExcessiveProcesses
|
||||||
|
? (mConstants.CUR_MAX_CACHED_PROCESSES - emptyProcessLimit) : Integer.MAX_VALUE;
|
||||||
int lastCachedGroup = 0;
|
int lastCachedGroup = 0;
|
||||||
int lastCachedGroupUid = 0;
|
int lastCachedGroupUid = 0;
|
||||||
int numCached = 0;
|
int numCached = 0;
|
||||||
@@ -1089,7 +1099,7 @@ public class OomAdjuster {
|
|||||||
case PROCESS_STATE_CACHED_EMPTY:
|
case PROCESS_STATE_CACHED_EMPTY:
|
||||||
if (numEmpty > mConstants.CUR_TRIM_EMPTY_PROCESSES
|
if (numEmpty > mConstants.CUR_TRIM_EMPTY_PROCESSES
|
||||||
&& app.getLastActivityTime() < oldTime) {
|
&& app.getLastActivityTime() < oldTime) {
|
||||||
app.killLocked("empty for " + ((oldTime + ProcessList.MAX_EMPTY_TIME
|
app.killLocked("empty for " + ((now
|
||||||
- app.getLastActivityTime()) / 1000) + "s",
|
- app.getLastActivityTime()) / 1000) + "s",
|
||||||
"empty for too long",
|
"empty for too long",
|
||||||
ApplicationExitInfo.REASON_OTHER,
|
ApplicationExitInfo.REASON_OTHER,
|
||||||
@@ -1258,6 +1268,25 @@ public class OomAdjuster {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return true if we should kill excessive cached/empty processes.
|
||||||
|
*/
|
||||||
|
private boolean shouldKillExcessiveProcesses(long nowUptime) {
|
||||||
|
final long lastUserUnlockingUptime = mService.mUserController.getLastUserUnlockingUptime();
|
||||||
|
|
||||||
|
if (lastUserUnlockingUptime == 0) {
|
||||||
|
// No users have been unlocked.
|
||||||
|
return !mConstants.mNoKillCachedProcessesUntilBootCompleted;
|
||||||
|
}
|
||||||
|
final long noKillCachedProcessesPostBootCompletedDurationMillis =
|
||||||
|
mConstants.mNoKillCachedProcessesPostBootCompletedDurationMillis;
|
||||||
|
if ((lastUserUnlockingUptime + noKillCachedProcessesPostBootCompletedDurationMillis)
|
||||||
|
> nowUptime) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
private final ComputeOomAdjWindowCallback mTmpComputeOomAdjWindowCallback =
|
private final ComputeOomAdjWindowCallback mTmpComputeOomAdjWindowCallback =
|
||||||
new ComputeOomAdjWindowCallback();
|
new ComputeOomAdjWindowCallback();
|
||||||
|
|
||||||
|
|||||||
@@ -293,9 +293,6 @@ public final class ProcessList {
|
|||||||
// without empty apps being able to push them out of memory.
|
// without empty apps being able to push them out of memory.
|
||||||
static final int MIN_CACHED_APPS = 2;
|
static final int MIN_CACHED_APPS = 2;
|
||||||
|
|
||||||
// We allow empty processes to stick around for at most 30 minutes.
|
|
||||||
static final long MAX_EMPTY_TIME = 30 * 60 * 1000;
|
|
||||||
|
|
||||||
// Threshold of number of cached+empty where we consider memory critical.
|
// Threshold of number of cached+empty where we consider memory critical.
|
||||||
static final int TRIM_CRITICAL_THRESHOLD = 3;
|
static final int TRIM_CRITICAL_THRESHOLD = 3;
|
||||||
|
|
||||||
|
|||||||
@@ -399,6 +399,9 @@ class UserController implements Handler.Callback {
|
|||||||
@GuardedBy("mLock")
|
@GuardedBy("mLock")
|
||||||
private @StopUserOnSwitch int mStopUserOnSwitch = STOP_USER_ON_SWITCH_DEFAULT;
|
private @StopUserOnSwitch int mStopUserOnSwitch = STOP_USER_ON_SWITCH_DEFAULT;
|
||||||
|
|
||||||
|
/** @see #getLastUserUnlockingUptime */
|
||||||
|
private volatile long mLastUserUnlockingUptime = 0;
|
||||||
|
|
||||||
UserController(ActivityManagerService service) {
|
UserController(ActivityManagerService service) {
|
||||||
this(new Injector(service));
|
this(new Injector(service));
|
||||||
}
|
}
|
||||||
@@ -661,6 +664,8 @@ class UserController implements Handler.Callback {
|
|||||||
|
|
||||||
uss.mUnlockProgress.setProgress(20);
|
uss.mUnlockProgress.setProgress(20);
|
||||||
|
|
||||||
|
mLastUserUnlockingUptime = SystemClock.uptimeMillis();
|
||||||
|
|
||||||
// Dispatch unlocked to system services; when fully dispatched,
|
// Dispatch unlocked to system services; when fully dispatched,
|
||||||
// that calls through to the next "unlocked" phase
|
// that calls through to the next "unlocked" phase
|
||||||
mHandler.obtainMessage(USER_UNLOCK_MSG, userId, 0, uss).sendToTarget();
|
mHandler.obtainMessage(USER_UNLOCK_MSG, userId, 0, uss).sendToTarget();
|
||||||
@@ -2753,6 +2758,7 @@ class UserController implements Handler.Callback {
|
|||||||
if (mSwitchingToSystemUserMessage != null) {
|
if (mSwitchingToSystemUserMessage != null) {
|
||||||
pw.println(" mSwitchingToSystemUserMessage: " + mSwitchingToSystemUserMessage);
|
pw.println(" mSwitchingToSystemUserMessage: " + mSwitchingToSystemUserMessage);
|
||||||
}
|
}
|
||||||
|
pw.println(" mLastUserUnlockingUptime:" + mLastUserUnlockingUptime);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3077,6 +3083,14 @@ class UserController implements Handler.Callback {
|
|||||||
return bOptions;
|
return bOptions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Uptime when any user was being unlocked most recently. 0 if no users have been unlocked
|
||||||
|
* yet. To avoid lock contention (since it's used by OomAdjuster), it's volatile internally.
|
||||||
|
*/
|
||||||
|
public long getLastUserUnlockingUptime() {
|
||||||
|
return mLastUserUnlockingUptime;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper class to store user journey and session id.
|
* Helper class to store user journey and session id.
|
||||||
*
|
*
|
||||||
|
|||||||
Reference in New Issue
Block a user