private static final String TAG_CONFIGURATION = TAG + POSTFIX_CONFIGURATION;
private static final String TAG_FOCUS = TAG + POSTFIX_FOCUS;
private static final String TAG_IMMERSIVE = TAG + POSTFIX_IMMERSIVE;
- private static final String TAG_LOCKSCREEN = TAG + POSTFIX_LOCKSCREEN;
private static final String TAG_LOCKTASK = TAG + POSTFIX_LOCKTASK;
private static final String TAG_LRU = TAG + POSTFIX_LRU;
private static final String TAG_MU = TAG + POSTFIX_MU;
private static final String TAG_UID_OBSERVERS = TAG + POSTFIX_UID_OBSERVERS;
private static final String TAG_URI_PERMISSION = TAG + POSTFIX_URI_PERMISSION;
private static final String TAG_VISIBILITY = TAG + POSTFIX_VISIBILITY;
- private static final String TAG_VISIBLE_BEHIND = TAG + POSTFIX_VISIBLE_BEHIND;
// Mock "pretend we're idle now" broadcast action to the job scheduler; declared
// here so that while the job scheduler can depend on AMS, the other way around
final ArrayList<UidRecord.ChangeItem> mPendingUidChanges = new ArrayList<>();
final ArrayList<UidRecord.ChangeItem> mAvailUidChanges = new ArrayList<>();
+ OomAdjObserver mCurOomAdjObserver;
+ int mCurOomAdjUid;
+
+ interface OomAdjObserver {
+ void onOomAdjMessage(String msg);
+ }
+
/**
* Runtime CPU use collection thread. This object's lock is used to
* perform synchronization with the thread (notifying it to run).
static final int DISPATCH_PENDING_INTENT_CANCEL_MSG = 67;
static final int PUSH_TEMP_WHITELIST_UI_MSG = 68;
static final int SERVICE_FOREGROUND_CRASH_MSG = 69;
+ static final int DISPATCH_OOM_ADJ_OBSERVER_MSG = 70;
static final int START_USER_SWITCH_FG_MSG = 712;
static final int FIRST_ACTIVITY_STACK_MSG = 100;
case DISPATCH_UIDS_CHANGED_UI_MSG: {
dispatchUidsChanged();
} break;
+ case DISPATCH_OOM_ADJ_OBSERVER_MSG: {
+ dispatchOomAdjObserver((String)msg.obj);
+ } break;
case PUSH_TEMP_WHITELIST_UI_MSG: {
pushTempWhitelist();
} break;
}
}
+ void dispatchOomAdjObserver(String msg) {
+ OomAdjObserver observer;
+ synchronized (this) {
+ observer = mCurOomAdjObserver;
+ }
+
+ if (observer != null) {
+ observer.onOomAdjMessage(msg);
+ }
+ }
+
+ void setOomAdjObserver(int uid, OomAdjObserver observer) {
+ synchronized (this) {
+ mCurOomAdjUid = uid;
+ mCurOomAdjObserver = observer;
+ }
+ }
+
+ void clearOomAdjObserver() {
+ synchronized (this) {
+ mCurOomAdjUid = -1;
+ mCurOomAdjObserver = null;
+ }
+ }
+
+ void reportOomAdjMessageLocked(String tag, String msg) {
+ Slog.d(tag, msg);
+ if (mCurOomAdjObserver != null) {
+ mUiHandler.obtainMessage(DISPATCH_OOM_ADJ_OBSERVER_MSG, msg).sendToTarget();
+ }
+ }
+
@Override
public final int startActivity(IApplicationThread caller, String callingPackage,
Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
if (app.curAdj != app.setAdj) {
ProcessList.setOomAdj(app.pid, app.uid, app.curAdj);
- if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG_OOM_ADJ,
- "Set " + app.pid + " " + app.processName + " adj " + app.curAdj + ": "
- + app.adjType);
+ if (DEBUG_SWITCH || DEBUG_OOM_ADJ || mCurOomAdjUid == app.info.uid) {
+ String msg = "Set " + app.pid + " " + app.processName + " adj "
+ + app.curAdj + ": " + app.adjType;
+ reportOomAdjMessageLocked(TAG_OOM_ADJ, msg);
+ }
app.setAdj = app.curAdj;
app.verifiedAdj = ProcessList.INVALID_ADJ;
}
if (app.setSchedGroup != app.curSchedGroup) {
int oldSchedGroup = app.setSchedGroup;
app.setSchedGroup = app.curSchedGroup;
- if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG_OOM_ADJ,
- "Setting sched group of " + app.processName
- + " to " + app.curSchedGroup);
+ if (DEBUG_SWITCH || DEBUG_OOM_ADJ || mCurOomAdjUid == app.uid) {
+ String msg = "Setting sched group of " + app.processName
+ + " to " + app.curSchedGroup;
+ reportOomAdjMessageLocked(TAG_OOM_ADJ, msg);
+ }
if (app.waitingToKill != null && app.curReceivers.isEmpty()
&& app.setSchedGroup == ProcessList.SCHED_GROUP_BACKGROUND) {
app.kill(app.waitingToKill, true);
"Not requesting PSS of " + app + ": next=" + (app.nextPssTime-now));
}
if (app.setProcState != app.curProcState) {
- if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG_OOM_ADJ,
- "Proc state change of " + app.processName
- + " to " + app.curProcState);
+ if (DEBUG_SWITCH || DEBUG_OOM_ADJ || mCurOomAdjUid == app.uid) {
+ String msg = "Proc state change of " + app.processName
+ + " to " + app.curProcState;
+ reportOomAdjMessageLocked(TAG_OOM_ADJ, msg);
+ }
boolean setImportant = app.setProcState < ActivityManager.PROCESS_STATE_SERVICE;
boolean curImportant = app.curProcState < ActivityManager.PROCESS_STATE_SERVICE;
if (setImportant && !curImportant) {
import android.util.ArrayMap;
import android.util.DebugUtils;
import android.util.DisplayMetrics;
-import android.view.IWindowManager;
import com.android.internal.util.HexDump;
import com.android.internal.util.Preconditions;
return 0;
}
- static final class MyUidObserver extends IUidObserver.Stub {
+ static final class MyUidObserver extends IUidObserver.Stub
+ implements ActivityManagerService.OomAdjObserver {
final IActivityManager mInterface;
+ final ActivityManagerService mInternal;
final PrintWriter mPw;
final InputStream mInput;
+ final int mUid;
static final int STATE_NORMAL = 0;
int mState;
- MyUidObserver(IActivityManager iam, PrintWriter pw, InputStream input) {
- mInterface = iam;
+ MyUidObserver(ActivityManagerService service, PrintWriter pw, InputStream input, int uid) {
+ mInterface = service;
+ mInternal = service;
mPw = pw;
mInput = input;
+ mUid = uid;
}
@Override
}
}
+ @Override
+ public void onOomAdjMessage(String msg) {
+ synchronized (this) {
+ mPw.print("# ");
+ mPw.println(msg);
+ mPw.flush();
+ }
+ }
+
void printMessageForState() {
switch (mState) {
case STATE_NORMAL:
| ActivityManager.UID_OBSERVER_GONE | ActivityManager.UID_OBSERVER_PROCSTATE
| ActivityManager.UID_OBSERVER_IDLE | ActivityManager.UID_OBSERVER_CACHED,
ActivityManager.PROCESS_STATE_UNKNOWN, null);
+ if (mUid >= 0) {
+ mInternal.setOomAdjObserver(mUid, this);
+ }
mState = STATE_NORMAL;
InputStreamReader converter = new InputStreamReader(mInput);
e.printStackTrace(mPw);
mPw.flush();
} finally {
+ if (mUid >= 0) {
+ mInternal.clearOomAdjObserver();
+ }
mInterface.unregisterUidObserver(this);
}
}
int runWatchUids(PrintWriter pw) throws RemoteException {
String opt;
+ int uid = -1;
while ((opt=getNextOption()) != null) {
- getErrPrintWriter().println("Error: Unknown option: " + opt);
- return -1;
+ if (opt.equals("--oom")) {
+ uid = Integer.parseInt(getNextArgRequired());
+ } else {
+ getErrPrintWriter().println("Error: Unknown option: " + opt);
+ return -1;
+
+ }
}
- MyUidObserver controller = new MyUidObserver(mInterface, pw, getRawInputStream());
+ MyUidObserver controller = new MyUidObserver(mInternal, pw, getRawInputStream(), uid);
controller.run();
return 0;
}
level = ComponentCallbacks2.TRIM_MEMORY_COMPLETE;
break;
default:
- getErrPrintWriter().println("Error: Unknown level option: " + levelArg);
- return -1;
+ try {
+ level = Integer.parseInt(levelArg);
+ } catch (NumberFormatException e) {
+ getErrPrintWriter().println("Error: Unknown level option: " + levelArg);
+ return -1;
+ }
}
if (!mInterface.setProcessMemoryTrimLevel(proc, userId, level)) {
getErrPrintWriter().println("Unknown error: failed to set trim level");
pw.println(" monitor [--gdb <port>]");
pw.println(" Start monitoring for crashes or ANRs.");
pw.println(" --gdb: start gdbserv on the given port at crash/ANR");
- pw.println(" watch-uids [--gdb <port>]");
+ pw.println(" watch-uids [--oom <uid>");
pw.println(" Start watching for and reporting uid state changes.");
+ pw.println(" --oom: specify a uid for which to report detailed change messages.");
pw.println(" hang [--allow-restart]");
pw.println(" Hang the system.");
pw.println(" --allow-restart: allow watchdog to perform normal system restart");
pw.println(" Returns the inactive state of an app.");
pw.println(" send-trim-memory [--user <USER_ID>] <PROCESS>");
pw.println(" [HIDDEN|RUNNING_MODERATE|BACKGROUND|RUNNING_LOW|MODERATE|RUNNING_CRITICAL|COMPLETE]");
- pw.println(" Send a memory trim event to a <PROCESS>.");
+ pw.println(" Send a memory trim event to a <PROCESS>. May also supply a raw trim int level.");
pw.println(" display [COMMAND] [...]: sub-commands for operating on displays.");
pw.println(" move-stack <STACK_ID> <DISPLAY_ID>");
pw.println(" Move <STACK_ID> from its current display to <DISPLAY_ID>.");