summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cmds/am/src/com/android/commands/am/Am.java19
-rw-r--r--core/java/android/app/ActivityManagerNative.java17
-rw-r--r--core/java/android/app/IActivityManager.java3
-rw-r--r--core/java/android/content/Context.java21
-rw-r--r--services/java/com/android/server/IdleMaintenanceService.java69
-rw-r--r--services/java/com/android/server/SystemServer.java3
-rw-r--r--services/java/com/android/server/am/ActivityManagerService.java351
-rw-r--r--services/java/com/android/server/am/ProcessRecord.java14
8 files changed, 325 insertions, 172 deletions
diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java
index d78572b..c18f542 100644
--- a/cmds/am/src/com/android/commands/am/Am.java
+++ b/cmds/am/src/com/android/commands/am/Am.java
@@ -100,6 +100,7 @@ public class Am extends BaseCommand {
" am monitor [--gdb <port>]\n" +
" am hang [--allow-restart]\n" +
" am restart\n" +
+ " am idle-maintenance\n" +
" am screen-compat [on|off] <PACKAGE>\n" +
" am to-uri [INTENT]\n" +
" am to-intent-uri [INTENT]\n" +
@@ -189,6 +190,8 @@ public class Am extends BaseCommand {
"\n" +
"am restart: restart the user-space system.\n" +
"\n" +
+ "am idle-maintenance: perform idle maintenance now.\n" +
+ "\n" +
"am screen-compat: control screen compatibility mode of <PACKAGE>.\n" +
"\n" +
"am to-uri: print the given Intent specification as a URI.\n" +
@@ -295,6 +298,8 @@ public class Am extends BaseCommand {
runHang();
} else if (op.equals("restart")) {
runRestart();
+ } else if (op.equals("idle-maintenance")) {
+ runIdleMaintenance();
} else if (op.equals("screen-compat")) {
runScreenCompat();
} else if (op.equals("to-uri")) {
@@ -1393,6 +1398,20 @@ public class Am extends BaseCommand {
mAm.restart();
}
+ private void runIdleMaintenance() throws Exception {
+ String opt;
+ while ((opt=nextOption()) != null) {
+ System.err.println("Error: Unknown option: " + opt);
+ return;
+ }
+
+ System.out.println("Performing idle maintenance...");
+ Intent intent = new Intent(
+ "com.android.server.IdleMaintenanceService.action.FORCE_IDLE_MAINTENANCE");
+ mAm.broadcastIntent(null, intent, null, null, 0, null, null, null,
+ android.app.AppOpsManager.OP_NONE, true, false, UserHandle.USER_ALL);
+ }
+
private void runScreenCompat() throws Exception {
String mode = nextArgRequired();
boolean enabled;
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index 370db31..a727b07 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -1995,6 +1995,13 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
reply.writeParcelableArray(uris, 0);
return true;
}
+
+ case PERFORM_IDLE_MAINTENANCE_TRANSACTION: {
+ data.enforceInterface(IActivityManager.descriptor);
+ performIdleMaintenance();
+ reply.writeNoException();
+ return true;
+ }
}
return super.onTransact(code, data, reply, flags);
@@ -4578,5 +4585,15 @@ class ActivityManagerProxy implements IActivityManager
return uris;
}
+ public void performIdleMaintenance() throws RemoteException {
+ Parcel data = Parcel.obtain();
+ Parcel reply = Parcel.obtain();
+ data.writeInterfaceToken(IActivityManager.descriptor);
+ mRemote.transact(PERFORM_IDLE_MAINTENANCE_TRANSACTION, data, reply, 0);
+ reply.readException();
+ data.recycle();
+ reply.recycle();
+ }
+
private IBinder mRemote;
}
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index b2ae298..25c02df 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -403,6 +403,8 @@ public interface IActivityManager extends IInterface {
String sourcePackage, String targetPackage, int modeFlags, int modeMask)
throws RemoteException;
+ public void performIdleMaintenance() throws RemoteException;
+
/*
* Private non-Binder interfaces
*/
@@ -685,4 +687,5 @@ public interface IActivityManager extends IInterface {
int REPORT_ACTIVITY_FULLY_DRAWN_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+176;
int RESTART_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+177;
int GET_GRANTED_URI_PERMISSIONS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+178;
+ int PERFORM_IDLE_MAINTENANCE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+179;
}
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 92a9c7c..860b12c 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -2132,13 +2132,7 @@ public abstract class Context {
public static final String UPDATE_LOCK_SERVICE = "updatelock";
/**
- * Use with {@link #getSystemService} to retrieve a {@link
- * android.net.NetworkManagementService} for handling management of
- * system network services
- *
- * @hide
- * @see #getSystemService
- * @see android.net.NetworkManagementService
+ * Constant for the internal network management service, not really a Context service.
*/
public static final String NETWORKMANAGEMENT_SERVICE = "network_management";
@@ -2327,7 +2321,7 @@ public abstract class Context {
* android.hardware.SerialManager} for access to serial ports.
*
* @see #getSystemService
- * @see android.harware.SerialManager
+ * @see android.hardware.SerialManager
*
* @hide
*/
@@ -2353,17 +2347,6 @@ public abstract class Context {
/**
* Use with {@link #getSystemService} to retrieve a
- * {@link android.os.SchedulingPolicyService} for managing scheduling policy.
- *
- * @see #getSystemService
- * @see android.os.SchedulingPolicyService
- *
- * @hide
- */
- public static final String SCHEDULING_POLICY_SERVICE = "scheduling_policy";
-
- /**
- * Use with {@link #getSystemService} to retrieve a
* {@link android.os.UserManager} for managing users on devices that support multiple users.
*
* @see #getSystemService
diff --git a/services/java/com/android/server/IdleMaintenanceService.java b/services/java/com/android/server/IdleMaintenanceService.java
index 584d4bc..b0a1aca 100644
--- a/services/java/com/android/server/IdleMaintenanceService.java
+++ b/services/java/com/android/server/IdleMaintenanceService.java
@@ -17,6 +17,7 @@
package com.android.server;
import android.app.Activity;
+import android.app.ActivityManagerNative;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
@@ -24,12 +25,13 @@ import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Handler;
-import android.os.Looper;
import android.os.PowerManager;
import android.os.PowerManager.WakeLock;
+import android.os.RemoteException;
import android.os.SystemClock;
import android.os.UserHandle;
import android.util.Log;
+import android.util.Slog;
/**
* This service observes the device state and when applicable sends
@@ -69,6 +71,9 @@ public class IdleMaintenanceService extends BroadcastReceiver {
private static final String ACTION_UPDATE_IDLE_MAINTENANCE_STATE =
"com.android.server.IdleMaintenanceService.action.UPDATE_IDLE_MAINTENANCE_STATE";
+ private static final String ACTION_FORCE_IDLE_MAINTENANCE =
+ "com.android.server.IdleMaintenanceService.action.FORCE_IDLE_MAINTENANCE";
+
private static final Intent sIdleMaintenanceStartIntent;
static {
sIdleMaintenanceStartIntent = new Intent(Intent.ACTION_IDLE_MAINTENANCE_START);
@@ -115,10 +120,10 @@ public class IdleMaintenanceService extends BroadcastReceiver {
mUpdateIdleMaintenanceStatePendingIntent = PendingIntent.getBroadcast(mContext, 0,
intent, PendingIntent.FLAG_UPDATE_CURRENT);
- register(mContext.getMainLooper());
+ register(mHandler);
}
- public void register(Looper looper) {
+ public void register(Handler handler) {
IntentFilter intentFilter = new IntentFilter();
// Alarm actions.
@@ -136,7 +141,12 @@ public class IdleMaintenanceService extends BroadcastReceiver {
intentFilter.addAction(Intent.ACTION_DREAMING_STOPPED);
mContext.registerReceiverAsUser(this, UserHandle.ALL,
- intentFilter, null, new Handler(looper));
+ intentFilter, null, mHandler);
+
+ intentFilter = new IntentFilter();
+ intentFilter.addAction(ACTION_FORCE_IDLE_MAINTENANCE);
+ mContext.registerReceiverAsUser(this, UserHandle.ALL,
+ intentFilter, android.Manifest.permission.SET_ACTIVITY_WATCHER, mHandler);
}
private void scheduleUpdateIdleMaintenanceState(long delayMillis) {
@@ -149,7 +159,7 @@ public class IdleMaintenanceService extends BroadcastReceiver {
mAlarmService.cancel(mUpdateIdleMaintenanceStatePendingIntent);
}
- private void updateIdleMaintenanceState() {
+ private void updateIdleMaintenanceState(boolean noisy) {
if (mIdleMaintenanceStarted) {
// Idle maintenance can be interrupted by user activity, or duration
// time out, or low battery.
@@ -170,9 +180,9 @@ public class IdleMaintenanceService extends BroadcastReceiver {
getNextIdleMaintenanceIntervalStartFromNow());
}
}
- } else if (deviceStatePermitsIdleMaintenanceStart()
- && lastUserActivityPermitsIdleMaintenanceStart()
- && lastRunPermitsIdleMaintenanceStart()) {
+ } else if (deviceStatePermitsIdleMaintenanceStart(noisy)
+ && lastUserActivityPermitsIdleMaintenanceStart(noisy)
+ && lastRunPermitsIdleMaintenanceStart(noisy)) {
// Now that we started idle maintenance, we should schedule another
// update for the moment when the idle maintenance times out.
scheduleUpdateIdleMaintenanceState(MAX_IDLE_MAINTENANCE_DURATION);
@@ -182,8 +192,8 @@ public class IdleMaintenanceService extends BroadcastReceiver {
isBatteryCharging() ? 1 : 0);
mLastIdleMaintenanceStartTimeMillis = SystemClock.elapsedRealtime();
sendIdleMaintenanceStartIntent();
- } else if (lastUserActivityPermitsIdleMaintenanceStart()) {
- if (lastRunPermitsIdleMaintenanceStart()) {
+ } else if (lastUserActivityPermitsIdleMaintenanceStart(noisy)) {
+ if (lastRunPermitsIdleMaintenanceStart(noisy)) {
// The user does not use the device and we did not run maintenance in more
// than the min interval between runs, so schedule an update - maybe the
// battery will be charged latter.
@@ -204,6 +214,10 @@ public class IdleMaintenanceService extends BroadcastReceiver {
private void sendIdleMaintenanceStartIntent() {
mWakeLock.acquire();
+ try {
+ ActivityManagerNative.getDefault().performIdleMaintenance();
+ } catch (RemoteException e) {
+ }
mContext.sendOrderedBroadcastAsUser(sIdleMaintenanceStartIntent, UserHandle.ALL,
null, this, mHandler, Activity.RESULT_OK, null, null);
}
@@ -214,25 +228,37 @@ public class IdleMaintenanceService extends BroadcastReceiver {
null, this, mHandler, Activity.RESULT_OK, null, null);
}
- private boolean deviceStatePermitsIdleMaintenanceStart() {
+ private boolean deviceStatePermitsIdleMaintenanceStart(boolean noisy) {
final int minBatteryLevel = isBatteryCharging()
? MIN_BATTERY_LEVEL_IDLE_MAINTENANCE_START_CHARGING
: MIN_BATTERY_LEVEL_IDLE_MAINTENANCE_START_NOT_CHARGING;
- return (mLastUserActivityElapsedTimeMillis != LAST_USER_ACTIVITY_TIME_INVALID
+ boolean allowed = (mLastUserActivityElapsedTimeMillis != LAST_USER_ACTIVITY_TIME_INVALID
&& mBatteryService.getBatteryLevel() > minBatteryLevel);
+ if (!allowed && noisy) {
+ Slog.i("IdleMaintenance", "Idle maintenance not allowed due to power");
+ }
+ return allowed;
}
- private boolean lastUserActivityPermitsIdleMaintenanceStart() {
+ private boolean lastUserActivityPermitsIdleMaintenanceStart(boolean noisy) {
// The last time the user poked the device is above the threshold.
- return (mLastUserActivityElapsedTimeMillis != LAST_USER_ACTIVITY_TIME_INVALID
+ boolean allowed = (mLastUserActivityElapsedTimeMillis != LAST_USER_ACTIVITY_TIME_INVALID
&& SystemClock.elapsedRealtime() - mLastUserActivityElapsedTimeMillis
> MIN_USER_INACTIVITY_IDLE_MAINTENANCE_START);
+ if (!allowed && noisy) {
+ Slog.i("IdleMaintenance", "Idle maintenance not allowed due to last user activity");
+ }
+ return allowed;
}
- private boolean lastRunPermitsIdleMaintenanceStart() {
+ private boolean lastRunPermitsIdleMaintenanceStart(boolean noisy) {
// Enough time passed since the last maintenance run.
- return SystemClock.elapsedRealtime() - mLastIdleMaintenanceStartTimeMillis
+ boolean allowed = SystemClock.elapsedRealtime() - mLastIdleMaintenanceStartTimeMillis
> MIN_IDLE_MAINTENANCE_INTERVAL_MILLIS;
+ if (!allowed && noisy) {
+ Slog.i("IdleMaintenance", "Idle maintenance not allowed due time since last");
+ }
+ return allowed;
}
private boolean lastUserActivityPermitsIdleMaintenanceRunning() {
@@ -266,7 +292,7 @@ public class IdleMaintenanceService extends BroadcastReceiver {
// next release. The only client for this for now is internal an holds
// a wake lock correctly.
if (mIdleMaintenanceStarted) {
- updateIdleMaintenanceState();
+ updateIdleMaintenanceState(false);
}
} else if (Intent.ACTION_SCREEN_ON.equals(action)
|| Intent.ACTION_DREAMING_STOPPED.equals(action)) {
@@ -276,7 +302,7 @@ public class IdleMaintenanceService extends BroadcastReceiver {
unscheduleUpdateIdleMaintenanceState();
// If the screen went on/stopped dreaming, we know the user is using the
// device which means that idle maintenance should be stopped if running.
- updateIdleMaintenanceState();
+ updateIdleMaintenanceState(false);
} else if (Intent.ACTION_SCREEN_OFF.equals(action)
|| Intent.ACTION_DREAMING_STARTED.equals(action)) {
mLastUserActivityElapsedTimeMillis = SystemClock.elapsedRealtime();
@@ -285,7 +311,12 @@ public class IdleMaintenanceService extends BroadcastReceiver {
// this timeout elapses since the device may go to sleep by then.
scheduleUpdateIdleMaintenanceState(MIN_USER_INACTIVITY_IDLE_MAINTENANCE_START);
} else if (ACTION_UPDATE_IDLE_MAINTENANCE_STATE.equals(action)) {
- updateIdleMaintenanceState();
+ updateIdleMaintenanceState(false);
+ } else if (ACTION_FORCE_IDLE_MAINTENANCE.equals(action)) {
+ long now = SystemClock.elapsedRealtime() - 1;
+ mLastUserActivityElapsedTimeMillis = now - MIN_USER_INACTIVITY_IDLE_MAINTENANCE_START;
+ mLastIdleMaintenanceStartTimeMillis = now - MIN_IDLE_MAINTENANCE_INTERVAL_MILLIS;
+ updateIdleMaintenanceState(true);
} else if (Intent.ACTION_IDLE_MAINTENANCE_START.equals(action)
|| Intent.ACTION_IDLE_MAINTENANCE_END.equals(action)) {
// We were holding a wake lock while broadcasting the idle maintenance
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index d38756f..ef50df7 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -217,8 +217,7 @@ class ServerThread {
ServiceManager.addService("telephony.registry", telephonyRegistry);
Slog.i(TAG, "Scheduling Policy");
- ServiceManager.addService(Context.SCHEDULING_POLICY_SERVICE,
- new SchedulingPolicyService());
+ ServiceManager.addService("scheduling_policy", new SchedulingPolicyService());
AttributeCache.init(context);
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index e208f10..2bac96e 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -172,7 +172,6 @@ import android.view.WindowManager;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
-import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
@@ -850,10 +849,39 @@ public final class ActivityManagerService extends ActivityManagerNative
int mNewNumServiceProcs = 0;
/**
- * System monitoring: number of processes that died since the last
- * N procs were started.
+ * Allow the current computed overall memory level of the system to go down?
+ * This is set to false when we are killing processes for reasons other than
+ * memory management, so that the now smaller process list will not be taken as
+ * an indication that memory is tighter.
*/
- int[] mProcDeaths = new int[20];
+ boolean mAllowLowerMemLevel = false;
+
+ /**
+ * The last computed memory level, for holding when we are in a state that
+ * processes are going away for other reasons.
+ */
+ int mLastMemoryLevel = ProcessStats.ADJ_MEM_FACTOR_NORMAL;
+
+ /**
+ * The last total number of process we have, to determine if changes actually look
+ * like a shrinking number of process due to lower RAM.
+ */
+ int mLastNumProcesses;
+
+ /**
+ * The uptime of the last time we performed idle maintenance.
+ */
+ long mLastIdleTime = SystemClock.uptimeMillis();
+
+ /**
+ * Total time spent with RAM that has been added in the past since the last idle time.
+ */
+ long mLowRamTimeSinceLastIdle = 0;
+
+ /**
+ * If RAM is currently low, when that horrible situatin started.
+ */
+ long mLowRamStartTime = 0;
/**
* This is set if we had to do a delayed dexopt of an app before launching
@@ -978,17 +1006,18 @@ public final class ActivityManagerService extends ActivityManagerNative
static final int CANCEL_HEAVY_NOTIFICATION_MSG = 25;
static final int SHOW_STRICT_MODE_VIOLATION_MSG = 26;
static final int CHECK_EXCESSIVE_WAKE_LOCKS_MSG = 27;
- static final int CLEAR_DNS_CACHE = 28;
- static final int UPDATE_HTTP_PROXY = 29;
+ static final int CLEAR_DNS_CACHE_MSG = 28;
+ static final int UPDATE_HTTP_PROXY_MSG = 29;
static final int SHOW_COMPAT_MODE_DIALOG_MSG = 30;
static final int DISPATCH_PROCESSES_CHANGED = 31;
static final int DISPATCH_PROCESS_DIED = 32;
- static final int REPORT_MEM_USAGE = 33;
+ static final int REPORT_MEM_USAGE_MSG = 33;
static final int REPORT_USER_SWITCH_MSG = 34;
static final int CONTINUE_USER_SWITCH_MSG = 35;
static final int USER_SWITCH_TIMEOUT_MSG = 36;
static final int IMMERSIVE_MODE_LOCK_MSG = 37;
- static final int PERSIST_URI_GRANTS = 38;
+ static final int PERSIST_URI_GRANTS_MSG = 38;
+ static final int REQUEST_ALL_PSS_MSG = 39;
static final int FIRST_ACTIVITY_STACK_MSG = 100;
static final int FIRST_BROADCAST_QUEUE_MSG = 200;
@@ -1169,7 +1198,7 @@ public final class ActivityManagerService extends ActivityManagerNative
}
}
} break;
- case CLEAR_DNS_CACHE: {
+ case CLEAR_DNS_CACHE_MSG: {
synchronized (ActivityManagerService.this) {
for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
ProcessRecord r = mLruProcesses.get(i);
@@ -1183,7 +1212,7 @@ public final class ActivityManagerService extends ActivityManagerNative
}
}
} break;
- case UPDATE_HTTP_PROXY: {
+ case UPDATE_HTTP_PROXY_MSG: {
ProxyProperties proxy = (ProxyProperties)msg.obj;
String host = "";
String port = "";
@@ -1369,7 +1398,7 @@ public final class ActivityManagerService extends ActivityManagerNative
dispatchProcessDied(pid, uid);
break;
}
- case REPORT_MEM_USAGE: {
+ case REPORT_MEM_USAGE_MSG: {
final ArrayList<ProcessMemInfo> memInfos = (ArrayList<ProcessMemInfo>)msg.obj;
Thread thread = new Thread() {
@Override public void run() {
@@ -1583,10 +1612,14 @@ public final class ActivityManagerService extends ActivityManagerNative
}
break;
}
- case PERSIST_URI_GRANTS: {
+ case PERSIST_URI_GRANTS_MSG: {
writeGrantedUriPermissions();
break;
}
+ case REQUEST_ALL_PSS_MSG: {
+ requestPssAllProcsLocked(SystemClock.uptimeMillis(), true, false);
+ break;
+ }
}
}
};
@@ -1630,6 +1663,10 @@ public final class ActivityManagerService extends ActivityManagerNative
num++;
proc.lastPssTime = SystemClock.uptimeMillis();
proc.baseProcessTracker.addPss(pss, tmp[0], true);
+ if (proc.initialIdlePss == 0) {
+ proc.initialIdlePss = pss;
+ }
+ proc.lastPss = pss;
}
}
}
@@ -2250,8 +2287,7 @@ public final class ActivityManagerService extends ActivityManagerNative
}
}
- final void updateLruProcessLocked(ProcessRecord app,
- boolean oomAdj) {
+ final void updateLruProcessLocked(ProcessRecord app, boolean oomAdj) {
mLruSeq++;
updateLruProcessInternalLocked(app, 0);
@@ -2417,9 +2453,6 @@ public final class ActivityManagerService extends ActivityManagerNative
updateCpuStats();
- System.arraycopy(mProcDeaths, 0, mProcDeaths, 1, mProcDeaths.length-1);
- mProcDeaths[0] = 0;
-
try {
int uid = app.uid;
@@ -3428,7 +3461,7 @@ public final class ActivityManagerService extends ActivityManagerNative
}
}
if (doReport) {
- Message msg = mHandler.obtainMessage(REPORT_MEM_USAGE, memInfos);
+ Message msg = mHandler.obtainMessage(REPORT_MEM_USAGE_MSG, memInfos);
mHandler.sendMessage(msg);
}
scheduleAppGcsLocked();
@@ -3438,8 +3471,6 @@ public final class ActivityManagerService extends ActivityManagerNative
final void appDiedLocked(ProcessRecord app, int pid,
IApplicationThread thread) {
- mProcDeaths[0]++;
-
BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
synchronized (stats) {
stats.noteProcessDiedLocked(app.info.uid, pid);
@@ -3448,17 +3479,27 @@ public final class ActivityManagerService extends ActivityManagerNative
// Clean up already done if the process has been re-started.
if (app.pid == pid && app.thread != null &&
app.thread.asBinder() == thread.asBinder()) {
- if (!app.killedBackground) {
+ boolean doLowMem = app.instrumentationClass == null;
+ boolean doOomAdj = doLowMem;
+ if (!app.killedByAm) {
Slog.i(TAG, "Process " + app.processName + " (pid " + pid
+ ") has died.");
+ mAllowLowerMemLevel = true;
+ } else {
+ // Note that we always want to do oom adj to update our state with the
+ // new number of procs.
+ mAllowLowerMemLevel = false;
+ doLowMem = false;
}
EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.userId, app.pid, app.processName);
if (DEBUG_CLEANUP) Slog.v(
TAG, "Dying app: " + app + ", pid: " + pid
+ ", thread: " + thread.asBinder());
- boolean doLowMem = app.instrumentationClass == null;
handleAppDiedLocked(app, false, true);
+ if (doOomAdj) {
+ updateOomAdjLocked();
+ }
if (doLowMem) {
doLowMemReportIfNeededLocked(app);
}
@@ -3791,10 +3832,7 @@ public final class ActivityManagerService extends ActivityManagerNative
synchronized (this) {
if (!showBackground && !app.isInterestingToUserLocked() && app.pid != MY_PID) {
- Slog.w(TAG, "Killing " + app + ": background ANR");
- EventLog.writeEvent(EventLogTags.AM_KILL, app.userId, app.pid,
- app.processName, app.setAdj, "background ANR");
- Process.killProcessQuiet(app.pid);
+ killUnneededProcessLocked(app, "background ANR");
return;
}
@@ -3979,6 +4017,7 @@ public final class ActivityManagerService extends ActivityManagerNative
for (int i=0; i<N; i++) {
removeProcessLocked(procs.get(i), false, true, "kill all background");
}
+ mAllowLowerMemLevel = true;
updateOomAdjLocked();
doLowMemReportIfNeededLocked(null);
}
@@ -4478,10 +4517,9 @@ public final class ActivityManagerService extends ActivityManagerNative
mPidsSelfLocked.remove(pid);
mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
}
- Slog.i(TAG, "Killing proc " + app.toShortString() + ": " + reason);
+ killUnneededProcessLocked(app, reason);
handleAppDiedLocked(app, true, allowRestart);
mLruProcesses.remove(app);
- Process.killProcessQuiet(pid);
if (app.persistent && !app.isolated) {
if (!callerWillRestart) {
@@ -4523,9 +4561,7 @@ public final class ActivityManagerService extends ActivityManagerNative
checkAppInLaunchingProvidersLocked(app, true);
// Take care of any services that are waiting for the process.
mServices.processStartTimedOutLocked(app);
- EventLog.writeEvent(EventLogTags.AM_KILL, app.userId, pid,
- app.processName, app.setAdj, "start timeout");
- Process.killProcessQuiet(pid);
+ killUnneededProcessLocked(app, "start timeout");
if (mBackupTarget != null && mBackupTarget.app.pid == pid) {
Slog.w(TAG, "Unattached app died before backup, skipping");
try {
@@ -5769,8 +5805,8 @@ public final class ActivityManagerService extends ActivityManagerNative
pi.packageName, targetPkg, targetUid, uri);
final boolean persistChanged = perm.grantModes(modeFlags, persist, owner);
if (persistChanged) {
- mHandler.removeMessages(PERSIST_URI_GRANTS);
- mHandler.obtainMessage(PERSIST_URI_GRANTS).sendToTarget();
+ mHandler.removeMessages(PERSIST_URI_GRANTS_MSG);
+ mHandler.obtainMessage(PERSIST_URI_GRANTS_MSG).sendToTarget();
}
}
@@ -5994,8 +6030,8 @@ public final class ActivityManagerService extends ActivityManagerNative
}
if (persistChanged) {
- mHandler.removeMessages(PERSIST_URI_GRANTS);
- mHandler.obtainMessage(PERSIST_URI_GRANTS).sendToTarget();
+ mHandler.removeMessages(PERSIST_URI_GRANTS_MSG);
+ mHandler.obtainMessage(PERSIST_URI_GRANTS_MSG).sendToTarget();
}
}
@@ -6079,8 +6115,8 @@ public final class ActivityManagerService extends ActivityManagerNative
}
if (persistChanged) {
- mHandler.removeMessages(PERSIST_URI_GRANTS);
- mHandler.obtainMessage(PERSIST_URI_GRANTS).sendToTarget();
+ mHandler.removeMessages(PERSIST_URI_GRANTS_MSG);
+ mHandler.obtainMessage(PERSIST_URI_GRANTS_MSG).sendToTarget();
}
}
@@ -6508,6 +6544,16 @@ public final class ActivityManagerService extends ActivityManagerNative
}
}
+ private void killUnneededProcessLocked(ProcessRecord pr, String reason) {
+ if (!pr.killedByAm) {
+ Slog.i(TAG, "Killing " + pr.toShortString() + " (adj " + pr.setAdj + "): " + reason);
+ EventLog.writeEvent(EventLogTags.AM_KILL, pr.userId, pr.pid,
+ pr.processName, pr.setAdj, reason);
+ pr.killedByAm = true;
+ Process.killProcessQuiet(pr.pid);
+ }
+ }
+
private void cleanUpRemovedTaskLocked(TaskRecord tr, int flags) {
mRecentTasks.remove(tr);
mStackSupervisor.removeTask(tr);
@@ -6546,11 +6592,7 @@ public final class ActivityManagerService extends ActivityManagerNative
for (int i=0; i<procs.size(); i++) {
ProcessRecord pr = procs.get(i);
if (pr.setSchedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE) {
- Slog.i(TAG, "Killing " + pr.toShortString() + ": remove task");
- EventLog.writeEvent(EventLogTags.AM_KILL, pr.userId, pr.pid,
- pr.processName, pr.setAdj, "remove task");
- pr.killedBackground = true;
- Process.killProcessQuiet(pr.pid);
+ killUnneededProcessLocked(pr, "remove task");
} else {
pr.waitingToKill = "remove task";
}
@@ -8401,13 +8443,9 @@ public final class ActivityManagerService extends ActivityManagerNative
continue;
}
int adj = proc.setAdj;
- if (adj >= worstType && !proc.killedBackground) {
- Slog.w(TAG, "Killing " + proc + " (adj " + adj + "): " + reason);
- EventLog.writeEvent(EventLogTags.AM_KILL, proc.userId, proc.pid,
- proc.processName, adj, reason);
+ if (adj >= worstType && !proc.killedByAm) {
+ killUnneededProcessLocked(proc, reason);
killed = true;
- proc.killedBackground = true;
- Process.killProcessQuiet(pids[i]);
}
}
}
@@ -8449,13 +8487,9 @@ public final class ActivityManagerService extends ActivityManagerNative
if (proc == null) continue;
final int adj = proc.setAdj;
- if (adj > belowAdj && !proc.killedBackground) {
- Slog.w(TAG, "Killing " + proc + " (adj " + adj + "): " + reason);
- EventLog.writeEvent(EventLogTags.AM_KILL, proc.userId,
- proc.pid, proc.processName, adj, reason);
+ if (adj > belowAdj && !proc.killedByAm) {
+ killUnneededProcessLocked(proc, reason);
killed = true;
- proc.killedBackground = true;
- Process.killProcessQuiet(pid);
}
}
}
@@ -8533,6 +8567,61 @@ public final class ActivityManagerService extends ActivityManagerNative
br.onReceive(mContext, intent);
}
+ private long getLowRamTimeSinceIdle(long now) {
+ return mLowRamTimeSinceLastIdle + (mLowRamStartTime > 0 ? (now-mLowRamStartTime) : 0);
+ }
+
+ @Override
+ public void performIdleMaintenance() {
+ if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
+ != PackageManager.PERMISSION_GRANTED) {
+ throw new SecurityException("Requires permission "
+ + android.Manifest.permission.SET_ACTIVITY_WATCHER);
+ }
+
+ synchronized (this) {
+ final long now = SystemClock.uptimeMillis();
+ final long timeSinceLastIdle = now - mLastIdleTime;
+ final long lowRamSinceLastIdle = getLowRamTimeSinceIdle(now);
+ mLastIdleTime = now;
+ mLowRamTimeSinceLastIdle = 0;
+ if (mLowRamStartTime != 0) {
+ mLowRamStartTime = now;
+ }
+
+ StringBuilder sb = new StringBuilder(128);
+ sb.append("Idle maintenance over ");
+ TimeUtils.formatDuration(timeSinceLastIdle, sb);
+ sb.append(" low RAM for ");
+ TimeUtils.formatDuration(lowRamSinceLastIdle, sb);
+ Slog.i(TAG, sb.toString());
+
+ // If at least 1/3 of our time since the last idle period has been spent
+ // with RAM low, then we want to kill processes.
+ boolean doKilling = lowRamSinceLastIdle > (timeSinceLastIdle/3);
+
+ for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
+ ProcessRecord proc = mLruProcesses.get(i);
+ if (proc.notCachedSinceIdle) {
+ if (proc.setProcState > ActivityManager.PROCESS_STATE_TOP
+ && proc.setProcState <= ActivityManager.PROCESS_STATE_SERVICE) {
+ if (doKilling && proc.initialIdlePss != 0
+ && proc.lastPss > ((proc.initialIdlePss*3)/2)) {
+ killUnneededProcessLocked(proc, "idle maint (pss " + proc.lastPss
+ + " from " + proc.initialIdlePss + ")");
+ }
+ }
+ } else if (proc.setProcState < ActivityManager.PROCESS_STATE_HOME) {
+ proc.notCachedSinceIdle = true;
+ proc.initialIdlePss = 0;
+ }
+ }
+
+ mHandler.removeMessages(REQUEST_ALL_PSS_MSG);
+ mHandler.sendEmptyMessageDelayed(REQUEST_ALL_PSS_MSG, 2*60*1000);
+ }
+ }
+
public final void startRunning(String pkg, String cls, String action,
String data) {
synchronized(this) {
@@ -8967,10 +9056,7 @@ public final class ActivityManagerService extends ActivityManagerNative
}
if (app.pid > 0 && app.pid != MY_PID) {
handleAppCrashLocked(app);
- Slog.i(ActivityManagerService.TAG, "Killing " + app + ": user's request");
- EventLog.writeEvent(EventLogTags.AM_KILL, app.userId, app.pid,
- app.processName, app.setAdj, "user's request after error");
- Process.killProcessQuiet(app.pid);
+ killUnneededProcessLocked(app, "user request after error");
}
}
}
@@ -10444,6 +10530,15 @@ public final class ActivityManagerService extends ActivityManagerNative
+ " mNumCachedHiddenProcs=" + mNumCachedHiddenProcs
+ " mNumServiceProcs=" + mNumServiceProcs
+ " mNewNumServiceProcs=" + mNewNumServiceProcs);
+ pw.println(" mAllowLowerMemLevel=" + mAllowLowerMemLevel
+ + " mLastMemoryLevel" + mLastMemoryLevel
+ + " mLastNumProcesses" + mLastNumProcesses);
+ long now = SystemClock.uptimeMillis();
+ pw.print(" mLastIdleTime=");
+ TimeUtils.formatDuration(now, mLastIdleTime, pw);
+ pw.print(" mLowRamSinceLastIdle=");
+ TimeUtils.formatDuration(getLowRamTimeSinceIdle(now), pw);
+ pw.println();
}
}
@@ -11704,13 +11799,9 @@ public final class ActivityManagerService extends ActivityManagerNative
if (!capp.persistent && capp.thread != null
&& capp.pid != 0
&& capp.pid != MY_PID) {
- Slog.i(TAG, "Kill " + capp.processName
- + " (pid " + capp.pid + "): provider " + cpr.info.name
- + " in dying process " + (proc != null ? proc.processName : "??"));
- EventLog.writeEvent(EventLogTags.AM_KILL, capp.userId, capp.pid,
- capp.processName, capp.setAdj, "dying provider "
- + cpr.name.toShortString());
- Process.killProcessQuiet(capp.pid);
+ killUnneededProcessLocked(capp, "depends on provider "
+ + cpr.name.flattenToShortString()
+ + " in dying proc " + (proc != null ? proc.processName : "??"));
}
} else if (capp.thread != null && conn.provider.provider != null) {
try {
@@ -12791,12 +12882,12 @@ public final class ActivityManagerService extends ActivityManagerNative
}
if (intent.ACTION_CLEAR_DNS_CACHE.equals(intent.getAction())) {
- mHandler.sendEmptyMessage(CLEAR_DNS_CACHE);
+ mHandler.sendEmptyMessage(CLEAR_DNS_CACHE_MSG);
}
if (Proxy.PROXY_CHANGE_ACTION.equals(intent.getAction())) {
ProxyProperties proxy = intent.getParcelableExtra("proxy");
- mHandler.sendMessage(mHandler.obtainMessage(UPDATE_HTTP_PROXY, proxy));
+ mHandler.sendMessage(mHandler.obtainMessage(UPDATE_HTTP_PROXY_MSG, proxy));
}
// Add to the sticky list if requested.
@@ -14527,26 +14618,18 @@ public final class ActivityManagerService extends ActivityManagerNative
stats.reportExcessiveWakeLocked(app.info.uid, app.processName,
realtimeSince, wtimeUsed);
}
- Slog.w(TAG, "Excessive wake lock in " + app.processName
- + " (pid " + app.pid + "): held " + wtimeUsed
+ killUnneededProcessLocked(app, "excessive wake held " + wtimeUsed
+ " during " + realtimeSince);
- EventLog.writeEvent(EventLogTags.AM_KILL, app.userId, app.pid,
- app.processName, app.setAdj, "excessive wake lock");
app.baseProcessTracker.reportExcessiveWake(app.pkgList);
- Process.killProcessQuiet(app.pid);
} else if (doCpuKills && uptimeSince > 0
&& ((cputimeUsed*100)/uptimeSince) >= 50) {
synchronized (stats) {
stats.reportExcessiveCpuLocked(app.info.uid, app.processName,
uptimeSince, cputimeUsed);
}
- Slog.w(TAG, "Excessive CPU in " + app.processName
- + " (pid " + app.pid + "): used " + cputimeUsed
+ killUnneededProcessLocked(app, "excessive cpu " + cputimeUsed
+ " during " + uptimeSince);
- EventLog.writeEvent(EventLogTags.AM_KILL, app.userId, app.pid,
- app.processName, app.setAdj, "excessive cpu");
app.baseProcessTracker.reportExcessiveCpu(app.pkgList);
- Process.killProcessQuiet(app.pid);
} else {
app.lastWakeTime = wtime;
app.lastCpuTime = app.curCpuTime;
@@ -14593,11 +14676,7 @@ public final class ActivityManagerService extends ActivityManagerNative
+ " to " + app.curSchedGroup);
if (app.waitingToKill != null &&
app.setSchedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE) {
- Slog.i(TAG, "Killing " + app.toShortString() + ": " + app.waitingToKill);
- EventLog.writeEvent(EventLogTags.AM_KILL, app.userId, app.pid,
- app.processName, app.setAdj, app.waitingToKill);
- app.killedBackground = true;
- Process.killProcessQuiet(app.pid);
+ killUnneededProcessLocked(app, app.waitingToKill);
success = false;
} else {
if (true) {
@@ -14657,6 +14736,9 @@ public final class ActivityManagerService extends ActivityManagerNative
"Proc state change of " + app.processName
+ " to " + app.curProcState);
app.setProcState = app.curProcState;
+ if (app.setProcState >= ActivityManager.PROCESS_STATE_HOME) {
+ app.notCachedSinceIdle = false;
+ }
if (!doingAll) {
setProcessTrackerState(app, mProcessStats.getMemFactorLocked(), now);
} else {
@@ -14783,7 +14865,7 @@ public final class ActivityManagerService extends ActivityManagerNative
int nextEmptyAdj = curEmptyAdj+2;
for (int i=N-1; i>=0; i--) {
ProcessRecord app = mLruProcesses.get(i);
- if (!app.killedBackground && app.thread != null) {
+ if (!app.killedByAm && app.thread != null) {
app.procStateChanged = false;
final boolean wasKeeping = app.keeping;
computeOomAdjLocked(app, ProcessList.UNKNOWN_ADJ, TOP_APP, true, now);
@@ -14858,34 +14940,19 @@ public final class ActivityManagerService extends ActivityManagerNative
mNumCachedHiddenProcs++;
numCached++;
if (numCached > cachedProcessLimit) {
- Slog.i(TAG, "No longer want " + app.processName
- + " (pid " + app.pid + "): cached #" + numCached);
- EventLog.writeEvent(EventLogTags.AM_KILL, app.userId, app.pid,
- app.processName, app.setAdj, "too many background");
- app.killedBackground = true;
- Process.killProcessQuiet(app.pid);
+ killUnneededProcessLocked(app, "cached #" + numCached);
}
break;
case ActivityManager.PROCESS_STATE_CACHED_EMPTY:
if (numEmpty > ProcessList.TRIM_EMPTY_APPS
&& app.lastActivityTime < oldTime) {
- Slog.i(TAG, "No longer want " + app.processName
- + " (pid " + app.pid + "): empty for "
- + ((oldTime+ProcessList.MAX_EMPTY_TIME-app.lastActivityTime)
- / 1000) + "s");
- EventLog.writeEvent(EventLogTags.AM_KILL, app.userId, app.pid,
- app.processName, app.setAdj, "old background process");
- app.killedBackground = true;
- Process.killProcessQuiet(app.pid);
+ killUnneededProcessLocked(app, "empty for "
+ + ((oldTime + ProcessList.MAX_EMPTY_TIME - app.lastActivityTime)
+ / 1000) + "s");
} else {
numEmpty++;
if (numEmpty > emptyProcessLimit) {
- Slog.i(TAG, "No longer want " + app.processName
- + " (pid " + app.pid + "): empty #" + numEmpty);
- EventLog.writeEvent(EventLogTags.AM_KILL, app.userId, app.pid,
- app.processName, app.setAdj, "too many background");
- app.killedBackground = true;
- Process.killProcessQuiet(app.pid);
+ killUnneededProcessLocked(app, "empty #" + numEmpty);
}
}
break;
@@ -14901,16 +14968,11 @@ public final class ActivityManagerService extends ActivityManagerNative
// definition not re-use the same process again, and it is
// good to avoid having whatever code was running in them
// left sitting around after no longer needed.
- Slog.i(TAG, "Isolated process " + app.processName
- + " (pid " + app.pid + ") no longer needed");
- EventLog.writeEvent(EventLogTags.AM_KILL, app.userId, app.pid,
- app.processName, app.setAdj, "isolated not needed");
- app.killedBackground = true;
- Process.killProcessQuiet(app.pid);
+ killUnneededProcessLocked(app, "isolated not needed");
}
if (app.curProcState >= ActivityManager.PROCESS_STATE_HOME
- && !app.killedBackground) {
+ && !app.killedByAm) {
numTrimming++;
}
}
@@ -14924,31 +14986,60 @@ public final class ActivityManagerService extends ActivityManagerNative
// are managing to keep around is less than half the maximum we desire;
// if we are keeping a good number around, we'll let them use whatever
// memory they want.
- boolean allChanged;
+ final int numCachedAndEmpty = numCached + numEmpty;
+ int memFactor;
if (numCached <= ProcessList.TRIM_CACHED_APPS
&& numEmpty <= ProcessList.TRIM_EMPTY_APPS) {
- final int numCachedAndEmpty = numCached + numEmpty;
- int factor = numTrimming/3;
- int minFactor = 2;
- if (mHomeProcess != null) minFactor++;
- if (mPreviousProcess != null) minFactor++;
- if (factor < minFactor) factor = minFactor;
- int step = 0;
- int fgTrimLevel;
- int memFactor;
if (numCachedAndEmpty <= ProcessList.TRIM_CRITICAL_THRESHOLD) {
- fgTrimLevel = ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL;
memFactor = ProcessStats.ADJ_MEM_FACTOR_CRITICAL;
} else if (numCachedAndEmpty <= ProcessList.TRIM_LOW_THRESHOLD) {
- fgTrimLevel = ComponentCallbacks2.TRIM_MEMORY_RUNNING_LOW;
memFactor = ProcessStats.ADJ_MEM_FACTOR_LOW;
} else {
- fgTrimLevel = ComponentCallbacks2.TRIM_MEMORY_RUNNING_MODERATE;
memFactor = ProcessStats.ADJ_MEM_FACTOR_MODERATE;
}
+ } else {
+ memFactor = ProcessStats.ADJ_MEM_FACTOR_NORMAL;
+ }
+ // We always allow the memory level to go up (better). We only allow it to go
+ // down if we are in a state where that is allowed, *and* the total number of processes
+ // has gone down since last time.
+ if (DEBUG_OOM_ADJ) Slog.d(TAG, "oom: memFactor=" + memFactor + " last=" + mLastMemoryLevel
+ + " allowLow=" + mAllowLowerMemLevel + " numProcs=" + mLruProcesses.size()
+ + " last=" + mLastNumProcesses);
+ if (memFactor > mLastMemoryLevel) {
+ if (!mAllowLowerMemLevel || mLruProcesses.size() >= mLastNumProcesses) {
+ memFactor = mLastMemoryLevel;
+ if (DEBUG_OOM_ADJ) Slog.d(TAG, "Keeping last mem factor!");
+ }
+ }
+ mLastMemoryLevel = memFactor;
+ mLastNumProcesses = mLruProcesses.size();
+ boolean allChanged = mProcessStats.setMemFactorLocked(
+ ProcessStats.ADJ_MEM_FACTOR_NORMAL, !mSleeping, now);
+ final int trackerMemFactor = mProcessStats.getMemFactorLocked();
+ if (memFactor != ProcessStats.ADJ_MEM_FACTOR_NORMAL) {
+ if (mLowRamStartTime == 0) {
+ mLowRamStartTime = now;
+ }
+ int step = 0;
+ int fgTrimLevel;
+ switch (memFactor) {
+ case ProcessStats.ADJ_MEM_FACTOR_CRITICAL:
+ fgTrimLevel = ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL;
+ break;
+ case ProcessStats.ADJ_MEM_FACTOR_LOW:
+ fgTrimLevel = ComponentCallbacks2.TRIM_MEMORY_RUNNING_LOW;
+ break;
+ default:
+ fgTrimLevel = ComponentCallbacks2.TRIM_MEMORY_RUNNING_MODERATE;
+ break;
+ }
+ int factor = numTrimming/3;
+ int minFactor = 2;
+ if (mHomeProcess != null) minFactor++;
+ if (mPreviousProcess != null) minFactor++;
+ if (factor < minFactor) factor = minFactor;
int curLevel = ComponentCallbacks2.TRIM_MEMORY_COMPLETE;
- allChanged = mProcessStats.setMemFactorLocked(memFactor, !mSleeping, now);
- final int trackerMemFactor = mProcessStats.getMemFactorLocked();
for (int i=N-1; i>=0; i--) {
ProcessRecord app = mLruProcesses.get(i);
if (allChanged || app.procStateChanged) {
@@ -14956,7 +15047,7 @@ public final class ActivityManagerService extends ActivityManagerNative
app.procStateChanged = false;
}
if (app.curProcState >= ActivityManager.PROCESS_STATE_HOME
- && !app.killedBackground) {
+ && !app.killedByAm) {
if (app.trimMemoryLevel < curLevel && app.thread != null) {
try {
if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG,
@@ -15036,9 +15127,10 @@ public final class ActivityManagerService extends ActivityManagerNative
}
}
} else {
- allChanged = mProcessStats.setMemFactorLocked(
- ProcessStats.ADJ_MEM_FACTOR_NORMAL, !mSleeping, now);
- final int trackerMemFactor = mProcessStats.getMemFactorLocked();
+ if (mLowRamStartTime != 0) {
+ mLowRamTimeSinceLastIdle += now - mLowRamStartTime;
+ mLowRamStartTime = 0;
+ }
for (int i=N-1; i>=0; i--) {
ProcessRecord app = mLruProcesses.get(i);
if (allChanged || app.procStateChanged) {
@@ -15107,6 +15199,7 @@ public final class ActivityManagerService extends ActivityManagerNative
if (app.pid > 0 && app.pid != MY_PID) {
EventLog.writeEvent(EventLogTags.AM_KILL, app.userId, app.pid,
app.processName, app.setAdj, "empty");
+ app.killedByAm = true;
Process.killProcessQuiet(app.pid);
} else {
try {
diff --git a/services/java/com/android/server/am/ProcessRecord.java b/services/java/com/android/server/am/ProcessRecord.java
index 35e06b6..4fdacb3 100644
--- a/services/java/com/android/server/am/ProcessRecord.java
+++ b/services/java/com/android/server/am/ProcessRecord.java
@@ -66,6 +66,8 @@ final class ProcessRecord {
long lastPssTime; // Last time we retrieved PSS data
long nextPssTime; // Next time we want to request PSS data
long lastStateTime; // Last time setProcState changed
+ long initialIdlePss; // Initial memory pss of process for idle maintenance.
+ long lastPss; // Last computed memory pss.
int maxAdj; // Maximum OOM adjustment for this process
int curRawAdj; // Current OOM unlimited adjustment for this process
int setRawAdj; // Last set OOM unlimited adjustment for this process
@@ -82,6 +84,7 @@ final class ProcessRecord {
boolean serviceb; // Process currently is on the service B list
boolean keeping; // Actively running code so don't kill due to that?
boolean setIsForeground; // Running foreground UI when last set?
+ boolean notCachedSinceIdle; // Has this process not been in a cached state since last idle?
boolean hasActivities; // Are there any activities running in this process?
boolean hasClientActivities; // Are there any client services with activities?
boolean hasStartedServices; // Are there any started services running in this process?
@@ -92,7 +95,7 @@ final class ProcessRecord {
boolean pendingUiClean; // Want to clean up resources from showing UI?
boolean hasAboveClient; // Bound using BIND_ABOVE_CLIENT, so want to be lower
boolean bad; // True if disabled in the bad process list
- boolean killedBackground; // True when proc has been killed due to too many bg
+ boolean killedByAm; // True when proc has been killed by activity manager, not for RAM
boolean procStateChanged; // Keep track of whether we changed 'setAdj'.
String waitingToKill; // Process is waiting to be killed when in the bg; reason
IBinder forcingToForeground;// Token that is forcing this process to be foreground
@@ -216,6 +219,11 @@ final class ProcessRecord {
pw.print(" keeping="); pw.print(keeping);
pw.print(" cached="); pw.print(cached);
pw.print(" empty="); pw.println(empty);
+ if (notCachedSinceIdle) {
+ pw.print(prefix); pw.print("notCachedSinceIdle="); pw.print(notCachedSinceIdle);
+ pw.print(" initialIdlePss="); pw.print(initialIdlePss);
+ pw.print(" lastPss="); pw.println(lastPss);
+ }
pw.print(prefix); pw.print("oom: max="); pw.print(maxAdj);
pw.print(" curRaw="); pw.print(curRawAdj);
pw.print(" setRaw="); pw.print(setRawAdj);
@@ -280,8 +288,8 @@ final class ProcessRecord {
pw.print(" lastLowMemory=");
TimeUtils.formatDuration(lastLowMemory, now, pw);
pw.print(" reportLowMemory="); pw.println(reportLowMemory);
- if (killedBackground || waitingToKill != null) {
- pw.print(prefix); pw.print("killedBackground="); pw.print(killedBackground);
+ if (killedByAm || waitingToKill != null) {
+ pw.print(prefix); pw.print("killedByAm="); pw.print(killedByAm);
pw.print(" waitingToKill="); pw.println(waitingToKill);
}
if (debugging || crashing || crashDialog != null || notResponding