Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c8230519 authored by Dianne Hackborn's avatar Dianne Hackborn
Browse files

Switch proc stats to use new process state constants.

These new constants are a better mapping to the kind of
information that procstats is wanting to collect about
processes.  In doing this, the process states are tweaked
to have a bit more information that we care about for
procstats.

This changes the format of the data printed by procstats,
so the checkin version is bumped to 2.  The structure is
the same, however the codes for process states have all
changed.  The new codes are, in order of precedence:

p -- persistent system process.
t -- top activity; actually any visible activity.
f -- important foreground process (ime, wallpaper, etc).
b -- important background process
u -- performing backup operation.
w -- heavy-weight process (currently not used).
s -- background process running a service.
r -- process running a receiver.
h -- process hosting home/launcher app when not on top.
l -- process hosting the last app the user was in.
a -- cached process hosting a previous activity.
c -- cached process hosting a client activity.
e -- cached process that is empty.

In addition, we are now collecting uss along with pss
data for each process, so the pss checkin entries now
have three new values at the end of the min/avg/max uss
values of that process.

With this switch to using process state constants more
fundamentally, I realized that they could actually be
used by the core oom adj code to make it a lot cleaner.
So that change has been made, that code has changed quite
radically, and lost a lot of its secondary states and flags
that it used to use in its computation, now relying on
primarily the oom_adj and proc state values for the process.

This also cleaned up a few problems -- for example for
purposes of determing the memory level of the device, if a
long-running service dropped into the cached oom_adj level,
it would start being counted as a cached process and thus
make us think that the memory state is better than it is.
Now we do this based on the proc state, which always stays
as a service regardless of what is happening like this, giving
as a more consistent view of the memory state of the device.

Making proc state a more fundamentally part of the oom adj
computation means that the values can also be more carefully
tuned in semantic meaning so the value assigned to a process
doesn't tend to change unless the semantics of the process
has really significantly changed.

For example, a process will be assigned the service state
regardless of whether that services is executing operations
in the foreground, running normally, or has been dropped to
the lru list for pruning.  The top state is used for everything
related to activities visible to the user: when actually on
top, visible but not on top, currently pausing, etc.

There is a new Context.BIND_SHOWING_UI added for when system
services bind to apps, to explicitly indicate that the app
is showing UI for the system.  This gives us a better metric
to determine when it is showing UI, and thus when it needs
to do a memory trim when it is no longer in that state.  Without
this, services could get in bad states of continually trimming.

Finally, more HashSet containers have been changed to ArraySet,
reducing the temporary iterators created for iterating over
them.

