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

Commit 8233d9f6 authored by Suren Baghdasaryan's avatar Suren Baghdasaryan Committed by Android (Google) Code Review
Browse files

Merge "ActivityManager: Add dumpsys command to report number of lmkd kills"

parents 9ac286db 254752c6
Loading
Loading
Loading
Loading
+40 −0
Original line number Original line Diff line number Diff line
@@ -9159,6 +9159,11 @@ public class ActivityManagerService extends IActivityManager.Stub
                pw.println("-------------------------------------------------------------------------------");
                pw.println("-------------------------------------------------------------------------------");
            }
            }
            dumpBinderProxies(pw);
            dumpBinderProxies(pw);
            pw.println();
            if (dumpAll) {
                pw.println("-------------------------------------------------------------------------------");
            }
            dumpLmkLocked(pw);
        }
        }
    }
    }
@@ -9349,6 +9354,10 @@ public class ActivityManagerService extends IActivityManager.Stub
                synchronized (this) {
                synchronized (this) {
                    dumpOomLocked(fd, pw, args, opti, true);
                    dumpOomLocked(fd, pw, args, opti, true);
                }
                }
            } else if ("lmk".equals(cmd)) {
                synchronized (this) {
                    dumpLmkLocked(pw);
                }
            } else if ("permissions".equals(cmd) || "perm".equals(cmd)) {
            } else if ("permissions".equals(cmd) || "perm".equals(cmd)) {
                synchronized (this) {
                synchronized (this) {
                    dumpPermissionsLocked(fd, pw, args, opti, true, null);
                    dumpPermissionsLocked(fd, pw, args, opti, true, null);
@@ -10383,6 +10392,37 @@ public class ActivityManagerService extends IActivityManager.Stub
        return true;
        return true;
    }
    }
    private boolean reportLmkKillAtOrBelow(PrintWriter pw, int oom_adj) {
        Integer cnt = ProcessList.getLmkdKillCount(0, oom_adj);
        if (cnt != null) {
            pw.println("    kills at or below oom_adj " + oom_adj + ": " + cnt);
            return true;
        }
        return false;
    }
    boolean dumpLmkLocked(PrintWriter pw) {
        pw.println("ACTIVITY MANAGER LMK KILLS (dumpsys activity lmk)");
        Integer cnt = ProcessList.getLmkdKillCount(ProcessList.UNKNOWN_ADJ,
                ProcessList.UNKNOWN_ADJ);
        if (cnt == null) {
            return false;
        }
        pw.println("  Total number of kills: " + cnt);
        return reportLmkKillAtOrBelow(pw, ProcessList.CACHED_APP_MAX_ADJ) &&
            reportLmkKillAtOrBelow(pw, ProcessList.CACHED_APP_MIN_ADJ) &&
            reportLmkKillAtOrBelow(pw, ProcessList.SERVICE_B_ADJ) &&
            reportLmkKillAtOrBelow(pw, ProcessList.PREVIOUS_APP_ADJ) &&
            reportLmkKillAtOrBelow(pw, ProcessList.HOME_APP_ADJ) &&
            reportLmkKillAtOrBelow(pw, ProcessList.SERVICE_ADJ) &&
            reportLmkKillAtOrBelow(pw, ProcessList.HEAVY_WEIGHT_APP_ADJ) &&
            reportLmkKillAtOrBelow(pw, ProcessList.BACKUP_APP_ADJ) &&
            reportLmkKillAtOrBelow(pw, ProcessList.PERCEPTIBLE_APP_ADJ) &&
            reportLmkKillAtOrBelow(pw, ProcessList.VISIBLE_APP_ADJ) &&
            reportLmkKillAtOrBelow(pw, ProcessList.FOREGROUND_APP_ADJ);
    }
    /**
    /**
     * There are three ways to call this:
     * There are three ways to call this:
     *  - no provider specified: dump all the providers
     *  - no provider specified: dump all the providers
+85 −29
Original line number Original line Diff line number Diff line
@@ -99,14 +99,22 @@ import dalvik.system.VMRuntime;
import java.io.File;
import java.io.File;
import java.io.IOException;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStream;
import java.io.InputStream;
import java.io.PrintWriter;
import java.io.PrintWriter;
import java.nio.ByteBuffer;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Arrays;
import java.util.List;
import java.util.List;


import libcore.io.IoUtils;

/**
/**
 * Activity manager code dealing with processes.
 * Activity manager code dealing with processes.
 *
 * Method naming convention:
 * <ul>
 * <li> Methods suffixed with "LS" should be called within the {@link #sLmkdSocketLock} lock.
 * </ul>
 */
 */
public final class ProcessList {
public final class ProcessList {
    private static final String TAG = TAG_WITH_CLASS_NAME ? "ProcessList" : TAG_AM;
    private static final String TAG = TAG_WITH_CLASS_NAME ? "ProcessList" : TAG_AM;
@@ -229,10 +237,12 @@ public final class ProcessList {
    // LMK_PROCPRIO <pid> <uid> <prio>
    // LMK_PROCPRIO <pid> <uid> <prio>
    // LMK_PROCREMOVE <pid>
    // LMK_PROCREMOVE <pid>
    // LMK_PROCPURGE
    // LMK_PROCPURGE
    // LMK_GETKILLCNT
    static final byte LMK_TARGET = 0;
    static final byte LMK_TARGET = 0;
    static final byte LMK_PROCPRIO = 1;
    static final byte LMK_PROCPRIO = 1;
    static final byte LMK_PROCREMOVE = 2;
    static final byte LMK_PROCREMOVE = 2;
    static final byte LMK_PROCPURGE = 3;
    static final byte LMK_PROCPURGE = 3;
    static final byte LMK_GETKILLCNT = 4;


    ActivityManagerService mService = null;
    ActivityManagerService mService = null;


@@ -268,9 +278,17 @@ public final class ProcessList {


    private boolean mHaveDisplaySize;
    private boolean mHaveDisplaySize;


    private static Object sLmkdSocketLock = new Object();

    @GuardedBy("sLmkdSocketLock")
    private static LocalSocket sLmkdSocket;
    private static LocalSocket sLmkdSocket;

    @GuardedBy("sLmkdSocketLock")
    private static OutputStream sLmkdOutputStream;
    private static OutputStream sLmkdOutputStream;


    @GuardedBy("sLmkdSocketLock")
    private static InputStream sLmkdInputStream;

    /**
    /**
     * Temporary to avoid allocations.  Protected by main lock.
     * Temporary to avoid allocations.  Protected by main lock.
     */
     */
@@ -505,7 +523,7 @@ public final class ProcessList {
                buf.putInt(mOomAdj[i]);
                buf.putInt(mOomAdj[i]);
            }
            }


            writeLmkd(buf);
            writeLmkd(buf, null);
            SystemProperties.set("sys.sysctl.extra_free_kbytes", Integer.toString(reserve));
            SystemProperties.set("sys.sysctl.extra_free_kbytes", Integer.toString(reserve));
        }
        }
        // GB: 2048,3072,4096,6144,7168,8192
        // GB: 2048,3072,4096,6144,7168,8192
@@ -978,7 +996,7 @@ public final class ProcessList {
        buf.putInt(pid);
        buf.putInt(pid);
        buf.putInt(uid);
        buf.putInt(uid);
        buf.putInt(amt);
        buf.putInt(amt);
        writeLmkd(buf);
        writeLmkd(buf, null);
        long now = SystemClock.elapsedRealtime();
        long now = SystemClock.elapsedRealtime();
        if ((now-start) > 250) {
        if ((now-start) > 250) {
            Slog.w("ActivityManager", "SLOW OOM ADJ: " + (now-start) + "ms for pid " + pid
            Slog.w("ActivityManager", "SLOW OOM ADJ: " + (now-start) + "ms for pid " + pid
@@ -997,16 +1015,38 @@ public final class ProcessList {
        ByteBuffer buf = ByteBuffer.allocate(4 * 2);
        ByteBuffer buf = ByteBuffer.allocate(4 * 2);
        buf.putInt(LMK_PROCREMOVE);
        buf.putInt(LMK_PROCREMOVE);
        buf.putInt(pid);
        buf.putInt(pid);
        writeLmkd(buf);
        writeLmkd(buf, null);
    }
    }


    private static boolean openLmkdSocket() {
    /*
     * {@hide}
     */
    public static final Integer getLmkdKillCount(int min_oom_adj, int max_oom_adj) {
        ByteBuffer buf = ByteBuffer.allocate(4 * 3);
        ByteBuffer repl = ByteBuffer.allocate(4 * 2);
        buf.putInt(LMK_GETKILLCNT);
        buf.putInt(min_oom_adj);
        buf.putInt(max_oom_adj);
        if (writeLmkd(buf, repl)) {
            int i = repl.getInt();
            if (i != LMK_GETKILLCNT) {
                Slog.e("ActivityManager", "Failed to get kill count, code mismatch");
                return null;
            }
            return new Integer(repl.getInt());
        }
        return null;
    }

    @GuardedBy("sLmkdSocketLock")
    private static boolean openLmkdSocketLS() {
        try {
        try {
            sLmkdSocket = new LocalSocket(LocalSocket.SOCKET_SEQPACKET);
            sLmkdSocket = new LocalSocket(LocalSocket.SOCKET_SEQPACKET);
            sLmkdSocket.connect(
            sLmkdSocket.connect(
                new LocalSocketAddress("lmkd",
                new LocalSocketAddress("lmkd",
                        LocalSocketAddress.Namespace.RESERVED));
                        LocalSocketAddress.Namespace.RESERVED));
            sLmkdOutputStream = sLmkdSocket.getOutputStream();
            sLmkdOutputStream = sLmkdSocket.getOutputStream();
            sLmkdInputStream = sLmkdSocket.getInputStream();
        } catch (IOException ex) {
        } catch (IOException ex) {
            Slog.w(TAG, "lowmemorykiller daemon socket open failed");
            Slog.w(TAG, "lowmemorykiller daemon socket open failed");
            sLmkdSocket = null;
            sLmkdSocket = null;
@@ -1017,28 +1057,42 @@ public final class ProcessList {
    }
    }


    // Never call directly, use writeLmkd() instead
    // Never call directly, use writeLmkd() instead
    private static boolean writeLmkdCommand(ByteBuffer buf) {
    @GuardedBy("sLmkdSocketLock")
    private static boolean writeLmkdCommandLS(ByteBuffer buf) {
        try {
        try {
            sLmkdOutputStream.write(buf.array(), 0, buf.position());
            sLmkdOutputStream.write(buf.array(), 0, buf.position());
        } catch (IOException ex) {
        } catch (IOException ex) {
            Slog.w(TAG, "Error writing to lowmemorykiller socket");
            Slog.w(TAG, "Error writing to lowmemorykiller socket");
            IoUtils.closeQuietly(sLmkdSocket);
            sLmkdSocket = null;
            return false;
        }
        return true;
    }


    // Never call directly, use writeLmkd() instead
    @GuardedBy("sLmkdSocketLock")
    private static boolean readLmkdReplyLS(ByteBuffer buf) {
        int len;
        try {
        try {
                sLmkdSocket.close();
            len = sLmkdInputStream.read(buf.array(), 0, buf.array().length);
            } catch (IOException ex2) {
            if (len == buf.array().length) {
                return true;
            }
        } catch (IOException ex) {
            Slog.w(TAG, "Error reading from lowmemorykiller socket");
        }
        }


        IoUtils.closeQuietly(sLmkdSocket);
        sLmkdSocket = null;
        sLmkdSocket = null;
        return false;
        return false;
    }
    }
        return true;
    }

    private static void writeLmkd(ByteBuffer buf) {


    private static boolean writeLmkd(ByteBuffer buf, ByteBuffer repl) {
        synchronized (sLmkdSocketLock) {
            for (int i = 0; i < 3; i++) {
            for (int i = 0; i < 3; i++) {
                if (sLmkdSocket == null) {
                if (sLmkdSocket == null) {
                if (openLmkdSocket() == false) {
                    if (openLmkdSocketLS() == false) {
                        try {
                        try {
                            Thread.sleep(1000);
                            Thread.sleep(1000);
                        } catch (InterruptedException ie) {
                        } catch (InterruptedException ie) {
@@ -1049,15 +1103,17 @@ public final class ProcessList {
                    // Purge any previously registered pids
                    // Purge any previously registered pids
                    ByteBuffer purge_buf = ByteBuffer.allocate(4);
                    ByteBuffer purge_buf = ByteBuffer.allocate(4);
                    purge_buf.putInt(LMK_PROCPURGE);
                    purge_buf.putInt(LMK_PROCPURGE);
                if (writeLmkdCommand(purge_buf) == false) {
                    if (writeLmkdCommandLS(purge_buf) == false) {
                        // Write failed, skip the rest and retry
                        // Write failed, skip the rest and retry
                        continue;
                        continue;
                    }
                    }
                }
                }
            if (writeLmkdCommand(buf)) {
                if (writeLmkdCommandLS(buf) && (repl == null || readLmkdReplyLS(repl))) {
                return;
                    return true;
                }
            }
            }
        }
        }
        return false;
    }
    }


    static void killProcessGroup(int uid, int pid) {
    static void killProcessGroup(int uid, int pid) {