/** * Copyright (c) 2016, The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.server.utils; import java.io.FileDescriptor; import java.io.PrintWriter; /** * Helper for {@link android.os.Binder#dump(java.io.FileDescriptor, String[])} that supports the * {@link #PRIORITY_ARG} argument. *

* Typical usage: * *


public class SpringfieldNuclearPowerPlant extends Binder {

 private final PriorityDump.PriorityDumper mPriorityDumper = new PriorityDump.PriorityDumper() {

     @Override
     public void dumpCritical(FileDescriptor fd, PrintWriter pw, String[] args) {
       pw.println("Donuts in the box: 1");
     }

     @Override
     public void dumpNormal(FileDescriptor fd, PrintWriter pw, String[] args) {
       pw.println("Nuclear reactor status: DANGER - MELTDOWN IMMINENT");
     }
  };

  @Override
  protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
      PriorityDump.dump(mPriorityDumper, fd, pw, args);
  }
}

 * 
* * Disclaimer: a real-life service should prioritize core status over donuts :-) * *

Then to invoke it: * *


 *
    $ adb shell dumpsys snpp
    Donuts in the box: 1
    Nuclear reactor status: DANGER - MELTDOWN IMMINENT

    $ adb shell dumpsys snpp --dump_priority CRITICAL
    Donuts in the box: 1

    $ adb shell dumpsys snpp --dump_priority NORMAL
    Nuclear reactor status: DANGER - MELTDOWN IMMINENT

 * 
* * * *

To run the unit tests: *


 *
 mmm -j32 frameworks/base/services/tests/servicestests/ && \
 adb install -r -g ${ANDROID_PRODUCT_OUT}/data/app/FrameworksServicesTests/FrameworksServicesTests.apk && \
 adb shell am instrument -e class "com.android.server.utils.PriorityDumpTest" \
 -w "com.android.frameworks.servicestests/android.support.test.runner.AndroidJUnitRunner"

 * 
* * * @hide */ public final class PriorityDump { public static final String PRIORITY_ARG = "--dump_priority"; private PriorityDump() { throw new UnsupportedOperationException(); } /** * Parses {@code} and call the proper {@link PriorityDumper} method when the first argument is * {@code --dump_priority}, stripping the priority and its type. *

* For example, if called as {@code --dump_priority HIGH arg1 arg2 arg3}, it will call * dumper.dumpHigh(fd, pw, {"arg1", "arg2", "arg3"}) *

* If the {@code --dump_priority} is not set, it calls * {@link PriorityDumper#dump(FileDescriptor, PrintWriter, String[])} 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]; switch (priority) { case "CRITICAL": { dumper.dumpCritical(fd, pw, getStrippedArgs(args)); return; } case "HIGH": { dumper.dumpHigh(fd, pw, getStrippedArgs(args)); return; } case "NORMAL": { dumper.dumpNormal(fd, pw, getStrippedArgs(args)); return; } } } dumper.dump(fd, pw, args); } /** * Gets an array without the {@code --dump_priority PRIORITY} prefix. */ private static String[] getStrippedArgs(String[] args) { final String[] stripped = new String[args.length - 2]; System.arraycopy(args, 2, stripped, 0, stripped.length); return stripped; } /** * Helper for {@link android.os.Binder#dump(java.io.FileDescriptor, String[])} that supports the * {@link #PRIORITY_ARG} argument. * * @hide */ public static interface PriorityDumper { /** * Dumps only the critical section. */ @SuppressWarnings("unused") default void dumpCritical(FileDescriptor fd, PrintWriter pw, String[] args) { } /** * Dumps only the high-priority section. */ @SuppressWarnings("unused") default void dumpHigh(FileDescriptor fd, PrintWriter pw, String[] args) { } /** * Dumps only the normal section. */ @SuppressWarnings("unused") default void dumpNormal(FileDescriptor fd, PrintWriter pw, String[] args) { } /** * Dumps all sections. *

* 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. */ @SuppressWarnings("unused") default void dump(FileDescriptor fd, PrintWriter pw, String[] args) { dumpCritical(fd, pw, args); dumpHigh(fd, pw, args); dumpNormal(fd, pw, args); } } }