Change-Id: I1724113f42abe7862e8aecb6faae5a7620245e89
parent c3bdf875
Loading
Loading
Loading
Loading
+28 −11
Original line number Diff line number Diff line
@@ -234,32 +234,49 @@ public class ActivityManager {
    /** @hide Process is a persistent system process and is doing UI. */
    public static final int PROCESS_STATE_PERSISTENT_UI = 1;

    /** @hide Process is hosting the current top activity. */
    /** @hide Process is hosting the current top activities.  Note that this covers
     * all activities that are visible to the user. */
    public static final int PROCESS_STATE_TOP = 2;

    /** @hide Process is important to the user, and something they are aware of. */
    public static final int PROCESS_STATE_IMPORTANT_PERCEPTIBLE = 3;
    public static final int PROCESS_STATE_IMPORTANT_FOREGROUND = 3;

    /** @hide Process is important to the user, but not something they are aware of. */
    public static final int PROCESS_STATE_IMPORTANT_BACKGROUND = 4;

    /** @hide Process is in the background running a receiver. */
    public static final int PROCESS_STATE_RECEIVER = 5;

    /** @hide Process is in the background running a backup/restore operation. */
    public static final int PROCESS_STATE_BACKUP = 6;
    public static final int PROCESS_STATE_BACKUP = 5;

    /** @hide Process is in the background, but it can't restore its state so we want
     * to try to avoid killing it. */
    public static final int PROCESS_STATE_HEAVY_WEIGHT = 6;

    /** @hide Process is in the background running a service. */
    /** @hide Process is in the background running a service.  Unlike oom_adj, this level
     * is used for both the normal running in background state and the executing
     * operations state. */
    public static final int PROCESS_STATE_SERVICE = 7;

    /** @hide Process is in the background running a receiver.   Note that from the
     * perspective of oom_adj receivers run at a higher foreground level, but for our
     * prioritization here that is not necessary and putting them below services means
     * many fewer changes in some process states as they receive broadcasts. */
    public static final int PROCESS_STATE_RECEIVER = 8;

    /** @hide Process is in the background but hosts the home activity. */
    public static final int PROCESS_STATE_HOME = 8;
    public static final int PROCESS_STATE_HOME = 9;

    /** @hide Process is in the background but hosts the last shown activity. */
    public static final int PROCESS_STATE_LAST_ACTIVITY = 9;
    public static final int PROCESS_STATE_LAST_ACTIVITY = 10;

    /** @hide Process is being cached for later use and contains activities. */
    public static final int PROCESS_STATE_CACHED_ACTIVITY = 11;

    /** @hide Process is being cached for later use and is a client of another cached
     * process that contains activities. */
    public static final int PROCESS_STATE_CACHED_ACTIVITY_CLIENT = 12;

    /** @hide Process is being cached for later use. */
    public static final int PROCESS_STATE_CACHED = 10;
    /** @hide Process is being cached for later use and is empty. */
    public static final int PROCESS_STATE_CACHED_EMPTY = 13;

    /*package*/ ActivityManager(Context context, Handler handler) {
        mContext = context;
+9 −1
Original line number Diff line number Diff line
@@ -230,7 +230,15 @@ public abstract class Context {
     * tries to balance such requests from one app vs. the importantance of
     * keeping other apps around.
     */
    public static final int BIND_VISIBLE = 0x0100;
    public static final int BIND_VISIBLE = 0x10000000;

    /**
     * @hide
     * Flag for {@link #bindService}: Consider this binding to be causing the target
     * process to be showing UI, so it will be do a UI_HIDDEN memory trim when it goes
     * away.
     */
    public static final int BIND_SHOWING_UI = 0x20000000;

    /**
     * Flag for {@link #bindService}: Don't consider the bound service to be
+11 −2
Original line number Diff line number Diff line
@@ -192,6 +192,14 @@ public final class Debug
            return dalvikPss + nativePss + otherPss;
        }

        /**
         * @hide Return total PSS memory usage in kB.
         */
        public int getTotalUss() {
            return dalvikPrivateClean + dalvikPrivateDirty
                    + nativePrivateClean + nativePrivateDirty
                    + otherPrivateClean + otherPrivateDirty;
        }

        /**
         * Return total PSS memory usage in kB.
@@ -1001,9 +1009,10 @@ href="{@docRoot}guide/developing/tools/traceview.html">Traceview: A Graphical Lo

    /**
     * Retrieves the PSS memory used by the process as given by the
     * smaps. @hide
     * smaps.  Optionally supply a long array of 1 entry to also
     * receive the uss of the process.  @hide
     */
    public static native long getPss(int pid);
    public static native long getPss(int pid, long[] outUss);

    /**
     * Establish an object allocation limit in the current thread.
+28 −8
Original line number Diff line number Diff line
@@ -380,10 +380,11 @@ static void android_os_Debug_getDirtyPages(JNIEnv *env, jobject clazz, jobject o
    android_os_Debug_getDirtyPagesPid(env, clazz, getpid(), object);
}

static jlong android_os_Debug_getPssPid(JNIEnv *env, jobject clazz, jint pid)
static jlong android_os_Debug_getPssPid(JNIEnv *env, jobject clazz, jint pid, jlongArray outUss)
{
    char line[1024];
    jlong pss = 0;
    jlong uss = 0;
    unsigned temp;

    char tmp[128];
@@ -398,23 +399,42 @@ static jlong android_os_Debug_getPssPid(JNIEnv *env, jobject clazz, jint pid)
            break;
        }

        if (strncmp(line, "Pss: ", 5) == 0) {
            char* c = line + 5;
        if (line[0] == 'P') {
            if (strncmp(line, "Pss:", 4) == 0) {
                char* c = line + 4;
                while (*c != 0 && (*c < '0' || *c > '9')) {
                    c++;
                }
                pss += atoi(c);
            } else if (strncmp(line, "Private_Clean:", 14)
                    || strncmp(line, "Private_Dirty:", 14)) {
                char* c = line + 14;
                while (*c != 0 && (*c < '0' || *c > '9')) {
                    c++;
                }
                uss += atoi(c);
            }
        }
    }

    fclose(fp);

    if (outUss != NULL) {
        if (env->GetArrayLength(outUss) >= 1) {
            jlong* outUssArray = env->GetLongArrayElements(outUss, 0);
            if (outUssArray != NULL) {
                outUssArray[0] = uss;
            }
            env->ReleaseLongArrayElements(outUss, outUssArray, 0);
        }
    }

    return pss;
}

static jlong android_os_Debug_getPss(JNIEnv *env, jobject clazz)
{
    return android_os_Debug_getPssPid(env, clazz, getpid());
    return android_os_Debug_getPssPid(env, clazz, getpid(), NULL);
}

static jint read_binder_stat(const char* stat)
@@ -689,7 +709,7 @@ static JNINativeMethod gMethods[] = {
            (void*) android_os_Debug_getDirtyPagesPid },
    { "getPss",                 "()J",
            (void*) android_os_Debug_getPss },
    { "getPss",                 "(I)J",
    { "getPss",                 "(I[J)J",
            (void*) android_os_Debug_getPssPid },
    { "dumpNativeHeap",         "(Ljava/io/FileDescriptor;)V",
            (void*) android_os_Debug_dumpNativeHeap },
+1 −1
Original line number Diff line number Diff line
@@ -1210,7 +1210,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
        mCurIntent.putExtra(Intent.EXTRA_CLIENT_INTENT, PendingIntent.getActivity(
                mContext, 0, new Intent(Settings.ACTION_INPUT_METHOD_SETTINGS), 0));
        if (bindCurrentInputMethodService(mCurIntent, this, Context.BIND_AUTO_CREATE
                | Context.BIND_NOT_VISIBLE)) {
                | Context.BIND_NOT_VISIBLE | Context.BIND_SHOWING_UI)) {
            mLastBindTime = SystemClock.uptimeMillis();
            mHaveConnection = true;
            mCurId = info.getId();
Loading