1f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme/**
2f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme * Copyright (c) 2016, The Android Open Source Project
3f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme *
4f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme * Licensed under the Apache License, Version 2.0 (the "License");
5f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme * you may not use this file except in compliance with the License.
6f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme * You may obtain a copy of the License at
7f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme *
8f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme *     http://www.apache.org/licenses/LICENSE-2.0
9f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme *
10f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme * Unless required by applicable law or agreed to in writing, software
11f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme * distributed under the License is distributed on an "AS IS" BASIS,
12f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme * See the License for the specific language governing permissions and
14f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme * limitations under the License.
15f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme */
16f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme
17f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Lemepackage com.android.server.utils;
18f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme
19f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Lemeimport java.io.FileDescriptor;
20f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Lemeimport java.io.PrintWriter;
21f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme
22f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme/**
23f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme * Helper for {@link android.os.Binder#dump(java.io.FileDescriptor, String[])} that supports the
24f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme * {@link #PRIORITY_ARG} argument.
25f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme * <p>
26f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme * Typical usage:
27f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme *
28f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme * <pre><code>
29f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Lemepublic class SpringfieldNuclearPowerPlant extends Binder {
30f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme
31f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme private final PriorityDump.PriorityDumper mPriorityDumper = new PriorityDump.PriorityDumper() {
32f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme
33f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme     @Override
34f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme     public void dumpCritical(FileDescriptor fd, PrintWriter pw, String[] args) {
35f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme       pw.println("Donuts in the box: 1");
36f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme     }
37f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme
38f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme     @Override
39f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme     public void dumpNormal(FileDescriptor fd, PrintWriter pw, String[] args) {
40f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme       pw.println("Nuclear reactor status: DANGER - MELTDOWN IMMINENT");
41f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme     }
42f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme  };
43f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme
44f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme  @Override
45f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme  protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
46f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme      PriorityDump.dump(mPriorityDumper, fd, pw, args);
47f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme  }
48f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme}
49f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme
50f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme * </code></pre>
51f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme *
52f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme * <strong>Disclaimer</strong>: a real-life service should prioritize core status over donuts :-)
53f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme *
54f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme * <p>Then to invoke it:
55f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme *
56f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme * <pre><code>
57f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme *
58f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme    $ adb shell dumpsys snpp
59f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme    Donuts in the box: 1
60f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme    Nuclear reactor status: DANGER - MELTDOWN IMMINENT
61f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme
62f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme    $ adb shell dumpsys snpp --dump_priority CRITICAL
63f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme    Donuts in the box: 1
64f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme
65f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme    $ adb shell dumpsys snpp --dump_priority NORMAL
66f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme    Nuclear reactor status: DANGER - MELTDOWN IMMINENT
67f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme
68f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme * </code></pre>
69f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme *
70f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme *
71f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme *
72f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme * <p>To run the unit tests:
73f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme * <pre><code>
74f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme *
75f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme mmm -j32 frameworks/base/services/tests/servicestests/ && \
76f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme adb install -r -g ${ANDROID_PRODUCT_OUT}/data/app/FrameworksServicesTests/FrameworksServicesTests.apk && \
77f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme adb shell am instrument -e class "com.android.server.utils.PriorityDumpTest" \
78f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme -w "com.android.frameworks.servicestests/android.support.test.runner.AndroidJUnitRunner"
79f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme
80f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme * </code></pre>
81f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme *
82f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme *
83f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme * @hide
84f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme */
85f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Lemepublic final class PriorityDump {
86f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme
87f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme    public static final String PRIORITY_ARG = "--dump_priority";
88f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme
89f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme    private PriorityDump() {
90f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme        throw new UnsupportedOperationException();
91f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme    }
92f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme
93f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme    /**
94f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme     * Parses {@code} and call the proper {@link PriorityDumper} method when the first argument is
95f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme     * {@code --dump_priority}, stripping the priority and its type.
96f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme     * <p>
97f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme     * For example, if called as {@code --dump_priority HIGH arg1 arg2 arg3}, it will call
98f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme     * <code>dumper.dumpHigh(fd, pw, {"arg1", "arg2", "arg3"}) </code>
99f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme     * <p>
100f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme     * If the {@code --dump_priority} is not set, it calls
101f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme     * {@link PriorityDumper#dump(FileDescriptor, PrintWriter, String[])} passing the whole
102f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme     * {@code args} instead.
103f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme     */
104f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme    public static void dump(PriorityDumper dumper, FileDescriptor fd, PrintWriter pw,
105f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme            String[] args) {
106f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme        if (args != null && args.length >= 2 && args[0].equals(PRIORITY_ARG)) {
107f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme            final String priority = args[1];
108f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme            switch (priority) {
109f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme                case "CRITICAL": {
110f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme                    dumper.dumpCritical(fd, pw, getStrippedArgs(args));
111f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme                    return;
112f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme                }
113f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme                case "HIGH": {
114f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme                    dumper.dumpHigh(fd, pw, getStrippedArgs(args));
115f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme                    return;
116f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme                }
117f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme                case "NORMAL": {
118f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme                    dumper.dumpNormal(fd, pw, getStrippedArgs(args));
119f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme                    return;
120f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme                }
121f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme            }
122f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme        }
123f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme        dumper.dump(fd, pw, args);
124f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme    }
125f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme
126f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme    /**
127f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme     * Gets an array without the {@code --dump_priority PRIORITY} prefix.
128f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme     */
129f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme    private static String[] getStrippedArgs(String[] args) {
130f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme        final String[] stripped = new String[args.length - 2];
131f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme        System.arraycopy(args, 2, stripped, 0, stripped.length);
132f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme        return stripped;
133f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme    }
134f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme
135f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme    /**
136f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme     * Helper for {@link android.os.Binder#dump(java.io.FileDescriptor, String[])} that supports the
137f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme     * {@link #PRIORITY_ARG} argument.
138f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme     *
139f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme     * @hide
140f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme     */
141f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme    public static interface PriorityDumper {
142f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme
143f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme        /**
144f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme         * Dumps only the critical section.
145f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme         */
146f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme        @SuppressWarnings("unused")
147f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme        default void dumpCritical(FileDescriptor fd, PrintWriter pw, String[] args) {
148f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme        }
149f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme
150f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme        /**
151f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme         * Dumps only the high-priority section.
152f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme         */
153f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme        @SuppressWarnings("unused")
154f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme        default void dumpHigh(FileDescriptor fd, PrintWriter pw, String[] args) {
155f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme        }
156f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme
157f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme        /**
158f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme         * Dumps only the normal section.
159f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme         */
160f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme        @SuppressWarnings("unused")
161f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme        default void dumpNormal(FileDescriptor fd, PrintWriter pw, String[] args) {
162f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme        }
163f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme
164f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme        /**
165f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme         * Dumps all sections.
166f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme         * <p>
167f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme         * This method is called when
168f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme         * {@link PriorityDump#dump(PriorityDumper, FileDescriptor, PrintWriter, String[])} is
169f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme         * called without priority arguments. By default, it calls the 3 {@code dumpTYPE} methods,
170f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme         * so sub-classes just need to implement the priority types they support.
171f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme         */
172f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme        @SuppressWarnings("unused")
173f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme        default void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
174f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme            dumpCritical(fd, pw, args);
175f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme            dumpHigh(fd, pw, args);
176f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme            dumpNormal(fd, pw, args);
177f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme        }
178f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme    }
179f4006d9b0be123b2a4e874b89eb4a431d3d49c8bFelipe Leme}
180