Merge "Add support for freezing cached apps"
This commit is contained in:
committed by
Android (Google) Code Review
commit
b83a44dcd9
@@ -861,6 +861,17 @@ public class Process {
|
||||
public static final native void setProcessGroup(int pid, int group)
|
||||
throws IllegalArgumentException, SecurityException;
|
||||
|
||||
/**
|
||||
* Freeze or unfreeze the specified process.
|
||||
*
|
||||
* @param pid Identifier of the process to freeze or unfreeze.
|
||||
* @param uid Identifier of the user the process is running under.
|
||||
* @param frozen Specify whether to free (true) or unfreeze (false).
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public static final native void setProcessFrozen(int pid, int uid, boolean frozen);
|
||||
|
||||
/**
|
||||
* Return the scheduling group of requested process.
|
||||
*
|
||||
|
||||
@@ -330,6 +330,22 @@ void android_os_Process_setProcessGroup(JNIEnv* env, jobject clazz, int pid, jin
|
||||
closedir(d);
|
||||
}
|
||||
|
||||
void android_os_Process_setProcessFrozen(
|
||||
JNIEnv *env, jobject clazz, jint pid, jint uid, jboolean freeze)
|
||||
{
|
||||
bool success = true;
|
||||
|
||||
if (freeze) {
|
||||
success = SetProcessProfiles(uid, pid, {"Frozen"});
|
||||
} else {
|
||||
success = SetProcessProfiles(uid, pid, {"Unfrozen"});
|
||||
}
|
||||
|
||||
if (!success) {
|
||||
signalExceptionForGroupError(env, EINVAL, pid);
|
||||
}
|
||||
}
|
||||
|
||||
jint android_os_Process_getProcessGroup(JNIEnv* env, jobject clazz, jint pid)
|
||||
{
|
||||
SchedPolicy sp;
|
||||
@@ -1327,6 +1343,7 @@ static const JNINativeMethod methods[] = {
|
||||
{"setGid", "(I)I", (void*)android_os_Process_setGid},
|
||||
{"sendSignal", "(II)V", (void*)android_os_Process_sendSignal},
|
||||
{"sendSignalQuiet", "(II)V", (void*)android_os_Process_sendSignalQuiet},
|
||||
{"setProcessFrozen", "(IIZ)V", (void*)android_os_Process_setProcessFrozen},
|
||||
{"getFreeMemory", "()J", (void*)android_os_Process_getFreeMemory},
|
||||
{"getTotalMemory", "()J", (void*)android_os_Process_getTotalMemory},
|
||||
{"readProcLines", "(Ljava/lang/String;[Ljava/lang/String;[J)V",
|
||||
|
||||
@@ -50,6 +50,7 @@ class ActivityManagerDebugConfig {
|
||||
static final boolean DEBUG_BROADCAST_LIGHT = DEBUG_BROADCAST || false;
|
||||
static final boolean DEBUG_BROADCAST_DEFERRAL = DEBUG_BROADCAST || false;
|
||||
static final boolean DEBUG_COMPACTION = DEBUG_ALL || false;
|
||||
static final boolean DEBUG_FREEZER = DEBUG_ALL || false;
|
||||
static final boolean DEBUG_LRU = DEBUG_ALL || false;
|
||||
static final boolean DEBUG_MU = DEBUG_ALL || false;
|
||||
static final boolean DEBUG_NETWORK = DEBUG_ALL || false;
|
||||
|
||||
@@ -19,6 +19,7 @@ package com.android.server.am;
|
||||
import static android.os.Process.THREAD_PRIORITY_FOREGROUND;
|
||||
|
||||
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_COMPACTION;
|
||||
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_FREEZER;
|
||||
import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
|
||||
|
||||
import android.app.ActivityManager;
|
||||
@@ -42,6 +43,7 @@ import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.server.ServiceThread;
|
||||
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.FileReader;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
@@ -55,6 +57,7 @@ public final class CachedAppOptimizer {
|
||||
|
||||
// Flags stored in the DeviceConfig API.
|
||||
@VisibleForTesting static final String KEY_USE_COMPACTION = "use_compaction";
|
||||
@VisibleForTesting static final String KEY_USE_FREEZER = "use_freezer";
|
||||
@VisibleForTesting static final String KEY_COMPACT_ACTION_1 = "compact_action_1";
|
||||
@VisibleForTesting static final String KEY_COMPACT_ACTION_2 = "compact_action_2";
|
||||
@VisibleForTesting static final String KEY_COMPACT_THROTTLE_1 = "compact_throttle_1";
|
||||
@@ -65,6 +68,8 @@ public final class CachedAppOptimizer {
|
||||
@VisibleForTesting static final String KEY_COMPACT_THROTTLE_6 = "compact_throttle_6";
|
||||
@VisibleForTesting static final String KEY_COMPACT_STATSD_SAMPLE_RATE =
|
||||
"compact_statsd_sample_rate";
|
||||
@VisibleForTesting static final String KEY_FREEZER_STATSD_SAMPLE_RATE =
|
||||
"freeze_statsd_sample_rate";
|
||||
@VisibleForTesting static final String KEY_COMPACT_FULL_RSS_THROTTLE_KB =
|
||||
"compact_full_rss_throttle_kb";
|
||||
@VisibleForTesting static final String KEY_COMPACT_FULL_DELTA_RSS_THROTTLE_KB =
|
||||
@@ -85,6 +90,7 @@ public final class CachedAppOptimizer {
|
||||
|
||||
// Defaults for phenotype flags.
|
||||
@VisibleForTesting static final Boolean DEFAULT_USE_COMPACTION = false;
|
||||
@VisibleForTesting static final Boolean DEFAULT_USE_FREEZER = false;
|
||||
@VisibleForTesting static final int DEFAULT_COMPACT_ACTION_1 = COMPACT_ACTION_FILE_FLAG;
|
||||
@VisibleForTesting static final int DEFAULT_COMPACT_ACTION_2 = COMPACT_ACTION_FULL_FLAG;
|
||||
@VisibleForTesting static final long DEFAULT_COMPACT_THROTTLE_1 = 5_000;
|
||||
@@ -114,6 +120,13 @@ public final class CachedAppOptimizer {
|
||||
static final int COMPACT_PROCESS_BFGS = 4;
|
||||
static final int COMPACT_PROCESS_MSG = 1;
|
||||
static final int COMPACT_SYSTEM_MSG = 2;
|
||||
static final int SET_FROZEN_PROCESS_MSG = 3;
|
||||
|
||||
//TODO:change this static definition into a configurable flag.
|
||||
static final int FREEZE_TIMEOUT_MS = 500;
|
||||
|
||||
static final int DO_FREEZE = 1;
|
||||
static final int DO_UNFREEZE = 2;
|
||||
|
||||
/**
|
||||
* This thread must be moved to the system background cpuset.
|
||||
@@ -144,7 +157,9 @@ public final class CachedAppOptimizer {
|
||||
|| KEY_COMPACT_THROTTLE_4.equals(name)) {
|
||||
updateCompactionThrottles();
|
||||
} else if (KEY_COMPACT_STATSD_SAMPLE_RATE.equals(name)) {
|
||||
updateStatsdSampleRate();
|
||||
updateCompactStatsdSampleRate();
|
||||
} else if (KEY_FREEZER_STATSD_SAMPLE_RATE.equals(name)) {
|
||||
updateFreezerStatsdSampleRate();
|
||||
} else if (KEY_COMPACT_FULL_RSS_THROTTLE_KB.equals(name)) {
|
||||
updateFullRssThrottle();
|
||||
} else if (KEY_COMPACT_FULL_DELTA_RSS_THROTTLE_KB.equals(name)) {
|
||||
@@ -183,9 +198,11 @@ public final class CachedAppOptimizer {
|
||||
@VisibleForTesting volatile long mCompactThrottlePersistent = DEFAULT_COMPACT_THROTTLE_6;
|
||||
@GuardedBy("mPhenotypeFlagLock")
|
||||
private volatile boolean mUseCompaction = DEFAULT_USE_COMPACTION;
|
||||
private volatile boolean mUseFreezer = DEFAULT_USE_FREEZER;
|
||||
private final Random mRandom = new Random();
|
||||
@GuardedBy("mPhenotypeFlagLock")
|
||||
@VisibleForTesting volatile float mStatsdSampleRate = DEFAULT_STATSD_SAMPLE_RATE;
|
||||
@VisibleForTesting volatile float mCompactStatsdSampleRate = DEFAULT_STATSD_SAMPLE_RATE;
|
||||
@VisibleForTesting volatile float mFreezerStatsdSampleRate = DEFAULT_STATSD_SAMPLE_RATE;
|
||||
@GuardedBy("mPhenotypeFlagLock")
|
||||
@VisibleForTesting volatile long mFullAnonRssThrottleKb =
|
||||
DEFAULT_COMPACT_FULL_RSS_THROTTLE_KB;
|
||||
@@ -197,6 +214,7 @@ public final class CachedAppOptimizer {
|
||||
|
||||
// Handler on which compaction runs.
|
||||
private Handler mCompactionHandler;
|
||||
private Handler mFreezeHandler;
|
||||
|
||||
// Maps process ID to last compaction statistics for processes that we've fully compacted. Used
|
||||
// when evaluating throttles that we only consider for "full" compaction, so we don't store
|
||||
@@ -238,10 +256,12 @@ public final class CachedAppOptimizer {
|
||||
updateUseCompaction();
|
||||
updateCompactionActions();
|
||||
updateCompactionThrottles();
|
||||
updateStatsdSampleRate();
|
||||
updateCompactStatsdSampleRate();
|
||||
updateFreezerStatsdSampleRate();
|
||||
updateFullRssThrottle();
|
||||
updateFullDeltaRssThrottle();
|
||||
updateProcStateThrottle();
|
||||
updateUseFreezer();
|
||||
}
|
||||
Process.setThreadGroupAndCpuset(mCachedAppOptimizerThread.getThreadId(),
|
||||
Process.THREAD_GROUP_SYSTEM);
|
||||
@@ -256,6 +276,15 @@ public final class CachedAppOptimizer {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether freezer is enabled.
|
||||
*/
|
||||
public boolean useFreezer() {
|
||||
synchronized (mPhenotypeFlagLock) {
|
||||
return mUseFreezer;
|
||||
}
|
||||
}
|
||||
|
||||
@GuardedBy("mAm")
|
||||
void dump(PrintWriter pw) {
|
||||
pw.println("CachedAppOptimizer settings");
|
||||
@@ -269,7 +298,7 @@ public final class CachedAppOptimizer {
|
||||
pw.println(" " + KEY_COMPACT_THROTTLE_4 + "=" + mCompactThrottleFullFull);
|
||||
pw.println(" " + KEY_COMPACT_THROTTLE_5 + "=" + mCompactThrottleBFGS);
|
||||
pw.println(" " + KEY_COMPACT_THROTTLE_6 + "=" + mCompactThrottlePersistent);
|
||||
pw.println(" " + KEY_COMPACT_STATSD_SAMPLE_RATE + "=" + mStatsdSampleRate);
|
||||
pw.println(" " + KEY_COMPACT_STATSD_SAMPLE_RATE + "=" + mCompactStatsdSampleRate);
|
||||
pw.println(" " + KEY_COMPACT_FULL_RSS_THROTTLE_KB + "="
|
||||
+ mFullAnonRssThrottleKb);
|
||||
pw.println(" " + KEY_COMPACT_FULL_DELTA_RSS_THROTTLE_KB + "="
|
||||
@@ -283,6 +312,8 @@ public final class CachedAppOptimizer {
|
||||
|
||||
pw.println(" Tracking last compaction stats for " + mLastCompactionStats.size()
|
||||
+ " processes.");
|
||||
pw.println(" " + KEY_USE_FREEZER + "=" + mUseFreezer);
|
||||
pw.println(" " + KEY_FREEZER_STATSD_SAMPLE_RATE + "=" + mFreezerStatsdSampleRate);
|
||||
if (DEBUG_COMPACTION) {
|
||||
for (Map.Entry<Integer, LastCompactionStats> entry
|
||||
: mLastCompactionStats.entrySet()) {
|
||||
@@ -356,18 +387,76 @@ public final class CachedAppOptimizer {
|
||||
|
||||
/**
|
||||
* Reads the flag value from DeviceConfig to determine whether app compaction
|
||||
* should be enabled, and starts the compaction thread if needed.
|
||||
* should be enabled, and starts the freeze/compaction thread if needed.
|
||||
*/
|
||||
@GuardedBy("mPhenotypeFlagLock")
|
||||
private void updateUseCompaction() {
|
||||
mUseCompaction = DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
|
||||
KEY_USE_COMPACTION, DEFAULT_USE_COMPACTION);
|
||||
if (mUseCompaction && !mCachedAppOptimizerThread.isAlive()) {
|
||||
mCachedAppOptimizerThread.start();
|
||||
|
||||
if (mUseCompaction) {
|
||||
if (!mCachedAppOptimizerThread.isAlive()) {
|
||||
mCachedAppOptimizerThread.start();
|
||||
}
|
||||
|
||||
mCompactionHandler = new MemCompactionHandler();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether the freezer is correctly supported by this system
|
||||
*/
|
||||
public boolean isFreezerSupported() {
|
||||
boolean supported = false;
|
||||
FileReader fr = null;
|
||||
|
||||
try {
|
||||
fr = new FileReader("/dev/freezer/frozen/freezer.killable");
|
||||
int i = fr.read();
|
||||
|
||||
if ((char) i == '1') {
|
||||
supported = true;
|
||||
} else {
|
||||
Slog.w(TAG_AM, "Freezer killability is turned off, disabling freezer");
|
||||
}
|
||||
} catch (java.io.FileNotFoundException e) {
|
||||
Slog.d(TAG_AM, "Freezer.killable not present, disabling freezer");
|
||||
} catch (Exception e) {
|
||||
Slog.d(TAG_AM, "Unable to read freezer.killable, disabling freezer: " + e.toString());
|
||||
}
|
||||
|
||||
if (fr != null) {
|
||||
try {
|
||||
fr.close();
|
||||
} catch (java.io.IOException e) {
|
||||
Slog.e(TAG_AM, "Exception closing freezer.killable: " + e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
return supported;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the flag value from DeviceConfig to determine whether app freezer
|
||||
* should be enabled, and starts the freeze/compaction thread if needed.
|
||||
*/
|
||||
@GuardedBy("mPhenotypeFlagLock")
|
||||
private void updateUseFreezer() {
|
||||
if (DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
|
||||
KEY_USE_FREEZER, DEFAULT_USE_FREEZER)) {
|
||||
mUseFreezer = isFreezerSupported();
|
||||
}
|
||||
|
||||
if (mUseFreezer) {
|
||||
Slog.d(TAG_AM, "Freezer enabled");
|
||||
if (!mCachedAppOptimizerThread.isAlive()) {
|
||||
mCachedAppOptimizerThread.start();
|
||||
}
|
||||
|
||||
mFreezeHandler = new FreezeHandler();
|
||||
}
|
||||
}
|
||||
|
||||
@GuardedBy("mPhenotypeFlagLock")
|
||||
private void updateCompactionActions() {
|
||||
int compactAction1 = DeviceConfig.getInt(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
|
||||
@@ -433,10 +522,17 @@ public final class CachedAppOptimizer {
|
||||
}
|
||||
|
||||
@GuardedBy("mPhenotypeFlagLock")
|
||||
private void updateStatsdSampleRate() {
|
||||
mStatsdSampleRate = DeviceConfig.getFloat(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
|
||||
private void updateCompactStatsdSampleRate() {
|
||||
mCompactStatsdSampleRate = DeviceConfig.getFloat(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
|
||||
KEY_COMPACT_STATSD_SAMPLE_RATE, DEFAULT_STATSD_SAMPLE_RATE);
|
||||
mStatsdSampleRate = Math.min(1.0f, Math.max(0.0f, mStatsdSampleRate));
|
||||
mCompactStatsdSampleRate = Math.min(1.0f, Math.max(0.0f, mCompactStatsdSampleRate));
|
||||
}
|
||||
|
||||
@GuardedBy("mPhenotypeFlagLock")
|
||||
private void updateFreezerStatsdSampleRate() {
|
||||
mFreezerStatsdSampleRate = DeviceConfig.getFloat(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
|
||||
KEY_FREEZER_STATSD_SAMPLE_RATE, DEFAULT_STATSD_SAMPLE_RATE);
|
||||
mFreezerStatsdSampleRate = Math.min(1.0f, Math.max(0.0f, mFreezerStatsdSampleRate));
|
||||
}
|
||||
|
||||
@GuardedBy("mPhenotypeFlagLock")
|
||||
@@ -507,6 +603,24 @@ public final class CachedAppOptimizer {
|
||||
}
|
||||
}
|
||||
|
||||
@GuardedBy("mAm")
|
||||
void freezeAppAsync(ProcessRecord app) {
|
||||
mFreezeHandler.removeMessages(SET_FROZEN_PROCESS_MSG, app);
|
||||
|
||||
mFreezeHandler.sendMessageDelayed(
|
||||
mFreezeHandler.obtainMessage(
|
||||
SET_FROZEN_PROCESS_MSG, DO_FREEZE, 0, app),
|
||||
FREEZE_TIMEOUT_MS);
|
||||
}
|
||||
|
||||
@GuardedBy("mAm")
|
||||
void unfreezeAppAsync(ProcessRecord app) {
|
||||
mFreezeHandler.removeMessages(SET_FROZEN_PROCESS_MSG, app);
|
||||
|
||||
mFreezeHandler.sendMessage(
|
||||
mFreezeHandler.obtainMessage(SET_FROZEN_PROCESS_MSG, DO_UNFREEZE, 0, app));
|
||||
}
|
||||
|
||||
private static final class LastCompactionStats {
|
||||
private final long[] mRssAfterCompaction;
|
||||
|
||||
@@ -734,7 +848,7 @@ public final class CachedAppOptimizer {
|
||||
// Note that as above not taking mPhenoTypeFlagLock here to avoid locking
|
||||
// on every single compaction for a flag that will seldom change and the
|
||||
// impact of reading the wrong value here is low.
|
||||
if (mRandom.nextFloat() < mStatsdSampleRate) {
|
||||
if (mRandom.nextFloat() < mCompactStatsdSampleRate) {
|
||||
StatsLog.write(StatsLog.APP_COMPACTED, pid, name, pendingAction,
|
||||
rssBefore[0], rssBefore[1], rssBefore[2], rssBefore[3],
|
||||
rssAfter[0], rssAfter[1], rssAfter[2], rssAfter[3], time,
|
||||
@@ -768,4 +882,119 @@ public final class CachedAppOptimizer {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private final class FreezeHandler extends Handler {
|
||||
private FreezeHandler() {
|
||||
super(mCachedAppOptimizerThread.getLooper());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
if (msg.what != SET_FROZEN_PROCESS_MSG) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (msg.arg1 == DO_FREEZE) {
|
||||
freezeProcess((ProcessRecord) msg.obj);
|
||||
} else if (msg.arg1 == DO_UNFREEZE) {
|
||||
unfreezeProcess((ProcessRecord) msg.obj);
|
||||
}
|
||||
}
|
||||
|
||||
private void freezeProcess(ProcessRecord proc) {
|
||||
final int pid;
|
||||
final String name;
|
||||
final long unfrozenDuration;
|
||||
final boolean frozen;
|
||||
|
||||
synchronized (mAm) {
|
||||
pid = proc.pid;
|
||||
name = proc.processName;
|
||||
|
||||
if (proc.curAdj <= ProcessList.CACHED_APP_MIN_ADJ) {
|
||||
if (DEBUG_FREEZER) {
|
||||
Slog.d(TAG_AM, "Skipping freeze for process " + pid
|
||||
+ " " + name + " (not cached)");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (pid == 0 || proc.frozen) {
|
||||
// Already frozen or not a real process, either one being
|
||||
// launched or one being killed
|
||||
return;
|
||||
}
|
||||
|
||||
long unfreezeTime = proc.freezeUnfreezeTime;
|
||||
|
||||
try {
|
||||
Process.setProcessFrozen(pid, proc.uid, true);
|
||||
|
||||
proc.freezeUnfreezeTime = SystemClock.uptimeMillis();
|
||||
proc.frozen = true;
|
||||
} catch (Exception e) {
|
||||
Slog.w(TAG_AM, "Unable to freeze " + pid + " " + name);
|
||||
}
|
||||
|
||||
unfrozenDuration = proc.freezeUnfreezeTime - unfreezeTime;
|
||||
frozen = proc.frozen;
|
||||
}
|
||||
|
||||
if (frozen) {
|
||||
if (DEBUG_FREEZER) {
|
||||
Slog.d(TAG_AM, "froze " + pid + " " + name);
|
||||
}
|
||||
|
||||
EventLog.writeEvent(EventLogTags.AM_FREEZE, pid, name);
|
||||
}
|
||||
}
|
||||
|
||||
private void unfreezeProcess(ProcessRecord proc) {
|
||||
final int pid;
|
||||
final String name;
|
||||
final long frozenDuration;
|
||||
final boolean frozen;
|
||||
|
||||
synchronized (mAm) {
|
||||
pid = proc.pid;
|
||||
name = proc.processName;
|
||||
|
||||
if (!proc.frozen) {
|
||||
if (DEBUG_FREEZER) {
|
||||
Slog.d(TAG_AM,
|
||||
"Skipping unfreeze for process " + pid + " "
|
||||
+ name + " (not frozen)");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (pid == 0) {
|
||||
// Not a real process, either being launched or killed
|
||||
return;
|
||||
}
|
||||
|
||||
long freezeTime = proc.freezeUnfreezeTime;
|
||||
|
||||
try {
|
||||
Process.setProcessFrozen(proc.pid, proc.uid, false);
|
||||
|
||||
proc.freezeUnfreezeTime = SystemClock.uptimeMillis();
|
||||
proc.frozen = false;
|
||||
} catch (Exception e) {
|
||||
Slog.w(TAG_AM, "Unable to unfreeze " + pid + " " + name);
|
||||
}
|
||||
|
||||
frozenDuration = proc.freezeUnfreezeTime - freezeTime;
|
||||
frozen = proc.frozen;
|
||||
}
|
||||
|
||||
if (!frozen) {
|
||||
if (DEBUG_FREEZER) {
|
||||
Slog.d(TAG_AM, "unfroze " + pid + " " + name);
|
||||
}
|
||||
|
||||
EventLog.writeEvent(EventLogTags.AM_UNFREEZE, pid, name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -88,3 +88,8 @@ option java_package com.android.server.am
|
||||
# The task is being compacted
|
||||
30063 am_compact (Pid|1|5),(Process Name|3),(Action|3),(BeforeRssTotal|2|2),(BeforeRssFile|2|2),(BeforeRssAnon|2|2),(BeforeRssSwap|2|2),(DeltaRssTotal|2|2),(DeltaRssFile|2|2),(DeltaRssAnon|2|2),(DeltaRssSwap|2|2),(Time|2|3),(LastAction|1|2),(LastActionTimestamp|2|3),(setAdj|1|2),(procState|1|2),(BeforeZRAMFree|2|2),(DeltaZRAMFree|2|2)
|
||||
|
||||
# The task is being frozen
|
||||
30068 am_freeze (Pid|1|5),(Process Name|3)
|
||||
|
||||
# The task is being unfrozen
|
||||
30069 am_unfreeze (Pid|1|5),(Process Name|3)
|
||||
|
||||
@@ -2173,6 +2173,9 @@ public final class OomAdjuster {
|
||||
app.repForegroundActivities = app.hasForegroundActivities();
|
||||
changes |= ActivityManagerService.ProcessChangeItem.CHANGE_ACTIVITIES;
|
||||
}
|
||||
|
||||
updateAppFreezeStateLocked(app);
|
||||
|
||||
if (app.getReportedProcState() != app.getCurProcState()) {
|
||||
app.setReportedProcState(app.getCurProcState());
|
||||
if (app.thread != null) {
|
||||
@@ -2489,4 +2492,18 @@ public final class OomAdjuster {
|
||||
void dumpCachedAppOptimizerSettings(PrintWriter pw) {
|
||||
mCachedAppOptimizer.dump(pw);
|
||||
}
|
||||
|
||||
@GuardedBy("mService")
|
||||
void updateAppFreezeStateLocked(ProcessRecord app) {
|
||||
if (!mCachedAppOptimizer.useFreezer()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Use current adjustment when freezing, set adjustment when unfreezing.
|
||||
if (app.curAdj >= ProcessList.CACHED_APP_MIN_ADJ && !app.frozen) {
|
||||
mCachedAppOptimizer.freezeAppAsync(app);
|
||||
} else if (app.setAdj < ProcessList.CACHED_APP_MIN_ADJ && app.frozen) {
|
||||
mCachedAppOptimizer.unfreezeAppAsync(app);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -163,6 +163,8 @@ class ProcessRecord implements WindowProcessListener {
|
||||
long lastCompactTime; // The last time that this process was compacted
|
||||
int reqCompactAction; // The most recent compaction action requested for this app.
|
||||
int lastCompactAction; // The most recent compaction action performed for this app.
|
||||
boolean frozen; // True when the process is frozen.
|
||||
long freezeUnfreezeTime; // Last time the app was (un)frozen, 0 for never
|
||||
private int mCurSchedGroup; // Currently desired scheduling class
|
||||
int setSchedGroup; // Last set to background scheduling class
|
||||
int trimMemoryLevel; // Last selected memory trimming level
|
||||
@@ -623,7 +625,7 @@ class ProcessRecord implements WindowProcessListener {
|
||||
curAdj = setAdj = verifiedAdj = ProcessList.INVALID_ADJ;
|
||||
mPersistent = false;
|
||||
removed = false;
|
||||
lastStateTime = lastPssTime = nextPssTime = SystemClock.uptimeMillis();
|
||||
freezeUnfreezeTime = lastStateTime = lastPssTime = nextPssTime = SystemClock.uptimeMillis();
|
||||
mWindowProcessController = new WindowProcessController(
|
||||
mService.mActivityTaskManager, info, processName, uid, userId, this, this);
|
||||
pkgList.put(_info.packageName, new ProcessStats.ProcessStateHolder(_info.longVersionCode));
|
||||
|
||||
@@ -120,7 +120,7 @@ public final class CachedAppOptimizerTest {
|
||||
CachedAppOptimizer.DEFAULT_COMPACT_THROTTLE_3);
|
||||
assertThat(mCachedAppOptimizerUnderTest.mCompactThrottleFullFull).isEqualTo(
|
||||
CachedAppOptimizer.DEFAULT_COMPACT_THROTTLE_4);
|
||||
assertThat(mCachedAppOptimizerUnderTest.mStatsdSampleRate).isEqualTo(
|
||||
assertThat(mCachedAppOptimizerUnderTest.mCompactStatsdSampleRate).isEqualTo(
|
||||
CachedAppOptimizer.DEFAULT_STATSD_SAMPLE_RATE);
|
||||
assertThat(mCachedAppOptimizerUnderTest.mFullAnonRssThrottleKb).isEqualTo(
|
||||
CachedAppOptimizer.DEFAULT_COMPACT_FULL_RSS_THROTTLE_KB);
|
||||
@@ -209,7 +209,7 @@ public final class CachedAppOptimizerTest {
|
||||
CachedAppOptimizer.DEFAULT_COMPACT_THROTTLE_5 + 1);
|
||||
assertThat(mCachedAppOptimizerUnderTest.mCompactThrottlePersistent).isEqualTo(
|
||||
CachedAppOptimizer.DEFAULT_COMPACT_THROTTLE_6 + 1);
|
||||
assertThat(mCachedAppOptimizerUnderTest.mStatsdSampleRate).isEqualTo(
|
||||
assertThat(mCachedAppOptimizerUnderTest.mCompactStatsdSampleRate).isEqualTo(
|
||||
CachedAppOptimizer.DEFAULT_STATSD_SAMPLE_RATE + 0.1f);
|
||||
assertThat(mCachedAppOptimizerUnderTest.mCompactThrottleBFGS).isEqualTo(
|
||||
CachedAppOptimizer.DEFAULT_COMPACT_THROTTLE_5 + 1);
|
||||
@@ -472,7 +472,7 @@ public final class CachedAppOptimizerTest {
|
||||
public void statsdSampleRate_listensToDeviceConfigChanges() throws InterruptedException {
|
||||
mCachedAppOptimizerUnderTest.init();
|
||||
|
||||
// When we override mStatsdSampleRate with a reasonable value ...
|
||||
// When we override mCompactStatsdSampleRate with a reasonable value ...
|
||||
mCountDown = new CountDownLatch(1);
|
||||
DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
|
||||
CachedAppOptimizer.KEY_COMPACT_STATSD_SAMPLE_RATE,
|
||||
@@ -480,7 +480,7 @@ public final class CachedAppOptimizerTest {
|
||||
assertThat(mCountDown.await(5, TimeUnit.SECONDS)).isTrue();
|
||||
|
||||
// Then that override is reflected in the compactor.
|
||||
assertThat(mCachedAppOptimizerUnderTest.mStatsdSampleRate).isEqualTo(
|
||||
assertThat(mCachedAppOptimizerUnderTest.mCompactStatsdSampleRate).isEqualTo(
|
||||
CachedAppOptimizer.DEFAULT_STATSD_SAMPLE_RATE + 0.1f);
|
||||
}
|
||||
|
||||
@@ -489,14 +489,14 @@ public final class CachedAppOptimizerTest {
|
||||
throws InterruptedException {
|
||||
mCachedAppOptimizerUnderTest.init();
|
||||
|
||||
// When we override mStatsdSampleRate with an unreasonable value ...
|
||||
// When we override mCompactStatsdSampleRate with an unreasonable value ...
|
||||
mCountDown = new CountDownLatch(1);
|
||||
DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
|
||||
CachedAppOptimizer.KEY_COMPACT_STATSD_SAMPLE_RATE, "foo", false);
|
||||
assertThat(mCountDown.await(5, TimeUnit.SECONDS)).isTrue();
|
||||
|
||||
// Then that override is reflected in the compactor.
|
||||
assertThat(mCachedAppOptimizerUnderTest.mStatsdSampleRate).isEqualTo(
|
||||
assertThat(mCachedAppOptimizerUnderTest.mCompactStatsdSampleRate).isEqualTo(
|
||||
CachedAppOptimizer.DEFAULT_STATSD_SAMPLE_RATE);
|
||||
}
|
||||
|
||||
@@ -505,7 +505,7 @@ public final class CachedAppOptimizerTest {
|
||||
throws InterruptedException {
|
||||
mCachedAppOptimizerUnderTest.init();
|
||||
|
||||
// When we override mStatsdSampleRate with an value outside of [0..1]...
|
||||
// When we override mCompactStatsdSampleRate with an value outside of [0..1]...
|
||||
mCountDown = new CountDownLatch(1);
|
||||
DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
|
||||
CachedAppOptimizer.KEY_COMPACT_STATSD_SAMPLE_RATE,
|
||||
@@ -513,7 +513,7 @@ public final class CachedAppOptimizerTest {
|
||||
assertThat(mCountDown.await(5, TimeUnit.SECONDS)).isTrue();
|
||||
|
||||
// Then the values is capped in the range.
|
||||
assertThat(mCachedAppOptimizerUnderTest.mStatsdSampleRate).isEqualTo(0.0f);
|
||||
assertThat(mCachedAppOptimizerUnderTest.mCompactStatsdSampleRate).isEqualTo(0.0f);
|
||||
|
||||
mCountDown = new CountDownLatch(1);
|
||||
DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
|
||||
@@ -522,7 +522,7 @@ public final class CachedAppOptimizerTest {
|
||||
assertThat(mCountDown.await(5, TimeUnit.SECONDS)).isTrue();
|
||||
|
||||
// Then the values is capped in the range.
|
||||
assertThat(mCachedAppOptimizerUnderTest.mStatsdSampleRate).isEqualTo(1.0f);
|
||||
assertThat(mCachedAppOptimizerUnderTest.mCompactStatsdSampleRate).isEqualTo(1.0f);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
Reference in New Issue
Block a user