Added --skip option to skip services.

This option will be used by dumpstate so critical services (like meminfo
and cpuinfo) can be dumped earlier on and then skipped later (when the
rest of the services are dumped).

BUG: 26639621
Change-Id: Ied61431c4d03d7d2eb010edd77872fb7e6bae3bd
diff --git a/cmds/dumpsys/dumpsys.cpp b/cmds/dumpsys/dumpsys.cpp
index 1701f53..ef009da 100644
--- a/cmds/dumpsys/dumpsys.cpp
+++ b/cmds/dumpsys/dumpsys.cpp
@@ -31,10 +31,20 @@
         "usage: dumpsys\n"
             "         To dump all services.\n"
             "or:\n"
-            "       dumpsys [--help | -l | SERVICE [ARGS]]\n"
+            "       dumpsys [--help | -l | --skip SERVICES | SERVICE [ARGS]]\n"
             "         --help: shows this help\n"
             "         -l: only list services, do not dump them\n"
-            "         SERVICE: dumps only service SERVICE, optionally passing ARGS to it\n");
+            "         --skip SERVICES: dumps all services but SERVICES (comma-separated list)\n"
+            "         SERVICE [ARGS]: dumps only service SERVICE, optionally passing ARGS to it\n");
+}
+
+bool IsSkipped(const Vector<String16>& skipped, const String16& service) {
+    for (const auto& candidate : skipped) {
+        if (candidate == service) {
+            return true;
+        }
+    }
+    return false;
 }
 
 int main(int argc, char* const argv[])
@@ -50,8 +60,10 @@
 
     Vector<String16> services;
     Vector<String16> args;
+    Vector<String16> skippedServices;
     bool showListOnly = false;
     if (argc == 2) {
+        // 1 argument: check for special cases (-l or --help)
         if (strcmp(argv[1], "--help") == 0) {
             usage();
             return 0;
@@ -60,11 +72,30 @@
             showListOnly = true;
         }
     }
-    if ((argc == 1) || showListOnly) {
+    if (argc == 3) {
+        // 2 arguments: check for special cases (--skip SERVICES)
+        if (strcmp(argv[1], "--skip") == 0) {
+            char* token = strtok(argv[2], ",");
+            while (token != NULL) {
+                skippedServices.add(String16(token));
+                token = strtok(NULL, ",");
+            }
+        }
+    }
+    bool dumpAll = argc == 1;
+    if (dumpAll || !skippedServices.empty() || showListOnly) {
+        // gets all services
         services = sm->listServices();
         services.sort(sort_func);
         args.add(String16("-a"));
     } else {
+        // gets a specific service:
+        // first check if its name is not a special argument...
+        if (strcmp(argv[1], "--skip") == 0 || strcmp(argv[1], "-l") == 0) {
+            usage();
+            return -1;
+        }
+        // ...then gets its arguments
         services.add(String16(argv[1]));
         for (int i=2; i<argc; i++) {
             args.add(String16(argv[i]));
@@ -80,7 +111,8 @@
         for (size_t i=0; i<N; i++) {
             sp<IBinder> service = sm->checkService(services[i]);
             if (service != NULL) {
-                aout << "  " << services[i] << endl;
+                bool skipped = IsSkipped(skippedServices, services[i]);
+                aout << "  " << services[i] << (skipped ? " (skipped)" : "") << endl;
             }
         }
     }
@@ -90,6 +122,8 @@
     }
 
     for (size_t i=0; i<N; i++) {
+        if (IsSkipped(skippedServices, services[i])) continue;
+
         sp<IBinder> service = sm->checkService(services[i]);
         if (service != NULL) {
             if (N > 1) {