Home | History | Annotate | Download | only in am
      1 /*
      2 **
      3 ** Copyright 2007, The Android Open Source Project
      4 **
      5 ** Licensed under the Apache License, Version 2.0 (the "License");
      6 ** you may not use this file except in compliance with the License.
      7 ** You may obtain a copy of the License at
      8 **
      9 **     http://www.apache.org/licenses/LICENSE-2.0
     10 **
     11 ** Unless required by applicable law or agreed to in writing, software
     12 ** distributed under the License is distributed on an "AS IS" BASIS,
     13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14 ** See the License for the specific language governing permissions and
     15 ** limitations under the License.
     16 */
     17 
     18 
     19 package com.android.commands.am;
     20 
     21 import android.app.ActivityManager;
     22 import android.app.ActivityManager.StackInfo;
     23 import android.app.ActivityManagerNative;
     24 import android.app.IActivityContainer;
     25 import android.app.IActivityController;
     26 import android.app.IActivityManager;
     27 import android.app.IInstrumentationWatcher;
     28 import android.app.Instrumentation;
     29 import android.app.ProfilerInfo;
     30 import android.app.UiAutomationConnection;
     31 import android.app.usage.ConfigurationStats;
     32 import android.app.usage.IUsageStatsManager;
     33 import android.app.usage.UsageStatsManager;
     34 import android.content.ComponentName;
     35 import android.content.Context;
     36 import android.content.IIntentReceiver;
     37 import android.content.Intent;
     38 import android.content.pm.IPackageManager;
     39 import android.content.pm.ParceledListSlice;
     40 import android.content.pm.ResolveInfo;
     41 import android.content.res.Configuration;
     42 import android.graphics.Rect;
     43 import android.net.Uri;
     44 import android.os.Binder;
     45 import android.os.Build;
     46 import android.os.Bundle;
     47 import android.os.IBinder;
     48 import android.os.ParcelFileDescriptor;
     49 import android.os.RemoteException;
     50 import android.os.SELinux;
     51 import android.os.ServiceManager;
     52 import android.os.SystemClock;
     53 import android.os.SystemProperties;
     54 import android.os.UserHandle;
     55 import android.text.TextUtils;
     56 import android.util.AndroidException;
     57 import android.util.ArrayMap;
     58 import android.view.IWindowManager;
     59 
     60 import com.android.internal.os.BaseCommand;
     61 
     62 import java.io.BufferedReader;
     63 import java.io.File;
     64 import java.io.FileNotFoundException;
     65 import java.io.IOException;
     66 import java.io.InputStreamReader;
     67 import java.io.PrintStream;
     68 import java.net.URISyntaxException;
     69 import java.util.ArrayList;
     70 import java.util.Collections;
     71 import java.util.Comparator;
     72 import java.util.HashSet;
     73 import java.util.List;
     74 
     75 public class Am extends BaseCommand {
     76 
     77     private IActivityManager mAm;
     78 
     79     private int mStartFlags = 0;
     80     private boolean mWaitOption = false;
     81     private boolean mStopOption = false;
     82 
     83     private int mRepeat = 0;
     84     private int mUserId;
     85     private String mReceiverPermission;
     86 
     87     private String mProfileFile;
     88     private int mSamplingInterval;
     89     private boolean mAutoStop;
     90 
     91     /**
     92      * Command-line entry point.
     93      *
     94      * @param args The command-line arguments
     95      */
     96     public static void main(String[] args) {
     97         (new Am()).run(args);
     98     }
     99 
    100     @Override
    101     public void onShowUsage(PrintStream out) {
    102         out.println(
    103                 "usage: am [subcommand] [options]\n" +
    104                 "usage: am start [-D] [-W] [-P <FILE>] [--start-profiler <FILE>]\n" +
    105                 "               [--sampling INTERVAL] [-R COUNT] [-S] [--opengl-trace]\n" +
    106                 "               [--user <USER_ID> | current] <INTENT>\n" +
    107                 "       am startservice [--user <USER_ID> | current] <INTENT>\n" +
    108                 "       am stopservice [--user <USER_ID> | current] <INTENT>\n" +
    109                 "       am force-stop [--user <USER_ID> | all | current] <PACKAGE>\n" +
    110                 "       am kill [--user <USER_ID> | all | current] <PACKAGE>\n" +
    111                 "       am kill-all\n" +
    112                 "       am broadcast [--user <USER_ID> | all | current] <INTENT>\n" +
    113                 "       am instrument [-r] [-e <NAME> <VALUE>] [-p <FILE>] [-w]\n" +
    114                 "               [--user <USER_ID> | current]\n" +
    115                 "               [--no-window-animation] [--abi <ABI>] <COMPONENT>\n" +
    116                 "       am profile start [--user <USER_ID> current] <PROCESS> <FILE>\n" +
    117                 "       am profile stop [--user <USER_ID> current] [<PROCESS>]\n" +
    118                 "       am dumpheap [--user <USER_ID> current] [-n] <PROCESS> <FILE>\n" +
    119                 "       am set-debug-app [-w] [--persistent] <PACKAGE>\n" +
    120                 "       am clear-debug-app\n" +
    121                 "       am monitor [--gdb <port>]\n" +
    122                 "       am hang [--allow-restart]\n" +
    123                 "       am restart\n" +
    124                 "       am idle-maintenance\n" +
    125                 "       am screen-compat [on|off] <PACKAGE>\n" +
    126                 "       am to-uri [INTENT]\n" +
    127                 "       am to-intent-uri [INTENT]\n" +
    128                 "       am to-app-uri [INTENT]\n" +
    129                 "       am switch-user <USER_ID>\n" +
    130                 "       am start-user <USER_ID>\n" +
    131                 "       am stop-user <USER_ID>\n" +
    132                 "       am stack start <DISPLAY_ID> <INTENT>\n" +
    133                 "       am stack movetask <TASK_ID> <STACK_ID> [true|false]\n" +
    134                 "       am stack resize <STACK_ID> <LEFT,TOP,RIGHT,BOTTOM>\n" +
    135                 "       am stack list\n" +
    136                 "       am stack info <STACK_ID>\n" +
    137                 "       am lock-task <TASK_ID>\n" +
    138                 "       am lock-task stop\n" +
    139                 "       am get-config\n" +
    140                 "\n" +
    141                 "am start: start an Activity.  Options are:\n" +
    142                 "    -D: enable debugging\n" +
    143                 "    -W: wait for launch to complete\n" +
    144                 "    --start-profiler <FILE>: start profiler and send results to <FILE>\n" +
    145                 "    --sampling INTERVAL: use sample profiling with INTERVAL microseconds\n" +
    146                 "        between samples (use with --start-profiler)\n" +
    147                 "    -P <FILE>: like above, but profiling stops when app goes idle\n" +
    148                 "    -R: repeat the activity launch <COUNT> times.  Prior to each repeat,\n" +
    149                 "        the top activity will be finished.\n" +
    150                 "    -S: force stop the target app before starting the activity\n" +
    151                 "    --opengl-trace: enable tracing of OpenGL functions\n" +
    152                 "    --user <USER_ID> | current: Specify which user to run as; if not\n" +
    153                 "        specified then run as the current user.\n" +
    154                 "\n" +
    155                 "am startservice: start a Service.  Options are:\n" +
    156                 "    --user <USER_ID> | current: Specify which user to run as; if not\n" +
    157                 "        specified then run as the current user.\n" +
    158                 "\n" +
    159                 "am stopservice: stop a Service.  Options are:\n" +
    160                 "    --user <USER_ID> | current: Specify which user to run as; if not\n" +
    161                 "        specified then run as the current user.\n" +
    162                 "\n" +
    163                 "am force-stop: force stop everything associated with <PACKAGE>.\n" +
    164                 "    --user <USER_ID> | all | current: Specify user to force stop;\n" +
    165                 "        all users if not specified.\n" +
    166                 "\n" +
    167                 "am kill: Kill all processes associated with <PACKAGE>.  Only kills.\n" +
    168                 "  processes that are safe to kill -- that is, will not impact the user\n" +
    169                 "  experience.\n" +
    170                 "    --user <USER_ID> | all | current: Specify user whose processes to kill;\n" +
    171                 "        all users if not specified.\n" +
    172                 "\n" +
    173                 "am kill-all: Kill all background processes.\n" +
    174                 "\n" +
    175                 "am broadcast: send a broadcast Intent.  Options are:\n" +
    176                 "    --user <USER_ID> | all | current: Specify which user to send to; if not\n" +
    177                 "        specified then send to all users.\n" +
    178                 "    --receiver-permission <PERMISSION>: Require receiver to hold permission.\n" +
    179                 "\n" +
    180                 "am instrument: start an Instrumentation.  Typically this target <COMPONENT>\n" +
    181                 "  is the form <TEST_PACKAGE>/<RUNNER_CLASS>.  Options are:\n" +
    182                 "    -r: print raw results (otherwise decode REPORT_KEY_STREAMRESULT).  Use with\n" +
    183                 "        [-e perf true] to generate raw output for performance measurements.\n" +
    184                 "    -e <NAME> <VALUE>: set argument <NAME> to <VALUE>.  For test runners a\n" +
    185                 "        common form is [-e <testrunner_flag> <value>[,<value>...]].\n" +
    186                 "    -p <FILE>: write profiling data to <FILE>\n" +
    187                 "    -w: wait for instrumentation to finish before returning.  Required for\n" +
    188                 "        test runners.\n" +
    189                 "    --user <USER_ID> | current: Specify user instrumentation runs in;\n" +
    190                 "        current user if not specified.\n" +
    191                 "    --no-window-animation: turn off window animations while running.\n" +
    192                 "    --abi <ABI>: Launch the instrumented process with the selected ABI.\n"  +
    193                 "        This assumes that the process supports the selected ABI.\n" +
    194                 "\n" +
    195                 "am profile: start and stop profiler on a process.  The given <PROCESS> argument\n" +
    196                 "  may be either a process name or pid.  Options are:\n" +
    197                 "    --user <USER_ID> | current: When supplying a process name,\n" +
    198                 "        specify user of process to profile; uses current user if not specified.\n" +
    199                 "\n" +
    200                 "am dumpheap: dump the heap of a process.  The given <PROCESS> argument may\n" +
    201                 "  be either a process name or pid.  Options are:\n" +
    202                 "    -n: dump native heap instead of managed heap\n" +
    203                 "    --user <USER_ID> | current: When supplying a process name,\n" +
    204                 "        specify user of process to dump; uses current user if not specified.\n" +
    205                 "\n" +
    206                 "am set-debug-app: set application <PACKAGE> to debug.  Options are:\n" +
    207                 "    -w: wait for debugger when application starts\n" +
    208                 "    --persistent: retain this value\n" +
    209                 "\n" +
    210                 "am clear-debug-app: clear the previously set-debug-app.\n" +
    211                 "\n" +
    212                 "am bug-report: request bug report generation; will launch UI\n" +
    213                 "    when done to select where it should be delivered.\n" +
    214                 "\n" +
    215                 "am monitor: start monitoring for crashes or ANRs.\n" +
    216                 "    --gdb: start gdbserv on the given port at crash/ANR\n" +
    217                 "\n" +
    218                 "am hang: hang the system.\n" +
    219                 "    --allow-restart: allow watchdog to perform normal system restart\n" +
    220                 "\n" +
    221                 "am restart: restart the user-space system.\n" +
    222                 "\n" +
    223                 "am idle-maintenance: perform idle maintenance now.\n" +
    224                 "\n" +
    225                 "am screen-compat: control screen compatibility mode of <PACKAGE>.\n" +
    226                 "\n" +
    227                 "am to-uri: print the given Intent specification as a URI.\n" +
    228                 "\n" +
    229                 "am to-intent-uri: print the given Intent specification as an intent: URI.\n" +
    230                 "\n" +
    231                 "am to-app-uri: print the given Intent specification as an android-app: URI.\n" +
    232                 "\n" +
    233                 "am switch-user: switch to put USER_ID in the foreground, starting\n" +
    234                 "  execution of that user if it is currently stopped.\n" +
    235                 "\n" +
    236                 "am start-user: start USER_ID in background if it is currently stopped,\n" +
    237                 "  use switch-user if you want to start the user in foreground.\n" +
    238                 "\n" +
    239                 "am stop-user: stop execution of USER_ID, not allowing it to run any\n" +
    240                 "  code until a later explicit start or switch to it.\n" +
    241                 "\n" +
    242                 "am stack start: start a new activity on <DISPLAY_ID> using <INTENT>.\n" +
    243                 "\n" +
    244                 "am stack movetask: move <TASK_ID> from its current stack to the top (true) or" +
    245                 "   bottom (false) of <STACK_ID>.\n" +
    246                 "\n" +
    247                 "am stack resize: change <STACK_ID> size and position to <LEFT,TOP,RIGHT,BOTTOM>.\n" +
    248                 "\n" +
    249                 "am stack list: list all of the activity stacks and their sizes.\n" +
    250                 "\n" +
    251                 "am stack info: display the information about activity stack <STACK_ID>.\n" +
    252                 "\n" +
    253                 "am lock-task: bring <TASK_ID> to the front and don't allow other tasks to run\n" +
    254                 "\n" +
    255                 "am get-config: retrieve the configuration and any recent configurations\n" +
    256                 "  of the device\n" +
    257                 "\n" +
    258                 "<INTENT> specifications include these flags and arguments:\n" +
    259                 "    [-a <ACTION>] [-d <DATA_URI>] [-t <MIME_TYPE>]\n" +
    260                 "    [-c <CATEGORY> [-c <CATEGORY>] ...]\n" +
    261                 "    [-e|--es <EXTRA_KEY> <EXTRA_STRING_VALUE> ...]\n" +
    262                 "    [--esn <EXTRA_KEY> ...]\n" +
    263                 "    [--ez <EXTRA_KEY> <EXTRA_BOOLEAN_VALUE> ...]\n" +
    264                 "    [--ei <EXTRA_KEY> <EXTRA_INT_VALUE> ...]\n" +
    265                 "    [--el <EXTRA_KEY> <EXTRA_LONG_VALUE> ...]\n" +
    266                 "    [--ef <EXTRA_KEY> <EXTRA_FLOAT_VALUE> ...]\n" +
    267                 "    [--eu <EXTRA_KEY> <EXTRA_URI_VALUE> ...]\n" +
    268                 "    [--ecn <EXTRA_KEY> <EXTRA_COMPONENT_NAME_VALUE>]\n" +
    269                 "    [--eia <EXTRA_KEY> <EXTRA_INT_VALUE>[,<EXTRA_INT_VALUE...]]\n" +
    270                 "    [--ela <EXTRA_KEY> <EXTRA_LONG_VALUE>[,<EXTRA_LONG_VALUE...]]\n" +
    271                 "    [--efa <EXTRA_KEY> <EXTRA_FLOAT_VALUE>[,<EXTRA_FLOAT_VALUE...]]\n" +
    272                 "    [--esa <EXTRA_KEY> <EXTRA_STRING_VALUE>[,<EXTRA_STRING_VALUE...]]\n" +
    273                 "        (to embed a comma into a string escape it using \"\\,\")\n" +
    274                 "    [-n <COMPONENT>] [-p <PACKAGE>] [-f <FLAGS>]\n" +
    275                 "    [--grant-read-uri-permission] [--grant-write-uri-permission]\n" +
    276                 "    [--grant-persistable-uri-permission] [--grant-prefix-uri-permission]\n" +
    277                 "    [--debug-log-resolution] [--exclude-stopped-packages]\n" +
    278                 "    [--include-stopped-packages]\n" +
    279                 "    [--activity-brought-to-front] [--activity-clear-top]\n" +
    280                 "    [--activity-clear-when-task-reset] [--activity-exclude-from-recents]\n" +
    281                 "    [--activity-launched-from-history] [--activity-multiple-task]\n" +
    282                 "    [--activity-no-animation] [--activity-no-history]\n" +
    283                 "    [--activity-no-user-action] [--activity-previous-is-top]\n" +
    284                 "    [--activity-reorder-to-front] [--activity-reset-task-if-needed]\n" +
    285                 "    [--activity-single-top] [--activity-clear-task]\n" +
    286                 "    [--activity-task-on-home]\n" +
    287                 "    [--receiver-registered-only] [--receiver-replace-pending]\n" +
    288                 "    [--selector]\n" +
    289                 "    [<URI> | <PACKAGE> | <COMPONENT>]\n"
    290                 );
    291     }
    292 
    293     @Override
    294     public void onRun() throws Exception {
    295 
    296         mAm = ActivityManagerNative.getDefault();
    297         if (mAm == null) {
    298             System.err.println(NO_SYSTEM_ERROR_CODE);
    299             throw new AndroidException("Can't connect to activity manager; is the system running?");
    300         }
    301 
    302         String op = nextArgRequired();
    303 
    304         if (op.equals("start")) {
    305             runStart();
    306         } else if (op.equals("startservice")) {
    307             runStartService();
    308         } else if (op.equals("stopservice")) {
    309             runStopService();
    310         } else if (op.equals("force-stop")) {
    311             runForceStop();
    312         } else if (op.equals("kill")) {
    313             runKill();
    314         } else if (op.equals("kill-all")) {
    315             runKillAll();
    316         } else if (op.equals("instrument")) {
    317             runInstrument();
    318         } else if (op.equals("broadcast")) {
    319             sendBroadcast();
    320         } else if (op.equals("profile")) {
    321             runProfile();
    322         } else if (op.equals("dumpheap")) {
    323             runDumpHeap();
    324         } else if (op.equals("set-debug-app")) {
    325             runSetDebugApp();
    326         } else if (op.equals("clear-debug-app")) {
    327             runClearDebugApp();
    328         } else if (op.equals("bug-report")) {
    329             runBugReport();
    330         } else if (op.equals("monitor")) {
    331             runMonitor();
    332         } else if (op.equals("hang")) {
    333             runHang();
    334         } else if (op.equals("restart")) {
    335             runRestart();
    336         } else if (op.equals("idle-maintenance")) {
    337             runIdleMaintenance();
    338         } else if (op.equals("screen-compat")) {
    339             runScreenCompat();
    340         } else if (op.equals("to-uri")) {
    341             runToUri(0);
    342         } else if (op.equals("to-intent-uri")) {
    343             runToUri(Intent.URI_INTENT_SCHEME);
    344         } else if (op.equals("to-app-uri")) {
    345             runToUri(Intent.URI_ANDROID_APP_SCHEME);
    346         } else if (op.equals("switch-user")) {
    347             runSwitchUser();
    348         } else if (op.equals("start-user")) {
    349             runStartUserInBackground();
    350         } else if (op.equals("stop-user")) {
    351             runStopUser();
    352         } else if (op.equals("stack")) {
    353             runStack();
    354         } else if (op.equals("lock-task")) {
    355             runLockTask();
    356         } else if (op.equals("get-config")) {
    357             runGetConfig();
    358         } else {
    359             showError("Error: unknown command '" + op + "'");
    360         }
    361     }
    362 
    363     int parseUserArg(String arg) {
    364         int userId;
    365         if ("all".equals(arg)) {
    366             userId = UserHandle.USER_ALL;
    367         } else if ("current".equals(arg) || "cur".equals(arg)) {
    368             userId = UserHandle.USER_CURRENT;
    369         } else {
    370             userId = Integer.parseInt(arg);
    371         }
    372         return userId;
    373     }
    374 
    375     private Intent makeIntent(int defUser) throws URISyntaxException {
    376         Intent intent = new Intent();
    377         Intent baseIntent = intent;
    378         boolean hasIntentInfo = false;
    379 
    380         mStartFlags = 0;
    381         mWaitOption = false;
    382         mStopOption = false;
    383         mRepeat = 0;
    384         mProfileFile = null;
    385         mSamplingInterval = 0;
    386         mAutoStop = false;
    387         mUserId = defUser;
    388         Uri data = null;
    389         String type = null;
    390 
    391         String opt;
    392         while ((opt=nextOption()) != null) {
    393             if (opt.equals("-a")) {
    394                 intent.setAction(nextArgRequired());
    395                 if (intent == baseIntent) {
    396                     hasIntentInfo = true;
    397                 }
    398             } else if (opt.equals("-d")) {
    399                 data = Uri.parse(nextArgRequired());
    400                 if (intent == baseIntent) {
    401                     hasIntentInfo = true;
    402                 }
    403             } else if (opt.equals("-t")) {
    404                 type = nextArgRequired();
    405                 if (intent == baseIntent) {
    406                     hasIntentInfo = true;
    407                 }
    408             } else if (opt.equals("-c")) {
    409                 intent.addCategory(nextArgRequired());
    410                 if (intent == baseIntent) {
    411                     hasIntentInfo = true;
    412                 }
    413             } else if (opt.equals("-e") || opt.equals("--es")) {
    414                 String key = nextArgRequired();
    415                 String value = nextArgRequired();
    416                 intent.putExtra(key, value);
    417             } else if (opt.equals("--esn")) {
    418                 String key = nextArgRequired();
    419                 intent.putExtra(key, (String) null);
    420             } else if (opt.equals("--ei")) {
    421                 String key = nextArgRequired();
    422                 String value = nextArgRequired();
    423                 intent.putExtra(key, Integer.decode(value));
    424             } else if (opt.equals("--eu")) {
    425                 String key = nextArgRequired();
    426                 String value = nextArgRequired();
    427                 intent.putExtra(key, Uri.parse(value));
    428             } else if (opt.equals("--ecn")) {
    429                 String key = nextArgRequired();
    430                 String value = nextArgRequired();
    431                 ComponentName cn = ComponentName.unflattenFromString(value);
    432                 if (cn == null) throw new IllegalArgumentException("Bad component name: " + value);
    433                 intent.putExtra(key, cn);
    434             } else if (opt.equals("--eia")) {
    435                 String key = nextArgRequired();
    436                 String value = nextArgRequired();
    437                 String[] strings = value.split(",");
    438                 int[] list = new int[strings.length];
    439                 for (int i = 0; i < strings.length; i++) {
    440                     list[i] = Integer.decode(strings[i]);
    441                 }
    442                 intent.putExtra(key, list);
    443             } else if (opt.equals("--el")) {
    444                 String key = nextArgRequired();
    445                 String value = nextArgRequired();
    446                 intent.putExtra(key, Long.valueOf(value));
    447             } else if (opt.equals("--ela")) {
    448                 String key = nextArgRequired();
    449                 String value = nextArgRequired();
    450                 String[] strings = value.split(",");
    451                 long[] list = new long[strings.length];
    452                 for (int i = 0; i < strings.length; i++) {
    453                     list[i] = Long.valueOf(strings[i]);
    454                 }
    455                 intent.putExtra(key, list);
    456                 hasIntentInfo = true;
    457             } else if (opt.equals("--ef")) {
    458                 String key = nextArgRequired();
    459                 String value = nextArgRequired();
    460                 intent.putExtra(key, Float.valueOf(value));
    461                 hasIntentInfo = true;
    462             } else if (opt.equals("--efa")) {
    463                 String key = nextArgRequired();
    464                 String value = nextArgRequired();
    465                 String[] strings = value.split(",");
    466                 float[] list = new float[strings.length];
    467                 for (int i = 0; i < strings.length; i++) {
    468                     list[i] = Float.valueOf(strings[i]);
    469                 }
    470                 intent.putExtra(key, list);
    471                 hasIntentInfo = true;
    472             } else if (opt.equals("--esa")) {
    473                 String key = nextArgRequired();
    474                 String value = nextArgRequired();
    475                 // Split on commas unless they are preceeded by an escape.
    476                 // The escape character must be escaped for the string and
    477                 // again for the regex, thus four escape characters become one.
    478                 String[] strings = value.split("(?<!\\\\),");
    479                 intent.putExtra(key, strings);
    480                 hasIntentInfo = true;
    481             } else if (opt.equals("--ez")) {
    482                 String key = nextArgRequired();
    483                 String value = nextArgRequired().toLowerCase();
    484                 // Boolean.valueOf() results in false for anything that is not "true", which is
    485                 // error-prone in shell commands
    486                 boolean arg;
    487                 if ("true".equals(value) || "t".equals(value)) {
    488                     arg = true;
    489                 } else if ("false".equals(value) || "f".equals(value)) {
    490                     arg = false;
    491                 } else {
    492                     try {
    493                         arg = Integer.decode(value) != 0;
    494                     } catch (NumberFormatException ex) {
    495                         throw new IllegalArgumentException("Invalid boolean value: " + value);
    496                     }
    497                 }
    498 
    499                 intent.putExtra(key, arg);
    500             } else if (opt.equals("-n")) {
    501                 String str = nextArgRequired();
    502                 ComponentName cn = ComponentName.unflattenFromString(str);
    503                 if (cn == null) throw new IllegalArgumentException("Bad component name: " + str);
    504                 intent.setComponent(cn);
    505                 if (intent == baseIntent) {
    506                     hasIntentInfo = true;
    507                 }
    508             } else if (opt.equals("-p")) {
    509                 String str = nextArgRequired();
    510                 intent.setPackage(str);
    511                 if (intent == baseIntent) {
    512                     hasIntentInfo = true;
    513                 }
    514             } else if (opt.equals("-f")) {
    515                 String str = nextArgRequired();
    516                 intent.setFlags(Integer.decode(str).intValue());
    517             } else if (opt.equals("--grant-read-uri-permission")) {
    518                 intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
    519             } else if (opt.equals("--grant-write-uri-permission")) {
    520                 intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
    521             } else if (opt.equals("--grant-persistable-uri-permission")) {
    522                 intent.addFlags(Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION);
    523             } else if (opt.equals("--grant-prefix-uri-permission")) {
    524                 intent.addFlags(Intent.FLAG_GRANT_PREFIX_URI_PERMISSION);
    525             } else if (opt.equals("--exclude-stopped-packages")) {
    526                 intent.addFlags(Intent.FLAG_EXCLUDE_STOPPED_PACKAGES);
    527             } else if (opt.equals("--include-stopped-packages")) {
    528                 intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
    529             } else if (opt.equals("--debug-log-resolution")) {
    530                 intent.addFlags(Intent.FLAG_DEBUG_LOG_RESOLUTION);
    531             } else if (opt.equals("--activity-brought-to-front")) {
    532                 intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
    533             } else if (opt.equals("--activity-clear-top")) {
    534                 intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
    535             } else if (opt.equals("--activity-clear-when-task-reset")) {
    536                 intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
    537             } else if (opt.equals("--activity-exclude-from-recents")) {
    538                 intent.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
    539             } else if (opt.equals("--activity-launched-from-history")) {
    540                 intent.addFlags(Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY);
    541             } else if (opt.equals("--activity-multiple-task")) {
    542                 intent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
    543             } else if (opt.equals("--activity-no-animation")) {
    544                 intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
    545             } else if (opt.equals("--activity-no-history")) {
    546                 intent.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
    547             } else if (opt.equals("--activity-no-user-action")) {
    548                 intent.addFlags(Intent.FLAG_ACTIVITY_NO_USER_ACTION);
    549             } else if (opt.equals("--activity-previous-is-top")) {
    550                 intent.addFlags(Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP);
    551             } else if (opt.equals("--activity-reorder-to-front")) {
    552                 intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
    553             } else if (opt.equals("--activity-reset-task-if-needed")) {
    554                 intent.addFlags(Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
    555             } else if (opt.equals("--activity-single-top")) {
    556                 intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
    557             } else if (opt.equals("--activity-clear-task")) {
    558                 intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
    559             } else if (opt.equals("--activity-task-on-home")) {
    560                 intent.addFlags(Intent.FLAG_ACTIVITY_TASK_ON_HOME);
    561             } else if (opt.equals("--receiver-registered-only")) {
    562                 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
    563             } else if (opt.equals("--receiver-replace-pending")) {
    564                 intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
    565             } else if (opt.equals("--selector")) {
    566                 intent.setDataAndType(data, type);
    567                 intent = new Intent();
    568             } else if (opt.equals("-D")) {
    569                 mStartFlags |= ActivityManager.START_FLAG_DEBUG;
    570             } else if (opt.equals("-W")) {
    571                 mWaitOption = true;
    572             } else if (opt.equals("-P")) {
    573                 mProfileFile = nextArgRequired();
    574                 mAutoStop = true;
    575             } else if (opt.equals("--start-profiler")) {
    576                 mProfileFile = nextArgRequired();
    577                 mAutoStop = false;
    578             } else if (opt.equals("--sampling")) {
    579                 mSamplingInterval = Integer.parseInt(nextArgRequired());
    580             } else if (opt.equals("-R")) {
    581                 mRepeat = Integer.parseInt(nextArgRequired());
    582             } else if (opt.equals("-S")) {
    583                 mStopOption = true;
    584             } else if (opt.equals("--opengl-trace")) {
    585                 mStartFlags |= ActivityManager.START_FLAG_OPENGL_TRACES;
    586             } else if (opt.equals("--user")) {
    587                 mUserId = parseUserArg(nextArgRequired());
    588             } else if (opt.equals("--receiver-permission")) {
    589                 mReceiverPermission = nextArgRequired();
    590             } else {
    591                 System.err.println("Error: Unknown option: " + opt);
    592                 return null;
    593             }
    594         }
    595         intent.setDataAndType(data, type);
    596 
    597         final boolean hasSelector = intent != baseIntent;
    598         if (hasSelector) {
    599             // A selector was specified; fix up.
    600             baseIntent.setSelector(intent);
    601             intent = baseIntent;
    602         }
    603 
    604         String arg = nextArg();
    605         baseIntent = null;
    606         if (arg == null) {
    607             if (hasSelector) {
    608                 // If a selector has been specified, and no arguments
    609                 // have been supplied for the main Intent, then we can
    610                 // assume it is ACTION_MAIN CATEGORY_LAUNCHER; we don't
    611                 // need to have a component name specified yet, the
    612                 // selector will take care of that.
    613                 baseIntent = new Intent(Intent.ACTION_MAIN);
    614                 baseIntent.addCategory(Intent.CATEGORY_LAUNCHER);
    615             }
    616         } else if (arg.indexOf(':') >= 0) {
    617             // The argument is a URI.  Fully parse it, and use that result
    618             // to fill in any data not specified so far.
    619             baseIntent = Intent.parseUri(arg, Intent.URI_INTENT_SCHEME
    620                     | Intent.URI_ANDROID_APP_SCHEME | Intent.URI_ALLOW_UNSAFE);
    621         } else if (arg.indexOf('/') >= 0) {
    622             // The argument is a component name.  Build an Intent to launch
    623             // it.
    624             baseIntent = new Intent(Intent.ACTION_MAIN);
    625             baseIntent.addCategory(Intent.CATEGORY_LAUNCHER);
    626             baseIntent.setComponent(ComponentName.unflattenFromString(arg));
    627         } else {
    628             // Assume the argument is a package name.
    629             baseIntent = new Intent(Intent.ACTION_MAIN);
    630             baseIntent.addCategory(Intent.CATEGORY_LAUNCHER);
    631             baseIntent.setPackage(arg);
    632         }
    633         if (baseIntent != null) {
    634             Bundle extras = intent.getExtras();
    635             intent.replaceExtras((Bundle)null);
    636             Bundle uriExtras = baseIntent.getExtras();
    637             baseIntent.replaceExtras((Bundle)null);
    638             if (intent.getAction() != null && baseIntent.getCategories() != null) {
    639                 HashSet<String> cats = new HashSet<String>(baseIntent.getCategories());
    640                 for (String c : cats) {
    641                     baseIntent.removeCategory(c);
    642                 }
    643             }
    644             intent.fillIn(baseIntent, Intent.FILL_IN_COMPONENT | Intent.FILL_IN_SELECTOR);
    645             if (extras == null) {
    646                 extras = uriExtras;
    647             } else if (uriExtras != null) {
    648                 uriExtras.putAll(extras);
    649                 extras = uriExtras;
    650             }
    651             intent.replaceExtras(extras);
    652             hasIntentInfo = true;
    653         }
    654 
    655         if (!hasIntentInfo) throw new IllegalArgumentException("No intent supplied");
    656         return intent;
    657     }
    658 
    659     private void runStartService() throws Exception {
    660         Intent intent = makeIntent(UserHandle.USER_CURRENT);
    661         if (mUserId == UserHandle.USER_ALL) {
    662             System.err.println("Error: Can't start activity with user 'all'");
    663             return;
    664         }
    665         System.out.println("Starting service: " + intent);
    666         ComponentName cn = mAm.startService(null, intent, intent.getType(), mUserId);
    667         if (cn == null) {
    668             System.err.println("Error: Not found; no service started.");
    669         } else if (cn.getPackageName().equals("!")) {
    670             System.err.println("Error: Requires permission " + cn.getClassName());
    671         } else if (cn.getPackageName().equals("!!")) {
    672             System.err.println("Error: " + cn.getClassName());
    673         }
    674     }
    675 
    676     private void runStopService() throws Exception {
    677         Intent intent = makeIntent(UserHandle.USER_CURRENT);
    678         if (mUserId == UserHandle.USER_ALL) {
    679             System.err.println("Error: Can't stop activity with user 'all'");
    680             return;
    681         }
    682         System.out.println("Stopping service: " + intent);
    683         int result = mAm.stopService(null, intent, intent.getType(), mUserId);
    684         if (result == 0) {
    685             System.err.println("Service not stopped: was not running.");
    686         } else if (result == 1) {
    687             System.err.println("Service stopped");
    688         } else if (result == -1) {
    689             System.err.println("Error stopping service");
    690         }
    691     }
    692 
    693     private void runStart() throws Exception {
    694         Intent intent = makeIntent(UserHandle.USER_CURRENT);
    695 
    696         if (mUserId == UserHandle.USER_ALL) {
    697             System.err.println("Error: Can't start service with user 'all'");
    698             return;
    699         }
    700 
    701         String mimeType = intent.getType();
    702         if (mimeType == null && intent.getData() != null
    703                 && "content".equals(intent.getData().getScheme())) {
    704             mimeType = mAm.getProviderMimeType(intent.getData(), mUserId);
    705         }
    706 
    707         do {
    708             if (mStopOption) {
    709                 String packageName;
    710                 if (intent.getComponent() != null) {
    711                     packageName = intent.getComponent().getPackageName();
    712                 } else {
    713                     IPackageManager pm = IPackageManager.Stub.asInterface(
    714                             ServiceManager.getService("package"));
    715                     if (pm == null) {
    716                         System.err.println("Error: Package manager not running; aborting");
    717                         return;
    718                     }
    719                     List<ResolveInfo> activities = pm.queryIntentActivities(intent, mimeType, 0,
    720                             mUserId);
    721                     if (activities == null || activities.size() <= 0) {
    722                         System.err.println("Error: Intent does not match any activities: "
    723                                 + intent);
    724                         return;
    725                     } else if (activities.size() > 1) {
    726                         System.err.println("Error: Intent matches multiple activities; can't stop: "
    727                                 + intent);
    728                         return;
    729                     }
    730                     packageName = activities.get(0).activityInfo.packageName;
    731                 }
    732                 System.out.println("Stopping: " + packageName);
    733                 mAm.forceStopPackage(packageName, mUserId);
    734                 Thread.sleep(250);
    735             }
    736 
    737             System.out.println("Starting: " + intent);
    738             intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    739 
    740             ParcelFileDescriptor fd = null;
    741             ProfilerInfo profilerInfo = null;
    742 
    743             if (mProfileFile != null) {
    744                 try {
    745                     fd = openForSystemServer(
    746                             new File(mProfileFile),
    747                             ParcelFileDescriptor.MODE_CREATE |
    748                             ParcelFileDescriptor.MODE_TRUNCATE |
    749                             ParcelFileDescriptor.MODE_READ_WRITE);
    750                 } catch (FileNotFoundException e) {
    751                     System.err.println("Error: Unable to open file: " + mProfileFile);
    752                     System.err.println("Consider using a file under /data/local/tmp/");
    753                     return;
    754                 }
    755                 profilerInfo = new ProfilerInfo(mProfileFile, fd, mSamplingInterval, mAutoStop);
    756             }
    757 
    758             IActivityManager.WaitResult result = null;
    759             int res;
    760             final long startTime = SystemClock.uptimeMillis();
    761             if (mWaitOption) {
    762                 result = mAm.startActivityAndWait(null, null, intent, mimeType,
    763                             null, null, 0, mStartFlags, profilerInfo, null, mUserId);
    764                 res = result.result;
    765             } else {
    766                 res = mAm.startActivityAsUser(null, null, intent, mimeType,
    767                         null, null, 0, mStartFlags, profilerInfo, null, mUserId);
    768             }
    769             final long endTime = SystemClock.uptimeMillis();
    770             PrintStream out = mWaitOption ? System.out : System.err;
    771             boolean launched = false;
    772             switch (res) {
    773                 case ActivityManager.START_SUCCESS:
    774                     launched = true;
    775                     break;
    776                 case ActivityManager.START_SWITCHES_CANCELED:
    777                     launched = true;
    778                     out.println(
    779                             "Warning: Activity not started because the "
    780                             + " current activity is being kept for the user.");
    781                     break;
    782                 case ActivityManager.START_DELIVERED_TO_TOP:
    783                     launched = true;
    784                     out.println(
    785                             "Warning: Activity not started, intent has "
    786                             + "been delivered to currently running "
    787                             + "top-most instance.");
    788                     break;
    789                 case ActivityManager.START_RETURN_INTENT_TO_CALLER:
    790                     launched = true;
    791                     out.println(
    792                             "Warning: Activity not started because intent "
    793                             + "should be handled by the caller");
    794                     break;
    795                 case ActivityManager.START_TASK_TO_FRONT:
    796                     launched = true;
    797                     out.println(
    798                             "Warning: Activity not started, its current "
    799                             + "task has been brought to the front");
    800                     break;
    801                 case ActivityManager.START_INTENT_NOT_RESOLVED:
    802                     out.println(
    803                             "Error: Activity not started, unable to "
    804                             + "resolve " + intent.toString());
    805                     break;
    806                 case ActivityManager.START_CLASS_NOT_FOUND:
    807                     out.println(NO_CLASS_ERROR_CODE);
    808                     out.println("Error: Activity class " +
    809                             intent.getComponent().toShortString()
    810                             + " does not exist.");
    811                     break;
    812                 case ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT:
    813                     out.println(
    814                             "Error: Activity not started, you requested to "
    815                             + "both forward and receive its result");
    816                     break;
    817                 case ActivityManager.START_PERMISSION_DENIED:
    818                     out.println(
    819                             "Error: Activity not started, you do not "
    820                             + "have permission to access it.");
    821                     break;
    822                 case ActivityManager.START_NOT_VOICE_COMPATIBLE:
    823                     out.println(
    824                             "Error: Activity not started, voice control not allowed for: "
    825                                     + intent);
    826                     break;
    827                 default:
    828                     out.println(
    829                             "Error: Activity not started, unknown error code " + res);
    830                     break;
    831             }
    832             if (mWaitOption && launched) {
    833                 if (result == null) {
    834                     result = new IActivityManager.WaitResult();
    835                     result.who = intent.getComponent();
    836                 }
    837                 System.out.println("Status: " + (result.timeout ? "timeout" : "ok"));
    838                 if (result.who != null) {
    839                     System.out.println("Activity: " + result.who.flattenToShortString());
    840                 }
    841                 if (result.thisTime >= 0) {
    842                     System.out.println("ThisTime: " + result.thisTime);
    843                 }
    844                 if (result.totalTime >= 0) {
    845                     System.out.println("TotalTime: " + result.totalTime);
    846                 }
    847                 System.out.println("WaitTime: " + (endTime-startTime));
    848                 System.out.println("Complete");
    849             }
    850             mRepeat--;
    851             if (mRepeat > 1) {
    852                 mAm.unhandledBack();
    853             }
    854         } while (mRepeat > 1);
    855     }
    856 
    857     private void runForceStop() throws Exception {
    858         int userId = UserHandle.USER_ALL;
    859 
    860         String opt;
    861         while ((opt=nextOption()) != null) {
    862             if (opt.equals("--user")) {
    863                 userId = parseUserArg(nextArgRequired());
    864             } else {
    865                 System.err.println("Error: Unknown option: " + opt);
    866                 return;
    867             }
    868         }
    869         mAm.forceStopPackage(nextArgRequired(), userId);
    870     }
    871 
    872     private void runKill() throws Exception {
    873         int userId = UserHandle.USER_ALL;
    874 
    875         String opt;
    876         while ((opt=nextOption()) != null) {
    877             if (opt.equals("--user")) {
    878                 userId = parseUserArg(nextArgRequired());
    879             } else {
    880                 System.err.println("Error: Unknown option: " + opt);
    881                 return;
    882             }
    883         }
    884         mAm.killBackgroundProcesses(nextArgRequired(), userId);
    885     }
    886 
    887     private void runKillAll() throws Exception {
    888         mAm.killAllBackgroundProcesses();
    889     }
    890 
    891     private void sendBroadcast() throws Exception {
    892         Intent intent = makeIntent(UserHandle.USER_CURRENT);
    893         IntentReceiver receiver = new IntentReceiver();
    894         System.out.println("Broadcasting: " + intent);
    895         mAm.broadcastIntent(null, intent, null, receiver, 0, null, null, mReceiverPermission,
    896                 android.app.AppOpsManager.OP_NONE, true, false, mUserId);
    897         receiver.waitForFinish();
    898     }
    899 
    900     private void runInstrument() throws Exception {
    901         String profileFile = null;
    902         boolean wait = false;
    903         boolean rawMode = false;
    904         boolean no_window_animation = false;
    905         int userId = UserHandle.USER_CURRENT;
    906         Bundle args = new Bundle();
    907         String argKey = null, argValue = null;
    908         IWindowManager wm = IWindowManager.Stub.asInterface(ServiceManager.getService("window"));
    909         String abi = null;
    910 
    911         String opt;
    912         while ((opt=nextOption()) != null) {
    913             if (opt.equals("-p")) {
    914                 profileFile = nextArgRequired();
    915             } else if (opt.equals("-w")) {
    916                 wait = true;
    917             } else if (opt.equals("-r")) {
    918                 rawMode = true;
    919             } else if (opt.equals("-e")) {
    920                 argKey = nextArgRequired();
    921                 argValue = nextArgRequired();
    922                 args.putString(argKey, argValue);
    923             } else if (opt.equals("--no_window_animation")
    924                     || opt.equals("--no-window-animation")) {
    925                 no_window_animation = true;
    926             } else if (opt.equals("--user")) {
    927                 userId = parseUserArg(nextArgRequired());
    928             } else if (opt.equals("--abi")) {
    929                 abi = nextArgRequired();
    930             } else {
    931                 System.err.println("Error: Unknown option: " + opt);
    932                 return;
    933             }
    934         }
    935 
    936         if (userId == UserHandle.USER_ALL) {
    937             System.err.println("Error: Can't start instrumentation with user 'all'");
    938             return;
    939         }
    940 
    941         String cnArg = nextArgRequired();
    942         ComponentName cn = ComponentName.unflattenFromString(cnArg);
    943         if (cn == null) throw new IllegalArgumentException("Bad component name: " + cnArg);
    944 
    945         InstrumentationWatcher watcher = null;
    946         UiAutomationConnection connection = null;
    947         if (wait) {
    948             watcher = new InstrumentationWatcher();
    949             watcher.setRawOutput(rawMode);
    950             connection = new UiAutomationConnection();
    951         }
    952 
    953         float[] oldAnims = null;
    954         if (no_window_animation) {
    955             oldAnims = wm.getAnimationScales();
    956             wm.setAnimationScale(0, 0.0f);
    957             wm.setAnimationScale(1, 0.0f);
    958         }
    959 
    960         if (abi != null) {
    961             final String[] supportedAbis = Build.SUPPORTED_ABIS;
    962             boolean matched = false;
    963             for (String supportedAbi : supportedAbis) {
    964                 if (supportedAbi.equals(abi)) {
    965                     matched = true;
    966                     break;
    967                 }
    968             }
    969 
    970             if (!matched) {
    971                 throw new AndroidException(
    972                         "INSTRUMENTATION_FAILED: Unsupported instruction set " + abi);
    973             }
    974         }
    975 
    976         if (!mAm.startInstrumentation(cn, profileFile, 0, args, watcher, connection, userId, abi)) {
    977             throw new AndroidException("INSTRUMENTATION_FAILED: " + cn.flattenToString());
    978         }
    979 
    980         if (watcher != null) {
    981             if (!watcher.waitForFinish()) {
    982                 System.out.println("INSTRUMENTATION_ABORTED: System has crashed.");
    983             }
    984         }
    985 
    986         if (oldAnims != null) {
    987             wm.setAnimationScales(oldAnims);
    988         }
    989     }
    990 
    991     static void removeWallOption() {
    992         String props = SystemProperties.get("dalvik.vm.extra-opts");
    993         if (props != null && props.contains("-Xprofile:wallclock")) {
    994             props = props.replace("-Xprofile:wallclock", "");
    995             props = props.trim();
    996             SystemProperties.set("dalvik.vm.extra-opts", props);
    997         }
    998     }
    999 
   1000     private void runProfile() throws Exception {
   1001         String profileFile = null;
   1002         boolean start = false;
   1003         boolean wall = false;
   1004         int userId = UserHandle.USER_CURRENT;
   1005         int profileType = 0;
   1006 
   1007         String process = null;
   1008 
   1009         String cmd = nextArgRequired();
   1010 
   1011         if ("start".equals(cmd)) {
   1012             start = true;
   1013             String opt;
   1014             while ((opt=nextOption()) != null) {
   1015                 if (opt.equals("--user")) {
   1016                     userId = parseUserArg(nextArgRequired());
   1017                 } else if (opt.equals("--wall")) {
   1018                     wall = true;
   1019                 } else {
   1020                     System.err.println("Error: Unknown option: " + opt);
   1021                     return;
   1022                 }
   1023             }
   1024             process = nextArgRequired();
   1025         } else if ("stop".equals(cmd)) {
   1026             String opt;
   1027             while ((opt=nextOption()) != null) {
   1028                 if (opt.equals("--user")) {
   1029                     userId = parseUserArg(nextArgRequired());
   1030                 } else {
   1031                     System.err.println("Error: Unknown option: " + opt);
   1032                     return;
   1033                 }
   1034             }
   1035             process = nextArg();
   1036         } else {
   1037             // Compatibility with old syntax: process is specified first.
   1038             process = cmd;
   1039             cmd = nextArgRequired();
   1040             if ("start".equals(cmd)) {
   1041                 start = true;
   1042             } else if (!"stop".equals(cmd)) {
   1043                 throw new IllegalArgumentException("Profile command " + process + " not valid");
   1044             }
   1045         }
   1046 
   1047         if (userId == UserHandle.USER_ALL) {
   1048             System.err.println("Error: Can't profile with user 'all'");
   1049             return;
   1050         }
   1051 
   1052         ParcelFileDescriptor fd = null;
   1053         ProfilerInfo profilerInfo = null;
   1054 
   1055         if (start) {
   1056             profileFile = nextArgRequired();
   1057             try {
   1058                 fd = openForSystemServer(
   1059                         new File(profileFile),
   1060                         ParcelFileDescriptor.MODE_CREATE |
   1061                         ParcelFileDescriptor.MODE_TRUNCATE |
   1062                         ParcelFileDescriptor.MODE_READ_WRITE);
   1063             } catch (FileNotFoundException e) {
   1064                 System.err.println("Error: Unable to open file: " + profileFile);
   1065                 System.err.println("Consider using a file under /data/local/tmp/");
   1066                 return;
   1067             }
   1068             profilerInfo = new ProfilerInfo(profileFile, fd, 0, false);
   1069         }
   1070 
   1071         try {
   1072             if (wall) {
   1073                 // XXX doesn't work -- this needs to be set before booting.
   1074                 String props = SystemProperties.get("dalvik.vm.extra-opts");
   1075                 if (props == null || !props.contains("-Xprofile:wallclock")) {
   1076                     props = props + " -Xprofile:wallclock";
   1077                     //SystemProperties.set("dalvik.vm.extra-opts", props);
   1078                 }
   1079             } else if (start) {
   1080                 //removeWallOption();
   1081             }
   1082             if (!mAm.profileControl(process, userId, start, profilerInfo, profileType)) {
   1083                 wall = false;
   1084                 throw new AndroidException("PROFILE FAILED on process " + process);
   1085             }
   1086         } finally {
   1087             if (!wall) {
   1088                 //removeWallOption();
   1089             }
   1090         }
   1091     }
   1092 
   1093     private void runDumpHeap() throws Exception {
   1094         boolean managed = true;
   1095         int userId = UserHandle.USER_CURRENT;
   1096 
   1097         String opt;
   1098         while ((opt=nextOption()) != null) {
   1099             if (opt.equals("--user")) {
   1100                 userId = parseUserArg(nextArgRequired());
   1101                 if (userId == UserHandle.USER_ALL) {
   1102                     System.err.println("Error: Can't dump heap with user 'all'");
   1103                     return;
   1104                 }
   1105             } else if (opt.equals("-n")) {
   1106                 managed = false;
   1107             } else {
   1108                 System.err.println("Error: Unknown option: " + opt);
   1109                 return;
   1110             }
   1111         }
   1112         String process = nextArgRequired();
   1113         String heapFile = nextArgRequired();
   1114         ParcelFileDescriptor fd = null;
   1115 
   1116         try {
   1117             File file = new File(heapFile);
   1118             file.delete();
   1119             fd = openForSystemServer(file,
   1120                     ParcelFileDescriptor.MODE_CREATE |
   1121                     ParcelFileDescriptor.MODE_TRUNCATE |
   1122                     ParcelFileDescriptor.MODE_READ_WRITE);
   1123         } catch (FileNotFoundException e) {
   1124             System.err.println("Error: Unable to open file: " + heapFile);
   1125             System.err.println("Consider using a file under /data/local/tmp/");
   1126             return;
   1127         }
   1128 
   1129         if (!mAm.dumpHeap(process, userId, managed, heapFile, fd)) {
   1130             throw new AndroidException("HEAP DUMP FAILED on process " + process);
   1131         }
   1132     }
   1133 
   1134     private void runSetDebugApp() throws Exception {
   1135         boolean wait = false;
   1136         boolean persistent = false;
   1137 
   1138         String opt;
   1139         while ((opt=nextOption()) != null) {
   1140             if (opt.equals("-w")) {
   1141                 wait = true;
   1142             } else if (opt.equals("--persistent")) {
   1143                 persistent = true;
   1144             } else {
   1145                 System.err.println("Error: Unknown option: " + opt);
   1146                 return;
   1147             }
   1148         }
   1149 
   1150         String pkg = nextArgRequired();
   1151         mAm.setDebugApp(pkg, wait, persistent);
   1152     }
   1153 
   1154     private void runClearDebugApp() throws Exception {
   1155         mAm.setDebugApp(null, false, true);
   1156     }
   1157 
   1158     private void runBugReport() throws Exception {
   1159         mAm.requestBugReport();
   1160         System.out.println("Your lovely bug report is being created; please be patient.");
   1161     }
   1162 
   1163     private void runSwitchUser() throws Exception {
   1164         String user = nextArgRequired();
   1165         mAm.switchUser(Integer.parseInt(user));
   1166     }
   1167 
   1168     private void runStartUserInBackground() throws Exception {
   1169         String user = nextArgRequired();
   1170         boolean success = mAm.startUserInBackground(Integer.parseInt(user));
   1171         if (success) {
   1172             System.out.println("Success: user started");
   1173         } else {
   1174             System.err.println("Error: could not start user");
   1175         }
   1176     }
   1177 
   1178     private void runStopUser() throws Exception {
   1179         String user = nextArgRequired();
   1180         int res = mAm.stopUser(Integer.parseInt(user), null);
   1181         if (res != ActivityManager.USER_OP_SUCCESS) {
   1182             String txt = "";
   1183             switch (res) {
   1184                 case ActivityManager.USER_OP_IS_CURRENT:
   1185                     txt = " (Can't stop current user)";
   1186                     break;
   1187                 case ActivityManager.USER_OP_UNKNOWN_USER:
   1188                     txt = " (Unknown user " + user + ")";
   1189                     break;
   1190             }
   1191             System.err.println("Switch failed: " + res + txt);
   1192         }
   1193     }
   1194 
   1195     class MyActivityController extends IActivityController.Stub {
   1196         final String mGdbPort;
   1197 
   1198         static final int STATE_NORMAL = 0;
   1199         static final int STATE_CRASHED = 1;
   1200         static final int STATE_EARLY_ANR = 2;
   1201         static final int STATE_ANR = 3;
   1202 
   1203         int mState;
   1204 
   1205         static final int RESULT_DEFAULT = 0;
   1206 
   1207         static final int RESULT_CRASH_DIALOG = 0;
   1208         static final int RESULT_CRASH_KILL = 1;
   1209 
   1210         static final int RESULT_EARLY_ANR_CONTINUE = 0;
   1211         static final int RESULT_EARLY_ANR_KILL = 1;
   1212 
   1213         static final int RESULT_ANR_DIALOG = 0;
   1214         static final int RESULT_ANR_KILL = 1;
   1215         static final int RESULT_ANR_WAIT = 1;
   1216 
   1217         int mResult;
   1218 
   1219         Process mGdbProcess;
   1220         Thread mGdbThread;
   1221         boolean mGotGdbPrint;
   1222 
   1223         MyActivityController(String gdbPort) {
   1224             mGdbPort = gdbPort;
   1225         }
   1226 
   1227         @Override
   1228         public boolean activityResuming(String pkg) {
   1229             synchronized (this) {
   1230                 System.out.println("** Activity resuming: " + pkg);
   1231             }
   1232             return true;
   1233         }
   1234 
   1235         @Override
   1236         public boolean activityStarting(Intent intent, String pkg) {
   1237             synchronized (this) {
   1238                 System.out.println("** Activity starting: " + pkg);
   1239             }
   1240             return true;
   1241         }
   1242 
   1243         @Override
   1244         public boolean appCrashed(String processName, int pid, String shortMsg, String longMsg,
   1245                 long timeMillis, String stackTrace) {
   1246             synchronized (this) {
   1247                 System.out.println("** ERROR: PROCESS CRASHED");
   1248                 System.out.println("processName: " + processName);
   1249                 System.out.println("processPid: " + pid);
   1250                 System.out.println("shortMsg: " + shortMsg);
   1251                 System.out.println("longMsg: " + longMsg);
   1252                 System.out.println("timeMillis: " + timeMillis);
   1253                 System.out.println("stack:");
   1254                 System.out.print(stackTrace);
   1255                 System.out.println("#");
   1256                 int result = waitControllerLocked(pid, STATE_CRASHED);
   1257                 return result == RESULT_CRASH_KILL ? false : true;
   1258             }
   1259         }
   1260 
   1261         @Override
   1262         public int appEarlyNotResponding(String processName, int pid, String annotation) {
   1263             synchronized (this) {
   1264                 System.out.println("** ERROR: EARLY PROCESS NOT RESPONDING");
   1265                 System.out.println("processName: " + processName);
   1266                 System.out.println("processPid: " + pid);
   1267                 System.out.println("annotation: " + annotation);
   1268                 int result = waitControllerLocked(pid, STATE_EARLY_ANR);
   1269                 if (result == RESULT_EARLY_ANR_KILL) return -1;
   1270                 return 0;
   1271             }
   1272         }
   1273 
   1274         @Override
   1275         public int appNotResponding(String processName, int pid, String processStats) {
   1276             synchronized (this) {
   1277                 System.out.println("** ERROR: PROCESS NOT RESPONDING");
   1278                 System.out.println("processName: " + processName);
   1279                 System.out.println("processPid: " + pid);
   1280                 System.out.println("processStats:");
   1281                 System.out.print(processStats);
   1282                 System.out.println("#");
   1283                 int result = waitControllerLocked(pid, STATE_ANR);
   1284                 if (result == RESULT_ANR_KILL) return -1;
   1285                 if (result == RESULT_ANR_WAIT) return 1;
   1286                 return 0;
   1287             }
   1288         }
   1289 
   1290         @Override
   1291         public int systemNotResponding(String message) {
   1292             synchronized (this) {
   1293                 System.out.println("** ERROR: PROCESS NOT RESPONDING");
   1294                 System.out.println("message: " + message);
   1295                 System.out.println("#");
   1296                 System.out.println("Allowing system to die.");
   1297                 return -1;
   1298             }
   1299         }
   1300 
   1301         void killGdbLocked() {
   1302             mGotGdbPrint = false;
   1303             if (mGdbProcess != null) {
   1304                 System.out.println("Stopping gdbserver");
   1305                 mGdbProcess.destroy();
   1306                 mGdbProcess = null;
   1307             }
   1308             if (mGdbThread != null) {
   1309                 mGdbThread.interrupt();
   1310                 mGdbThread = null;
   1311             }
   1312         }
   1313 
   1314         int waitControllerLocked(int pid, int state) {
   1315             if (mGdbPort != null) {
   1316                 killGdbLocked();
   1317 
   1318                 try {
   1319                     System.out.println("Starting gdbserver on port " + mGdbPort);
   1320                     System.out.println("Do the following:");
   1321                     System.out.println("  adb forward tcp:" + mGdbPort + " tcp:" + mGdbPort);
   1322                     System.out.println("  gdbclient app_process :" + mGdbPort);
   1323 
   1324                     mGdbProcess = Runtime.getRuntime().exec(new String[] {
   1325                             "gdbserver", ":" + mGdbPort, "--attach", Integer.toString(pid)
   1326                     });
   1327                     final InputStreamReader converter = new InputStreamReader(
   1328                             mGdbProcess.getInputStream());
   1329                     mGdbThread = new Thread() {
   1330                         @Override
   1331                         public void run() {
   1332                             BufferedReader in = new BufferedReader(converter);
   1333                             String line;
   1334                             int count = 0;
   1335                             while (true) {
   1336                                 synchronized (MyActivityController.this) {
   1337                                     if (mGdbThread == null) {
   1338                                         return;
   1339                                     }
   1340                                     if (count == 2) {
   1341                                         mGotGdbPrint = true;
   1342                                         MyActivityController.this.notifyAll();
   1343                                     }
   1344                                 }
   1345                                 try {
   1346                                     line = in.readLine();
   1347                                     if (line == null) {
   1348                                         return;
   1349                                     }
   1350                                     System.out.println("GDB: " + line);
   1351                                     count++;
   1352                                 } catch (IOException e) {
   1353                                     return;
   1354                                 }
   1355                             }
   1356                         }
   1357                     };
   1358                     mGdbThread.start();
   1359 
   1360                     // Stupid waiting for .5s.  Doesn't matter if we end early.
   1361                     try {
   1362                         this.wait(500);
   1363                     } catch (InterruptedException e) {
   1364                     }
   1365 
   1366                 } catch (IOException e) {
   1367                     System.err.println("Failure starting gdbserver: " + e);
   1368                     killGdbLocked();
   1369                 }
   1370             }
   1371             mState = state;
   1372             System.out.println("");
   1373             printMessageForState();
   1374 
   1375             while (mState != STATE_NORMAL) {
   1376                 try {
   1377                     wait();
   1378                 } catch (InterruptedException e) {
   1379                 }
   1380             }
   1381 
   1382             killGdbLocked();
   1383 
   1384             return mResult;
   1385         }
   1386 
   1387         void resumeController(int result) {
   1388             synchronized (this) {
   1389                 mState = STATE_NORMAL;
   1390                 mResult = result;
   1391                 notifyAll();
   1392             }
   1393         }
   1394 
   1395         void printMessageForState() {
   1396             switch (mState) {
   1397                 case STATE_NORMAL:
   1398                     System.out.println("Monitoring activity manager...  available commands:");
   1399                     break;
   1400                 case STATE_CRASHED:
   1401                     System.out.println("Waiting after crash...  available commands:");
   1402                     System.out.println("(c)ontinue: show crash dialog");
   1403                     System.out.println("(k)ill: immediately kill app");
   1404                     break;
   1405                 case STATE_EARLY_ANR:
   1406                     System.out.println("Waiting after early ANR...  available commands:");
   1407                     System.out.println("(c)ontinue: standard ANR processing");
   1408                     System.out.println("(k)ill: immediately kill app");
   1409                     break;
   1410                 case STATE_ANR:
   1411                     System.out.println("Waiting after ANR...  available commands:");
   1412                     System.out.println("(c)ontinue: show ANR dialog");
   1413                     System.out.println("(k)ill: immediately kill app");
   1414                     System.out.println("(w)ait: wait some more");
   1415                     break;
   1416             }
   1417             System.out.println("(q)uit: finish monitoring");
   1418         }
   1419 
   1420         void run() throws RemoteException {
   1421             try {
   1422                 printMessageForState();
   1423 
   1424                 mAm.setActivityController(this);
   1425                 mState = STATE_NORMAL;
   1426 
   1427                 InputStreamReader converter = new InputStreamReader(System.in);
   1428                 BufferedReader in = new BufferedReader(converter);
   1429                 String line;
   1430 
   1431                 while ((line = in.readLine()) != null) {
   1432                     boolean addNewline = true;
   1433                     if (line.length() <= 0) {
   1434                         addNewline = false;
   1435                     } else if ("q".equals(line) || "quit".equals(line)) {
   1436                         resumeController(RESULT_DEFAULT);
   1437                         break;
   1438                     } else if (mState == STATE_CRASHED) {
   1439                         if ("c".equals(line) || "continue".equals(line)) {
   1440                             resumeController(RESULT_CRASH_DIALOG);
   1441                         } else if ("k".equals(line) || "kill".equals(line)) {
   1442                             resumeController(RESULT_CRASH_KILL);
   1443                         } else {
   1444                             System.out.println("Invalid command: " + line);
   1445                         }
   1446                     } else if (mState == STATE_ANR) {
   1447                         if ("c".equals(line) || "continue".equals(line)) {
   1448                             resumeController(RESULT_ANR_DIALOG);
   1449                         } else if ("k".equals(line) || "kill".equals(line)) {
   1450                             resumeController(RESULT_ANR_KILL);
   1451                         } else if ("w".equals(line) || "wait".equals(line)) {
   1452                             resumeController(RESULT_ANR_WAIT);
   1453                         } else {
   1454                             System.out.println("Invalid command: " + line);
   1455                         }
   1456                     } else if (mState == STATE_EARLY_ANR) {
   1457                         if ("c".equals(line) || "continue".equals(line)) {
   1458                             resumeController(RESULT_EARLY_ANR_CONTINUE);
   1459                         } else if ("k".equals(line) || "kill".equals(line)) {
   1460                             resumeController(RESULT_EARLY_ANR_KILL);
   1461                         } else {
   1462                             System.out.println("Invalid command: " + line);
   1463                         }
   1464                     } else {
   1465                         System.out.println("Invalid command: " + line);
   1466                     }
   1467 
   1468                     synchronized (this) {
   1469                         if (addNewline) {
   1470                             System.out.println("");
   1471                         }
   1472                         printMessageForState();
   1473                     }
   1474                 }
   1475 
   1476             } catch (IOException e) {
   1477                 e.printStackTrace();
   1478             } finally {
   1479                 mAm.setActivityController(null);
   1480             }
   1481         }
   1482     }
   1483 
   1484     private void runMonitor() throws Exception {
   1485         String opt;
   1486         String gdbPort = null;
   1487         while ((opt=nextOption()) != null) {
   1488             if (opt.equals("--gdb")) {
   1489                 gdbPort = nextArgRequired();
   1490             } else {
   1491                 System.err.println("Error: Unknown option: " + opt);
   1492                 return;
   1493             }
   1494         }
   1495 
   1496         MyActivityController controller = new MyActivityController(gdbPort);
   1497         controller.run();
   1498     }
   1499 
   1500     private void runHang() throws Exception {
   1501         String opt;
   1502         boolean allowRestart = false;
   1503         while ((opt=nextOption()) != null) {
   1504             if (opt.equals("--allow-restart")) {
   1505                 allowRestart = true;
   1506             } else {
   1507                 System.err.println("Error: Unknown option: " + opt);
   1508                 return;
   1509             }
   1510         }
   1511 
   1512         System.out.println("Hanging the system...");
   1513         mAm.hang(new Binder(), allowRestart);
   1514     }
   1515 
   1516     private void runRestart() throws Exception {
   1517         String opt;
   1518         while ((opt=nextOption()) != null) {
   1519             System.err.println("Error: Unknown option: " + opt);
   1520             return;
   1521         }
   1522 
   1523         System.out.println("Restart the system...");
   1524         mAm.restart();
   1525     }
   1526 
   1527     private void runIdleMaintenance() throws Exception {
   1528         String opt;
   1529         while ((opt=nextOption()) != null) {
   1530             System.err.println("Error: Unknown option: " + opt);
   1531             return;
   1532         }
   1533 
   1534         System.out.println("Performing idle maintenance...");
   1535         Intent intent = new Intent(
   1536                 "com.android.server.task.controllers.IdleController.ACTION_TRIGGER_IDLE");
   1537         mAm.broadcastIntent(null, intent, null, null, 0, null, null, null,
   1538                 android.app.AppOpsManager.OP_NONE, true, false, UserHandle.USER_ALL);
   1539     }
   1540 
   1541     private void runScreenCompat() throws Exception {
   1542         String mode = nextArgRequired();
   1543         boolean enabled;
   1544         if ("on".equals(mode)) {
   1545             enabled = true;
   1546         } else if ("off".equals(mode)) {
   1547             enabled = false;
   1548         } else {
   1549             System.err.println("Error: enabled mode must be 'on' or 'off' at " + mode);
   1550             return;
   1551         }
   1552 
   1553         String packageName = nextArgRequired();
   1554         do {
   1555             try {
   1556                 mAm.setPackageScreenCompatMode(packageName, enabled
   1557                         ? ActivityManager.COMPAT_MODE_ENABLED
   1558                         : ActivityManager.COMPAT_MODE_DISABLED);
   1559             } catch (RemoteException e) {
   1560             }
   1561             packageName = nextArg();
   1562         } while (packageName != null);
   1563     }
   1564 
   1565     private void runToUri(int flags) throws Exception {
   1566         Intent intent = makeIntent(UserHandle.USER_CURRENT);
   1567         System.out.println(intent.toUri(flags));
   1568     }
   1569 
   1570     private class IntentReceiver extends IIntentReceiver.Stub {
   1571         private boolean mFinished = false;
   1572 
   1573         @Override
   1574         public void performReceive(Intent intent, int resultCode, String data, Bundle extras,
   1575                 boolean ordered, boolean sticky, int sendingUser) {
   1576             String line = "Broadcast completed: result=" + resultCode;
   1577             if (data != null) line = line + ", data=\"" + data + "\"";
   1578             if (extras != null) line = line + ", extras: " + extras;
   1579             System.out.println(line);
   1580             synchronized (this) {
   1581               mFinished = true;
   1582               notifyAll();
   1583             }
   1584         }
   1585 
   1586         public synchronized void waitForFinish() {
   1587             try {
   1588                 while (!mFinished) wait();
   1589             } catch (InterruptedException e) {
   1590                 throw new IllegalStateException(e);
   1591             }
   1592         }
   1593     }
   1594 
   1595     private class InstrumentationWatcher extends IInstrumentationWatcher.Stub {
   1596         private boolean mFinished = false;
   1597         private boolean mRawMode = false;
   1598 
   1599         /**
   1600          * Set or reset "raw mode".  In "raw mode", all bundles are dumped.  In "pretty mode",
   1601          * if a bundle includes Instrumentation.REPORT_KEY_STREAMRESULT, just print that.
   1602          * @param rawMode true for raw mode, false for pretty mode.
   1603          */
   1604         public void setRawOutput(boolean rawMode) {
   1605             mRawMode = rawMode;
   1606         }
   1607 
   1608         @Override
   1609         public void instrumentationStatus(ComponentName name, int resultCode, Bundle results) {
   1610             synchronized (this) {
   1611                 // pretty printer mode?
   1612                 String pretty = null;
   1613                 if (!mRawMode && results != null) {
   1614                     pretty = results.getString(Instrumentation.REPORT_KEY_STREAMRESULT);
   1615                 }
   1616                 if (pretty != null) {
   1617                     System.out.print(pretty);
   1618                 } else {
   1619                     if (results != null) {
   1620                         for (String key : results.keySet()) {
   1621                             System.out.println(
   1622                                     "INSTRUMENTATION_STATUS: " + key + "=" + results.get(key));
   1623                         }
   1624                     }
   1625                     System.out.println("INSTRUMENTATION_STATUS_CODE: " + resultCode);
   1626                 }
   1627                 notifyAll();
   1628             }
   1629         }
   1630 
   1631         @Override
   1632         public void instrumentationFinished(ComponentName name, int resultCode,
   1633                 Bundle results) {
   1634             synchronized (this) {
   1635                 // pretty printer mode?
   1636                 String pretty = null;
   1637                 if (!mRawMode && results != null) {
   1638                     pretty = results.getString(Instrumentation.REPORT_KEY_STREAMRESULT);
   1639                 }
   1640                 if (pretty != null) {
   1641                     System.out.println(pretty);
   1642                 } else {
   1643                     if (results != null) {
   1644                         for (String key : results.keySet()) {
   1645                             System.out.println(
   1646                                     "INSTRUMENTATION_RESULT: " + key + "=" + results.get(key));
   1647                         }
   1648                     }
   1649                     System.out.println("INSTRUMENTATION_CODE: " + resultCode);
   1650                 }
   1651                 mFinished = true;
   1652                 notifyAll();
   1653             }
   1654         }
   1655 
   1656         public boolean waitForFinish() {
   1657             synchronized (this) {
   1658                 while (!mFinished) {
   1659                     try {
   1660                         if (!mAm.asBinder().pingBinder()) {
   1661                             return false;
   1662                         }
   1663                         wait(1000);
   1664                     } catch (InterruptedException e) {
   1665                         throw new IllegalStateException(e);
   1666                     }
   1667                 }
   1668             }
   1669             return true;
   1670         }
   1671     }
   1672 
   1673     private void runStack() throws Exception {
   1674         String op = nextArgRequired();
   1675         if (op.equals("start")) {
   1676             runStackStart();
   1677         } else if (op.equals("movetask")) {
   1678             runStackMoveTask();
   1679         } else if (op.equals("resize")) {
   1680             runStackResize();
   1681         } else if (op.equals("list")) {
   1682             runStackList();
   1683         } else if (op.equals("info")) {
   1684             runStackInfo();
   1685         } else {
   1686             showError("Error: unknown command '" + op + "'");
   1687             return;
   1688         }
   1689     }
   1690 
   1691     private void runStackStart() throws Exception {
   1692         String displayIdStr = nextArgRequired();
   1693         int displayId = Integer.valueOf(displayIdStr);
   1694         Intent intent = makeIntent(UserHandle.USER_CURRENT);
   1695 
   1696         try {
   1697             IBinder homeActivityToken = mAm.getHomeActivityToken();
   1698             IActivityContainer container = mAm.createActivityContainer(homeActivityToken, null);
   1699             container.attachToDisplay(displayId);
   1700             container.startActivity(intent);
   1701         } catch (RemoteException e) {
   1702         }
   1703     }
   1704 
   1705     private void runStackMoveTask() throws Exception {
   1706         String taskIdStr = nextArgRequired();
   1707         int taskId = Integer.valueOf(taskIdStr);
   1708         String stackIdStr = nextArgRequired();
   1709         int stackId = Integer.valueOf(stackIdStr);
   1710         String toTopStr = nextArgRequired();
   1711         final boolean toTop;
   1712         if ("true".equals(toTopStr)) {
   1713             toTop = true;
   1714         } else if ("false".equals(toTopStr)) {
   1715             toTop = false;
   1716         } else {
   1717             System.err.println("Error: bad toTop arg: " + toTopStr);
   1718             return;
   1719         }
   1720 
   1721         try {
   1722             mAm.moveTaskToStack(taskId, stackId, toTop);
   1723         } catch (RemoteException e) {
   1724         }
   1725     }
   1726 
   1727     private void runStackResize() throws Exception {
   1728         String stackIdStr = nextArgRequired();
   1729         int stackId = Integer.valueOf(stackIdStr);
   1730         String leftStr = nextArgRequired();
   1731         int left = Integer.valueOf(leftStr);
   1732         String topStr = nextArgRequired();
   1733         int top = Integer.valueOf(topStr);
   1734         String rightStr = nextArgRequired();
   1735         int right = Integer.valueOf(rightStr);
   1736         String bottomStr = nextArgRequired();
   1737         int bottom = Integer.valueOf(bottomStr);
   1738 
   1739         try {
   1740             mAm.resizeStack(stackId, new Rect(left, top, right, bottom));
   1741         } catch (RemoteException e) {
   1742         }
   1743     }
   1744 
   1745     private void runStackList() throws Exception {
   1746         try {
   1747             List<StackInfo> stacks = mAm.getAllStackInfos();
   1748             for (StackInfo info : stacks) {
   1749                 System.out.println(info);
   1750             }
   1751         } catch (RemoteException e) {
   1752         }
   1753     }
   1754 
   1755     private void runStackInfo() throws Exception {
   1756         try {
   1757             String stackIdStr = nextArgRequired();
   1758             int stackId = Integer.valueOf(stackIdStr);
   1759             StackInfo info = mAm.getStackInfo(stackId);
   1760             System.out.println(info);
   1761         } catch (RemoteException e) {
   1762         }
   1763     }
   1764 
   1765     private void runLockTask() throws Exception {
   1766         String taskIdStr = nextArgRequired();
   1767         try {
   1768             if (taskIdStr.equals("stop")) {
   1769                 mAm.stopLockTaskMode();
   1770             } else {
   1771                 int taskId = Integer.valueOf(taskIdStr);
   1772                 mAm.startLockTaskMode(taskId);
   1773             }
   1774             System.err.println("Activity manager is " + (mAm.isInLockTaskMode() ? "" : "not ") +
   1775                     "in lockTaskMode");
   1776         } catch (RemoteException e) {
   1777         }
   1778     }
   1779 
   1780     private List<Configuration> getRecentConfigurations(int days) {
   1781         IUsageStatsManager usm = IUsageStatsManager.Stub.asInterface(ServiceManager.getService(
   1782                     Context.USAGE_STATS_SERVICE));
   1783         final long now = System.currentTimeMillis();
   1784         final long nDaysAgo = now - (days * 24 * 60 * 60 * 1000);
   1785         try {
   1786             @SuppressWarnings("unchecked")
   1787             ParceledListSlice<ConfigurationStats> configStatsSlice = usm.queryConfigurationStats(
   1788                     UsageStatsManager.INTERVAL_BEST, nDaysAgo, now, "com.android.shell");
   1789             if (configStatsSlice == null) {
   1790                 return Collections.emptyList();
   1791             }
   1792 
   1793             final ArrayMap<Configuration, Integer> recentConfigs = new ArrayMap<>();
   1794             final List<ConfigurationStats> configStatsList = configStatsSlice.getList();
   1795             final int configStatsListSize = configStatsList.size();
   1796             for (int i = 0; i < configStatsListSize; i++) {
   1797                 final ConfigurationStats stats = configStatsList.get(i);
   1798                 final int indexOfKey = recentConfigs.indexOfKey(stats.getConfiguration());
   1799                 if (indexOfKey < 0) {
   1800                     recentConfigs.put(stats.getConfiguration(), stats.getActivationCount());
   1801                 } else {
   1802                     recentConfigs.setValueAt(indexOfKey,
   1803                             recentConfigs.valueAt(indexOfKey) + stats.getActivationCount());
   1804                 }
   1805             }
   1806 
   1807             final Comparator<Configuration> comparator = new Comparator<Configuration>() {
   1808                 @Override
   1809                 public int compare(Configuration a, Configuration b) {
   1810                     return recentConfigs.get(b).compareTo(recentConfigs.get(a));
   1811                 }
   1812             };
   1813 
   1814             ArrayList<Configuration> configs = new ArrayList<>(recentConfigs.size());
   1815             configs.addAll(recentConfigs.keySet());
   1816             Collections.sort(configs, comparator);
   1817             return configs;
   1818 
   1819         } catch (RemoteException e) {
   1820             return Collections.emptyList();
   1821         }
   1822     }
   1823 
   1824     private void runGetConfig() throws Exception {
   1825         int days = 14;
   1826         String option = nextOption();
   1827         if (option != null) {
   1828             if (!option.equals("--days")) {
   1829                 throw new IllegalArgumentException("unrecognized option " + option);
   1830             }
   1831 
   1832             days = Integer.parseInt(nextArgRequired());
   1833             if (days <= 0) {
   1834                 throw new IllegalArgumentException("--days must be a positive integer");
   1835             }
   1836         }
   1837 
   1838         try {
   1839             Configuration config = mAm.getConfiguration();
   1840             if (config == null) {
   1841                 System.err.println("Activity manager has no configuration");
   1842                 return;
   1843             }
   1844 
   1845             System.out.println("config: " + Configuration.resourceQualifierString(config));
   1846             System.out.println("abi: " + TextUtils.join(",", Build.SUPPORTED_ABIS));
   1847 
   1848             final List<Configuration> recentConfigs = getRecentConfigurations(days);
   1849             final int recentConfigSize = recentConfigs.size();
   1850             if (recentConfigSize > 0) {
   1851                 System.out.println("recentConfigs:");
   1852             }
   1853 
   1854             for (int i = 0; i < recentConfigSize; i++) {
   1855                 System.out.println("  config: " + Configuration.resourceQualifierString(
   1856                         recentConfigs.get(i)));
   1857             }
   1858 
   1859         } catch (RemoteException e) {
   1860         }
   1861     }
   1862 
   1863     /**
   1864      * Open the given file for sending into the system process. This verifies
   1865      * with SELinux that the system will have access to the file.
   1866      */
   1867     private static ParcelFileDescriptor openForSystemServer(File file, int mode)
   1868             throws FileNotFoundException {
   1869         final ParcelFileDescriptor fd = ParcelFileDescriptor.open(file, mode);
   1870         final String tcon = SELinux.getFileContext(file.getAbsolutePath());
   1871         if (!SELinux.checkSELinuxAccess("u:r:system_server:s0", tcon, "file", "read")) {
   1872             throw new FileNotFoundException("System server has no access to file context " + tcon);
   1873         }
   1874         return fd;
   1875     }
   1876 }
   1877