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

Commit e78b01ad authored by Vishnu Nair's avatar Vishnu Nair
Browse files

Add proto dump flag to services (2/2)

Adds new PROTO flag which requests services to dump sections in proto format. Modifies PriorityDumper helper class to parse proto arguments and set asProto flags. Registers WM and AM with proto dump supprt.

Bug: 67716082

Test: frameworks/base/services/tests/runtests.py -e class "com.android.server.utils.PriorityDumpTest"
Test: adb bugreport ~/tmp/bug.zip
Test: adb shell dumpsys window --proto
Test: adb shell dumpsys activity --proto

Change-Id: Icfc6857c8a9340110a43343734a27e48d0b5a229
parent a5da2cf5
Loading
Loading
Loading
Loading
+12 −8
Original line number Diff line number Diff line
@@ -45,13 +45,13 @@ public interface IServiceManager extends IInterface
     * Place a new @a service called @a name into the service
     * manager.
     */
    void addService(String name, IBinder service, boolean allowIsolated, int dumpPriority)
    void addService(String name, IBinder service, boolean allowIsolated, int dumpFlags)
            throws RemoteException;

    /**
     * Return a list of all currently running services.
     */
    String[] listServices(int dumpPriority) throws RemoteException;
    String[] listServices(int dumpFlags) throws RemoteException;

    /**
     * Assign a permission controller to the service manager.  After set, this
@@ -72,9 +72,13 @@ public interface IServiceManager extends IInterface
    /*
     * Must update values in IServiceManager.h
     */
    int DUMP_PRIORITY_CRITICAL = 1 << 0;
    int DUMP_PRIORITY_HIGH = 1 << 1;
    int DUMP_PRIORITY_NORMAL = 1 << 2;
    int DUMP_PRIORITY_ALL = DUMP_PRIORITY_CRITICAL | DUMP_PRIORITY_HIGH
            | DUMP_PRIORITY_NORMAL;
    /* Allows services to dump sections according to priorities. */
    int DUMP_FLAG_PRIORITY_CRITICAL = 1 << 0;
    int DUMP_FLAG_PRIORITY_HIGH = 1 << 1;
    int DUMP_FLAG_PRIORITY_NORMAL = 1 << 2;
    int DUMP_FLAG_PRIORITY_ALL = DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PRIORITY_HIGH
            | DUMP_FLAG_PRIORITY_NORMAL;
    /* Allows services to dump sections in protobuf format. */
    int DUMP_FLAG_PROTO = 1 << 3;

}
+3 −3
Original line number Diff line number Diff line
@@ -83,7 +83,7 @@ public final class ServiceManager {
     * @param service the service object
     */
    public static void addService(String name, IBinder service) {
        addService(name, service, false, IServiceManager.DUMP_PRIORITY_NORMAL);
        addService(name, service, false, IServiceManager.DUMP_FLAG_PRIORITY_NORMAL);
    }

    /**
@@ -96,7 +96,7 @@ public final class ServiceManager {
     * to access this service
     */
    public static void addService(String name, IBinder service, boolean allowIsolated) {
        addService(name, service, allowIsolated, IServiceManager.DUMP_PRIORITY_NORMAL);
        addService(name, service, allowIsolated, IServiceManager.DUMP_FLAG_PRIORITY_NORMAL);
    }

    /**
@@ -143,7 +143,7 @@ public final class ServiceManager {
     */
    public static String[] listServices() {
        try {
            return getIServiceManager().listServices(IServiceManager.DUMP_PRIORITY_ALL);
            return getIServiceManager().listServices(IServiceManager.DUMP_FLAG_PRIORITY_ALL);
        } catch (RemoteException e) {
            Log.e(TAG, "error in listServices", e);
            return null;
+38 −30
Original line number Diff line number Diff line
@@ -49,9 +49,10 @@ import static android.content.res.Configuration.UI_MODE_TYPE_TELEVISION;
import static android.net.NetworkPolicyManager.isProcStateAllowedWhileIdleOrPowerSaveMode;
import static android.net.NetworkPolicyManager.isProcStateAllowedWhileOnRestrictBackground;
import static android.os.Build.VERSION_CODES.N;
import static android.os.IServiceManager.DUMP_PRIORITY_CRITICAL;
import static android.os.IServiceManager.DUMP_PRIORITY_HIGH;
import static android.os.IServiceManager.DUMP_PRIORITY_NORMAL;
import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_CRITICAL;
import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_HIGH;
import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_NORMAL;
import static android.os.IServiceManager.DUMP_FLAG_PROTO;
import static android.os.Process.BLUETOOTH_UID;
import static android.os.Process.FIRST_APPLICATION_UID;
import static android.os.Process.FIRST_ISOLATED_UID;
@@ -714,30 +715,36 @@ public class ActivityManagerService extends IActivityManager.Stub
     */
    private final PriorityDump.PriorityDumper mPriorityDumper = new PriorityDump.PriorityDumper() {
        @Override
        public void dumpCritical(FileDescriptor fd, PrintWriter pw, String[] args) {
            doDump(fd, pw, new String[] {"activities"});
        public void dumpCritical(FileDescriptor fd, PrintWriter pw, String[] args,
                boolean asProto) {
            if (asProto) return;
            doDump(fd, pw, new String[]{"activities"}, asProto);
        }
        @Override
        public void dumpNormal(FileDescriptor fd, PrintWriter pw, String[] args) {
            doDump(fd, pw, new String[] {"settings"});
            doDump(fd, pw, new String[] {"intents"});
            doDump(fd, pw, new String[] {"broadcasts"});
            doDump(fd, pw, new String[] {"providers"});
            doDump(fd, pw, new String[] {"permissions"});
            doDump(fd, pw, new String[] {"services"});
            doDump(fd, pw, new String[] {"recents"});
            doDump(fd, pw, new String[] {"lastanr"});
            doDump(fd, pw, new String[] {"starter"});
        public void dumpNormal(FileDescriptor fd, PrintWriter pw, String[] args, boolean asProto) {
            if (asProto) {
                doDump(fd, pw, new String[0], asProto);
            } else {
                doDump(fd, pw, new String[]{"settings"}, asProto);
                doDump(fd, pw, new String[]{"intents"}, asProto);
                doDump(fd, pw, new String[]{"broadcasts"}, asProto);
                doDump(fd, pw, new String[]{"providers"}, asProto);
                doDump(fd, pw, new String[]{"permissions"}, asProto);
                doDump(fd, pw, new String[]{"services"}, asProto);
                doDump(fd, pw, new String[]{"recents"}, asProto);
                doDump(fd, pw, new String[]{"lastanr"}, asProto);
                doDump(fd, pw, new String[]{"starter"}, asProto);
                if (mAssociations.size() > 0) {
                doDump(fd, pw, new String[] {"associations"});
                    doDump(fd, pw, new String[]{"associations"}, asProto);
                }
                doDump(fd, pw, new String[]{"processes"}, asProto);
            }
            doDump(fd, pw, new String[] {"processes"});
        }
        @Override
        public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
            doDump(fd, pw, args);
        public void dump(FileDescriptor fd, PrintWriter pw, String[] args, boolean asProto) {
            doDump(fd, pw, args, asProto);
        }
    };
@@ -2483,15 +2490,15 @@ public class ActivityManagerService extends IActivityManager.Stub
    public void setSystemProcess() {
        try {
            ServiceManager.addService(Context.ACTIVITY_SERVICE, this, /* allowIsolated= */ true,
                    DUMP_PRIORITY_CRITICAL | DUMP_PRIORITY_NORMAL);
                    DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PRIORITY_NORMAL | DUMP_FLAG_PROTO);
            ServiceManager.addService(ProcessStats.SERVICE_NAME, mProcessStats);
            ServiceManager.addService("meminfo", new MemBinder(this), /* allowIsolated= */ false,
                    DUMP_PRIORITY_HIGH | DUMP_PRIORITY_NORMAL);
                    DUMP_FLAG_PRIORITY_HIGH | DUMP_FLAG_PRIORITY_NORMAL);
            ServiceManager.addService("gfxinfo", new GraphicsBinder(this));
            ServiceManager.addService("dbinfo", new DbBinder(this));
            if (MONITOR_CPU_USAGE) {
                ServiceManager.addService("cpuinfo", new CpuBinder(this),
                        /* allowIsolated= */ false, DUMP_PRIORITY_CRITICAL);
                        /* allowIsolated= */ false, DUMP_FLAG_PRIORITY_CRITICAL);
            }
            ServiceManager.addService("permission", new PermissionController(this));
            ServiceManager.addService("processinfo", new ProcessInfoService(this));
@@ -2544,7 +2551,9 @@ public class ActivityManagerService extends IActivityManager.Stub
        private final PriorityDump.PriorityDumper mPriorityDumper =
                new PriorityDump.PriorityDumper() {
            @Override
            public void dumpNormal(FileDescriptor fd, PrintWriter pw, String[] args) {
            public void dumpNormal(FileDescriptor fd, PrintWriter pw, String[] args,
                    boolean asProto) {
                if (asProto) return;
                mActivityManagerService.dumpApplicationMemoryUsage(fd, pw, "  ", args, false, null);
            }
        };
@@ -2594,7 +2603,9 @@ public class ActivityManagerService extends IActivityManager.Stub
        private final PriorityDump.PriorityDumper mPriorityDumper =
                new PriorityDump.PriorityDumper() {
            @Override
            public void dumpCritical(FileDescriptor fd, PrintWriter pw, String[] args) {
            public void dumpCritical(FileDescriptor fd, PrintWriter pw, String[] args,
                    boolean asProto) {
                if (asProto) return;
                if (!DumpUtils.checkDumpAndUsageStatsPermission(mActivityManagerService.mContext,
                        "cpuinfo", pw)) return;
                synchronized (mActivityManagerService.mProcessCpuTracker) {
@@ -14789,7 +14800,7 @@ public class ActivityManagerService extends IActivityManager.Stub
    /**
     * Wrapper function to print out debug data filtered by specified arguments.
    */
    private void doDump(FileDescriptor fd, PrintWriter pw, String[] args) {
    private void doDump(FileDescriptor fd, PrintWriter pw, String[] args, boolean useProto) {
        if (!DumpUtils.checkDumpAndUsageStatsPermission(mContext, TAG, pw)) return;
        boolean dumpAll = false;
@@ -14798,7 +14809,6 @@ public class ActivityManagerService extends IActivityManager.Stub
        boolean dumpCheckinFormat = false;
        boolean dumpVisibleStacksOnly = false;
        boolean dumpFocusedStackOnly = false;
        boolean useProto = false;
        String dumpPackage = null;
        int opti = 0;
@@ -14832,8 +14842,6 @@ public class ActivityManagerService extends IActivityManager.Stub
            } else if ("-h".equals(opt)) {
                ActivityManagerShellCommand.dumpHelp(pw, true);
                return;
            } else if ("--proto".equals(opt)) {
                useProto = true;
            } else {
                pw.println("Unknown argument: " + opt + "; use -h for help");
            }
+113 −40
Original line number Diff line number Diff line
@@ -16,12 +16,19 @@

package com.android.server.utils;

import android.annotation.IntDef;

import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;

/**
 * Helper for {@link android.os.Binder#dump(java.io.FileDescriptor, String[])} that supports the
 * {@link #PRIORITY_ARG} argument.
 * {@link #PRIORITY_ARG} and {@link #PROTO_ARG} arguments.
 * <p>
 * Typical usage:
 *
@@ -31,14 +38,26 @@ public class SpringfieldNuclearPowerPlant extends Binder {
 private final PriorityDump.PriorityDumper mPriorityDumper = new PriorityDump.PriorityDumper() {

     @Override
     public void dumpCritical(FileDescriptor fd, PrintWriter pw, String[] args) {
     public void dumpCritical(FileDescriptor fd, PrintWriter pw, String[] args, boolean asProto) {
       if (asProto) {
         ProtoOutputStream proto = new ProtoOutputStream(fd);
         proto.write(SpringfieldProto.DONUTS, 1);
         proto.flush();
       } else {
         pw.println("Donuts in the box: 1");
       }
     }

     @Override
     public void dumpNormal(FileDescriptor fd, PrintWriter pw, String[] args) {
        if (asProto) {
          ProtoOutputStream proto = new ProtoOutputStream(fd);
          proto.write(SpringfieldProto.REACTOR_STATUS, DANGER_MELTDOWN_IMMINENT);
          proto.flush();
        } else {
          pw.println("Nuclear reactor status: DANGER - MELTDOWN IMMINENT");
        }
     }
  };

  @Override
@@ -65,6 +84,9 @@ public class SpringfieldNuclearPowerPlant extends Binder {
    $ adb shell dumpsys snpp --dump-priority NORMAL
    Nuclear reactor status: DANGER - MELTDOWN IMMINENT

    $ adb shell dumpsys snpp --dump-priority CRITICAL --proto
    //binary output

 * </code></pre>
 *
 *
@@ -85,95 +107,146 @@ public class SpringfieldNuclearPowerPlant extends Binder {
public final class PriorityDump {

    public static final String PRIORITY_ARG = "--dump-priority";
    public static final String PROTO_ARG = "--proto";

    private PriorityDump() {
        throw new UnsupportedOperationException();
    }

    /** Enum to switch through supported priority types */
    @Retention(RetentionPolicy.SOURCE)
    @IntDef({PRIORITY_TYPE_INVALID, PRIORITY_TYPE_CRITICAL, PRIORITY_TYPE_HIGH,
            PRIORITY_TYPE_NORMAL})
    private @interface PriorityType { }
    private static final int PRIORITY_TYPE_INVALID = 0;
    private static final int PRIORITY_TYPE_CRITICAL = 1;
    private static final int PRIORITY_TYPE_HIGH = 2;
    private static final int PRIORITY_TYPE_NORMAL = 3;

    /**
     * Parses {@code} and call the proper {@link PriorityDumper} method when the first argument is
     * {@code --dump-priority}, stripping the priority and its type.
     * Parses {@code args} matching {@code --dump-priority} and/or {@code --proto}. The matching
     * arguments are stripped.
     * <p>
     * If priority args are passed as an argument, it will call the appropriate method and if proto
     * args are passed then the {@code asProto} flag is set.
     * <p>
     * For example, if called as {@code --dump-priority HIGH arg1 arg2 arg3}, it will call
     * <code>dumper.dumpHigh(fd, pw, {"arg1", "arg2", "arg3"}) </code>
     * <code>dumper.dumpHigh(fd, pw, {"arg1", "arg2", "arg3"}, false) </code>
     * <p>
     * If the {@code --dump-priority} is not set, it calls
     * {@link PriorityDumper#dump(FileDescriptor, PrintWriter, String[])} passing the whole
     * {@link PriorityDumper#dump(FileDescriptor, PrintWriter, String[], boolean)} passing the whole
     * {@code args} instead.
     */
    public static void dump(PriorityDumper dumper, FileDescriptor fd, PrintWriter pw,
            String[] args) {
        if (args != null && args.length >= 2 && args[0].equals(PRIORITY_ARG)) {
            final String priority = args[1];
        boolean asProto = false;
        @PriorityType int priority = PRIORITY_TYPE_INVALID;

        if (args == null) {
            dumper.dump(fd, pw, args, asProto);
            return;
        }

        String[] strippedArgs = new String[args.length];
        int strippedCount = 0;
        for (int argIndex = 0; argIndex < args.length; argIndex++) {
            if (args[argIndex].equals(PROTO_ARG)) {
                asProto = true;
            } else if (args[argIndex].equals(PRIORITY_ARG)) {
                if (argIndex + 1 < args.length) {
                    argIndex++;
                    priority = getPriorityType(args[argIndex]);
                }
            } else {
                strippedArgs[strippedCount++] = args[argIndex];
            }
        }

        if (strippedCount < args.length) {
            strippedArgs = Arrays.copyOf(strippedArgs, strippedCount);
        }

        switch (priority) {
                case "CRITICAL": {
                    dumper.dumpCritical(fd, pw, getStrippedArgs(args));
            case PRIORITY_TYPE_CRITICAL: {
                dumper.dumpCritical(fd, pw, strippedArgs, asProto);
                return;
            }
                case "HIGH": {
                    dumper.dumpHigh(fd, pw, getStrippedArgs(args));
            case PRIORITY_TYPE_HIGH: {
                dumper.dumpHigh(fd, pw, strippedArgs, asProto);
                return;
            }
                case "NORMAL": {
                    dumper.dumpNormal(fd, pw, getStrippedArgs(args));
            case PRIORITY_TYPE_NORMAL: {
                dumper.dumpNormal(fd, pw, strippedArgs, asProto);
                return;
            }
            default: {
                dumper.dump(fd, pw, strippedArgs, asProto);
                return;
            }
        }
        dumper.dump(fd, pw, args);
    }

    /**
     * Gets an array without the {@code --dump-priority PRIORITY} prefix.
     * Converts priority argument type to enum.
     */
    private static String[] getStrippedArgs(String[] args) {
        final String[] stripped = new String[args.length - 2];
        System.arraycopy(args, 2, stripped, 0, stripped.length);
        return stripped;
    private static @PriorityType int getPriorityType(String arg) {
        switch (arg) {
            case "CRITICAL": {
                return PRIORITY_TYPE_CRITICAL;
            }
            case "HIGH": {
                return PRIORITY_TYPE_HIGH;
            }
            case "NORMAL": {
                return PRIORITY_TYPE_NORMAL;
            }
        }
        return PRIORITY_TYPE_INVALID;
    }

    /**
     * Helper for {@link android.os.Binder#dump(java.io.FileDescriptor, String[])} that supports the
     * {@link #PRIORITY_ARG} argument.
     * {@link #PRIORITY_ARG} and {@link #PROTO_ARG} arguments.
     *
     * @hide
     */
    public static interface PriorityDumper {
    public interface PriorityDumper {

        /**
         * Dumps only the critical section.
         */
        @SuppressWarnings("unused")
        default void dumpCritical(FileDescriptor fd, PrintWriter pw, String[] args) {
        default void dumpCritical(FileDescriptor fd, PrintWriter pw, String[] args,
                boolean asProto) {
        }

        /**
         * Dumps only the high-priority section.
         */
        @SuppressWarnings("unused")
        default void dumpHigh(FileDescriptor fd, PrintWriter pw, String[] args) {
        default void dumpHigh(FileDescriptor fd, PrintWriter pw, String[] args, boolean asProto) {
        }

        /**
         * Dumps only the normal section.
         */
        @SuppressWarnings("unused")
        default void dumpNormal(FileDescriptor fd, PrintWriter pw, String[] args) {
        default void dumpNormal(FileDescriptor fd, PrintWriter pw, String[] args, boolean asProto) {
        }

        /**
         * Dumps all sections.
         * <p>
         * This method is called when
         * {@link PriorityDump#dump(PriorityDumper, FileDescriptor, PrintWriter, String[])} is
         * called without priority arguments. By default, it calls the 3 {@code dumpTYPE} methods,
         * so sub-classes just need to implement the priority types they support.
         * {@link PriorityDump#dump(PriorityDumper, FileDescriptor, PrintWriter, String[], boolean)}
         * is called without priority arguments. By default, it calls the 3 {@code dumpTYPE}
         * methods, so sub-classes just need to implement the priority types they support.
         */
        @SuppressWarnings("unused")
        default void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
            dumpCritical(fd, pw, args);
            dumpHigh(fd, pw, args);
            dumpNormal(fd, pw, args);
        default void dump(FileDescriptor fd, PrintWriter pw, String[] args, boolean asProto) {
            dumpCritical(fd, pw, args, asProto);
            dumpHigh(fd, pw, args, asProto);
            dumpNormal(fd, pw, args, asProto);
        }
    }
}
+6 −8
Original line number Diff line number Diff line
@@ -394,13 +394,14 @@ public class WindowManagerService extends IWindowManager.Stub

    private final PriorityDump.PriorityDumper mPriorityDumper = new PriorityDump.PriorityDumper() {
        @Override
        public void dumpCritical(FileDescriptor fd, PrintWriter pw, String[] args) {
            doDump(fd, pw, new String[] {"-a"});
        public void dumpCritical(FileDescriptor fd, PrintWriter pw, String[] args,
                boolean asProto) {
            doDump(fd, pw, new String[] {"-a"}, asProto);
        }

        @Override
        public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
            doDump(fd, pw, args);
        public void dump(FileDescriptor fd, PrintWriter pw, String[] args, boolean asProto) {
            doDump(fd, pw, args, asProto);
        }
    };

@@ -6825,10 +6826,9 @@ public class WindowManagerService extends IWindowManager.Stub
        PriorityDump.dump(mPriorityDumper, fd, pw, args);
    }

    private void doDump(FileDescriptor fd, PrintWriter pw, String[] args) {
    private void doDump(FileDescriptor fd, PrintWriter pw, String[] args, boolean useProto) {
        if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
        boolean dumpAll = false;
        boolean useProto = false;

        int opti = 0;
        while (opti < args.length) {
@@ -6839,8 +6839,6 @@ public class WindowManagerService extends IWindowManager.Stub
            opti++;
            if ("-a".equals(opt)) {
                dumpAll = true;
            } else if ("--proto".equals(opt)) {
                useProto = true;
            } else if ("-h".equals(opt)) {
                pw.println("Window manager dump options:");
                pw.println("  [-a] [-h] [cmd] ...");
Loading