Am.java revision 92a8b22e7410e74e1cba1b856333116652af8a5c
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 19package com.android.commands.am; 20 21import android.app.ActivityManager; 22import android.app.ActivityManagerNative; 23import android.app.IActivityController; 24import android.app.IActivityManager; 25import android.app.IInstrumentationWatcher; 26import android.app.Instrumentation; 27import android.content.ComponentName; 28import android.content.Context; 29import android.content.IIntentReceiver; 30import android.content.Intent; 31import android.content.pm.IPackageManager; 32import android.content.pm.ResolveInfo; 33import android.net.Uri; 34import android.os.Binder; 35import android.os.Bundle; 36import android.os.ParcelFileDescriptor; 37import android.os.RemoteException; 38import android.os.ServiceManager; 39import android.os.SystemProperties; 40import android.util.AndroidException; 41import android.view.IWindowManager; 42 43import java.io.BufferedReader; 44import java.io.File; 45import java.io.FileNotFoundException; 46import java.io.IOException; 47import java.io.InputStreamReader; 48import java.io.PrintStream; 49import java.net.URISyntaxException; 50import java.util.HashSet; 51import java.util.List; 52 53public class Am { 54 55 private IActivityManager mAm; 56 private String[] mArgs; 57 private int mNextArg; 58 private String mCurArgData; 59 60 private boolean mDebugOption = false; 61 private boolean mWaitOption = false; 62 private boolean mStopOption = false; 63 64 private boolean mOpenglTraceOption = false; 65 66 private int mRepeat = 0; 67 68 private String mProfileFile; 69 private boolean mProfileAutoStop; 70 71 // These are magic strings understood by the Eclipse plugin. 72 private static final String FATAL_ERROR_CODE = "Error type 1"; 73 private static final String NO_SYSTEM_ERROR_CODE = "Error type 2"; 74 private static final String NO_CLASS_ERROR_CODE = "Error type 3"; 75 76 /** 77 * Command-line entry point. 78 * 79 * @param args The command-line arguments 80 */ 81 public static void main(String[] args) { 82 try { 83 (new Am()).run(args); 84 } catch (IllegalArgumentException e) { 85 showUsage(); 86 System.err.println("Error: " + e.getMessage()); 87 } catch (Exception e) { 88 e.printStackTrace(System.err); 89 System.exit(1); 90 } 91 } 92 93 private void run(String[] args) throws Exception { 94 if (args.length < 1) { 95 showUsage(); 96 return; 97 } 98 99 mAm = ActivityManagerNative.getDefault(); 100 if (mAm == null) { 101 System.err.println(NO_SYSTEM_ERROR_CODE); 102 throw new AndroidException("Can't connect to activity manager; is the system running?"); 103 } 104 105 mArgs = args; 106 String op = args[0]; 107 mNextArg = 1; 108 109 if (op.equals("start")) { 110 runStart(); 111 } else if (op.equals("startservice")) { 112 runStartService(); 113 } else if (op.equals("force-stop")) { 114 runForceStop(); 115 } else if (op.equals("kill")) { 116 runKill(); 117 } else if (op.equals("kill-all")) { 118 runKillAll(); 119 } else if (op.equals("instrument")) { 120 runInstrument(); 121 } else if (op.equals("broadcast")) { 122 sendBroadcast(); 123 } else if (op.equals("profile")) { 124 runProfile(); 125 } else if (op.equals("dumpheap")) { 126 runDumpHeap(); 127 } else if (op.equals("set-debug-app")) { 128 runSetDebugApp(); 129 } else if (op.equals("clear-debug-app")) { 130 runClearDebugApp(); 131 } else if (op.equals("monitor")) { 132 runMonitor(); 133 } else if (op.equals("screen-compat")) { 134 runScreenCompat(); 135 } else if (op.equals("display-size")) { 136 runDisplaySize(); 137 } else if (op.equals("to-uri")) { 138 runToUri(false); 139 } else if (op.equals("to-intent-uri")) { 140 runToUri(true); 141 } else if (op.equals("switch-profile")) { 142 runSwitchUser(); 143 } else { 144 throw new IllegalArgumentException("Unknown command: " + op); 145 } 146 } 147 148 private Intent makeIntent() throws URISyntaxException { 149 Intent intent = new Intent(); 150 Intent baseIntent = intent; 151 boolean hasIntentInfo = false; 152 153 mDebugOption = false; 154 mWaitOption = false; 155 mStopOption = false; 156 mOpenglTraceOption = false; 157 mRepeat = 0; 158 mProfileFile = null; 159 Uri data = null; 160 String type = null; 161 162 String opt; 163 while ((opt=nextOption()) != null) { 164 if (opt.equals("-a")) { 165 intent.setAction(nextArgRequired()); 166 if (intent == baseIntent) { 167 hasIntentInfo = true; 168 } 169 } else if (opt.equals("-d")) { 170 data = Uri.parse(nextArgRequired()); 171 if (intent == baseIntent) { 172 hasIntentInfo = true; 173 } 174 } else if (opt.equals("-t")) { 175 type = nextArgRequired(); 176 if (intent == baseIntent) { 177 hasIntentInfo = true; 178 } 179 } else if (opt.equals("-c")) { 180 intent.addCategory(nextArgRequired()); 181 if (intent == baseIntent) { 182 hasIntentInfo = true; 183 } 184 } else if (opt.equals("-e") || opt.equals("--es")) { 185 String key = nextArgRequired(); 186 String value = nextArgRequired(); 187 intent.putExtra(key, value); 188 } else if (opt.equals("--esn")) { 189 String key = nextArgRequired(); 190 intent.putExtra(key, (String) null); 191 } else if (opt.equals("--ei")) { 192 String key = nextArgRequired(); 193 String value = nextArgRequired(); 194 intent.putExtra(key, Integer.valueOf(value)); 195 } else if (opt.equals("--eu")) { 196 String key = nextArgRequired(); 197 String value = nextArgRequired(); 198 intent.putExtra(key, Uri.parse(value)); 199 } else if (opt.equals("--eia")) { 200 String key = nextArgRequired(); 201 String value = nextArgRequired(); 202 String[] strings = value.split(","); 203 int[] list = new int[strings.length]; 204 for (int i = 0; i < strings.length; i++) { 205 list[i] = Integer.valueOf(strings[i]); 206 } 207 intent.putExtra(key, list); 208 } else if (opt.equals("--el")) { 209 String key = nextArgRequired(); 210 String value = nextArgRequired(); 211 intent.putExtra(key, Long.valueOf(value)); 212 } else if (opt.equals("--ela")) { 213 String key = nextArgRequired(); 214 String value = nextArgRequired(); 215 String[] strings = value.split(","); 216 long[] list = new long[strings.length]; 217 for (int i = 0; i < strings.length; i++) { 218 list[i] = Long.valueOf(strings[i]); 219 } 220 intent.putExtra(key, list); 221 hasIntentInfo = true; 222 } else if (opt.equals("--ef")) { 223 String key = nextArgRequired(); 224 String value = nextArgRequired(); 225 intent.putExtra(key, Float.valueOf(value)); 226 hasIntentInfo = true; 227 } else if (opt.equals("--efa")) { 228 String key = nextArgRequired(); 229 String value = nextArgRequired(); 230 String[] strings = value.split(","); 231 float[] list = new float[strings.length]; 232 for (int i = 0; i < strings.length; i++) { 233 list[i] = Float.valueOf(strings[i]); 234 } 235 intent.putExtra(key, list); 236 hasIntentInfo = true; 237 } else if (opt.equals("--ez")) { 238 String key = nextArgRequired(); 239 String value = nextArgRequired(); 240 intent.putExtra(key, Boolean.valueOf(value)); 241 } else if (opt.equals("-n")) { 242 String str = nextArgRequired(); 243 ComponentName cn = ComponentName.unflattenFromString(str); 244 if (cn == null) throw new IllegalArgumentException("Bad component name: " + str); 245 intent.setComponent(cn); 246 if (intent == baseIntent) { 247 hasIntentInfo = true; 248 } 249 } else if (opt.equals("-f")) { 250 String str = nextArgRequired(); 251 intent.setFlags(Integer.decode(str).intValue()); 252 } else if (opt.equals("--grant-read-uri-permission")) { 253 intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); 254 } else if (opt.equals("--grant-write-uri-permission")) { 255 intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION); 256 } else if (opt.equals("--exclude-stopped-packages")) { 257 intent.addFlags(Intent.FLAG_EXCLUDE_STOPPED_PACKAGES); 258 } else if (opt.equals("--include-stopped-packages")) { 259 intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); 260 } else if (opt.equals("--debug-log-resolution")) { 261 intent.addFlags(Intent.FLAG_DEBUG_LOG_RESOLUTION); 262 } else if (opt.equals("--activity-brought-to-front")) { 263 intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT); 264 } else if (opt.equals("--activity-clear-top")) { 265 intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); 266 } else if (opt.equals("--activity-clear-when-task-reset")) { 267 intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET); 268 } else if (opt.equals("--activity-exclude-from-recents")) { 269 intent.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS); 270 } else if (opt.equals("--activity-launched-from-history")) { 271 intent.addFlags(Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY); 272 } else if (opt.equals("--activity-multiple-task")) { 273 intent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK); 274 } else if (opt.equals("--activity-no-animation")) { 275 intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION); 276 } else if (opt.equals("--activity-no-history")) { 277 intent.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY); 278 } else if (opt.equals("--activity-no-user-action")) { 279 intent.addFlags(Intent.FLAG_ACTIVITY_NO_USER_ACTION); 280 } else if (opt.equals("--activity-previous-is-top")) { 281 intent.addFlags(Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP); 282 } else if (opt.equals("--activity-reorder-to-front")) { 283 intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT); 284 } else if (opt.equals("--activity-reset-task-if-needed")) { 285 intent.addFlags(Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED); 286 } else if (opt.equals("--activity-single-top")) { 287 intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP); 288 } else if (opt.equals("--activity-clear-task")) { 289 intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK); 290 } else if (opt.equals("--activity-task-on-home")) { 291 intent.addFlags(Intent.FLAG_ACTIVITY_TASK_ON_HOME); 292 } else if (opt.equals("--receiver-registered-only")) { 293 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); 294 } else if (opt.equals("--receiver-replace-pending")) { 295 intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING); 296 } else if (opt.equals("--selector")) { 297 intent.setDataAndType(data, type); 298 intent = new Intent(); 299 } else if (opt.equals("-D")) { 300 mDebugOption = true; 301 } else if (opt.equals("-W")) { 302 mWaitOption = true; 303 } else if (opt.equals("-P")) { 304 mProfileFile = nextArgRequired(); 305 mProfileAutoStop = true; 306 } else if (opt.equals("--start-profiler")) { 307 mProfileFile = nextArgRequired(); 308 mProfileAutoStop = false; 309 } else if (opt.equals("-R")) { 310 mRepeat = Integer.parseInt(nextArgRequired()); 311 } else if (opt.equals("-S")) { 312 mStopOption = true; 313 } else if (opt.equals("--opengl-trace")) { 314 mOpenglTraceOption = true; 315 } else { 316 System.err.println("Error: Unknown option: " + opt); 317 showUsage(); 318 return null; 319 } 320 } 321 intent.setDataAndType(data, type); 322 323 final boolean hasSelector = intent != baseIntent; 324 if (hasSelector) { 325 // A selector was specified; fix up. 326 baseIntent.setSelector(intent); 327 intent = baseIntent; 328 } 329 330 String arg = nextArg(); 331 baseIntent = null; 332 if (arg == null) { 333 if (hasSelector) { 334 // If a selector has been specified, and no arguments 335 // have been supplied for the main Intent, then we can 336 // assume it is ACTION_MAIN CATEGORY_LAUNCHER; we don't 337 // need to have a component name specified yet, the 338 // selector will take care of that. 339 baseIntent = new Intent(Intent.ACTION_MAIN); 340 baseIntent.addCategory(Intent.CATEGORY_LAUNCHER); 341 } 342 } else if (arg.indexOf(':') >= 0) { 343 // The argument is a URI. Fully parse it, and use that result 344 // to fill in any data not specified so far. 345 baseIntent = Intent.parseUri(arg, Intent.URI_INTENT_SCHEME); 346 } else if (arg.indexOf('/') >= 0) { 347 // The argument is a component name. Build an Intent to launch 348 // it. 349 baseIntent = new Intent(Intent.ACTION_MAIN); 350 baseIntent.addCategory(Intent.CATEGORY_LAUNCHER); 351 baseIntent.setComponent(ComponentName.unflattenFromString(arg)); 352 } else { 353 // Assume the argument is a package name. 354 baseIntent = new Intent(Intent.ACTION_MAIN); 355 baseIntent.addCategory(Intent.CATEGORY_LAUNCHER); 356 baseIntent.setPackage(arg); 357 } 358 if (baseIntent != null) { 359 Bundle extras = intent.getExtras(); 360 intent.replaceExtras((Bundle)null); 361 Bundle uriExtras = baseIntent.getExtras(); 362 baseIntent.replaceExtras((Bundle)null); 363 if (intent.getAction() != null && baseIntent.getCategories() != null) { 364 HashSet<String> cats = new HashSet<String>(baseIntent.getCategories()); 365 for (String c : cats) { 366 baseIntent.removeCategory(c); 367 } 368 } 369 intent.fillIn(baseIntent, Intent.FILL_IN_COMPONENT | Intent.FILL_IN_SELECTOR); 370 if (extras == null) { 371 extras = uriExtras; 372 } else if (uriExtras != null) { 373 uriExtras.putAll(extras); 374 extras = uriExtras; 375 } 376 intent.replaceExtras(extras); 377 hasIntentInfo = true; 378 } 379 380 if (!hasIntentInfo) throw new IllegalArgumentException("No intent supplied"); 381 return intent; 382 } 383 384 private void runStartService() throws Exception { 385 Intent intent = makeIntent(); 386 System.out.println("Starting service: " + intent); 387 ComponentName cn = mAm.startService(null, intent, intent.getType()); 388 if (cn == null) { 389 System.err.println("Error: Not found; no service started."); 390 } 391 } 392 393 private void runStart() throws Exception { 394 Intent intent = makeIntent(); 395 396 String mimeType = intent.getType(); 397 if (mimeType == null && intent.getData() != null 398 && "content".equals(intent.getData().getScheme())) { 399 mimeType = mAm.getProviderMimeType(intent.getData()); 400 } 401 402 do { 403 if (mStopOption) { 404 String packageName; 405 if (intent.getComponent() != null) { 406 packageName = intent.getComponent().getPackageName(); 407 } else { 408 IPackageManager pm = IPackageManager.Stub.asInterface( 409 ServiceManager.getService("package")); 410 if (pm == null) { 411 System.err.println("Error: Package manager not running; aborting"); 412 return; 413 } 414 List<ResolveInfo> activities = pm.queryIntentActivities(intent, mimeType, 0); 415 if (activities == null || activities.size() <= 0) { 416 System.err.println("Error: Intent does not match any activities: " 417 + intent); 418 return; 419 } else if (activities.size() > 1) { 420 System.err.println("Error: Intent matches multiple activities; can't stop: " 421 + intent); 422 return; 423 } 424 packageName = activities.get(0).activityInfo.packageName; 425 } 426 System.out.println("Stopping: " + packageName); 427 mAm.forceStopPackage(packageName); 428 Thread.sleep(250); 429 } 430 431 System.out.println("Starting: " + intent); 432 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 433 434 ParcelFileDescriptor fd = null; 435 436 if (mProfileFile != null) { 437 try { 438 fd = ParcelFileDescriptor.open( 439 new File(mProfileFile), 440 ParcelFileDescriptor.MODE_CREATE | 441 ParcelFileDescriptor.MODE_TRUNCATE | 442 ParcelFileDescriptor.MODE_READ_WRITE); 443 } catch (FileNotFoundException e) { 444 System.err.println("Error: Unable to open file: " + mProfileFile); 445 return; 446 } 447 } 448 449 IActivityManager.WaitResult result = null; 450 int res; 451 if (mWaitOption) { 452 result = mAm.startActivityAndWait(null, intent, mimeType, 453 null, 0, null, null, 0, false, 454 mDebugOption, mOpenglTraceOption, 455 mProfileFile, fd, mProfileAutoStop); 456 res = result.result; 457 } else { 458 res = mAm.startActivity(null, intent, mimeType, 459 null, 0, null, null, 0, false, 460 mDebugOption, mOpenglTraceOption, 461 mProfileFile, fd, mProfileAutoStop); 462 } 463 PrintStream out = mWaitOption ? System.out : System.err; 464 boolean launched = false; 465 switch (res) { 466 case IActivityManager.START_SUCCESS: 467 launched = true; 468 break; 469 case IActivityManager.START_SWITCHES_CANCELED: 470 launched = true; 471 out.println( 472 "Warning: Activity not started because the " 473 + " current activity is being kept for the user."); 474 break; 475 case IActivityManager.START_DELIVERED_TO_TOP: 476 launched = true; 477 out.println( 478 "Warning: Activity not started, intent has " 479 + "been delivered to currently running " 480 + "top-most instance."); 481 break; 482 case IActivityManager.START_RETURN_INTENT_TO_CALLER: 483 launched = true; 484 out.println( 485 "Warning: Activity not started because intent " 486 + "should be handled by the caller"); 487 break; 488 case IActivityManager.START_TASK_TO_FRONT: 489 launched = true; 490 out.println( 491 "Warning: Activity not started, its current " 492 + "task has been brought to the front"); 493 break; 494 case IActivityManager.START_INTENT_NOT_RESOLVED: 495 out.println( 496 "Error: Activity not started, unable to " 497 + "resolve " + intent.toString()); 498 break; 499 case IActivityManager.START_CLASS_NOT_FOUND: 500 out.println(NO_CLASS_ERROR_CODE); 501 out.println("Error: Activity class " + 502 intent.getComponent().toShortString() 503 + " does not exist."); 504 break; 505 case IActivityManager.START_FORWARD_AND_REQUEST_CONFLICT: 506 out.println( 507 "Error: Activity not started, you requested to " 508 + "both forward and receive its result"); 509 break; 510 case IActivityManager.START_PERMISSION_DENIED: 511 out.println( 512 "Error: Activity not started, you do not " 513 + "have permission to access it."); 514 break; 515 default: 516 out.println( 517 "Error: Activity not started, unknown error code " + res); 518 break; 519 } 520 if (mWaitOption && launched) { 521 if (result == null) { 522 result = new IActivityManager.WaitResult(); 523 result.who = intent.getComponent(); 524 } 525 System.out.println("Status: " + (result.timeout ? "timeout" : "ok")); 526 if (result.who != null) { 527 System.out.println("Activity: " + result.who.flattenToShortString()); 528 } 529 if (result.thisTime >= 0) { 530 System.out.println("ThisTime: " + result.thisTime); 531 } 532 if (result.totalTime >= 0) { 533 System.out.println("TotalTime: " + result.totalTime); 534 } 535 System.out.println("Complete"); 536 } 537 mRepeat--; 538 if (mRepeat > 1) { 539 mAm.unhandledBack(); 540 } 541 } while (mRepeat > 1); 542 } 543 544 private void runForceStop() throws Exception { 545 mAm.forceStopPackage(nextArgRequired()); 546 } 547 548 private void runKill() throws Exception { 549 mAm.killBackgroundProcesses(nextArgRequired()); 550 } 551 552 private void runKillAll() throws Exception { 553 mAm.killAllBackgroundProcesses(); 554 } 555 556 private void sendBroadcast() throws Exception { 557 Intent intent = makeIntent(); 558 IntentReceiver receiver = new IntentReceiver(); 559 System.out.println("Broadcasting: " + intent); 560 mAm.broadcastIntent(null, intent, null, receiver, 0, null, null, null, true, false, 561 Binder.getOrigCallingUser()); 562 receiver.waitForFinish(); 563 } 564 565 private void runInstrument() throws Exception { 566 String profileFile = null; 567 boolean wait = false; 568 boolean rawMode = false; 569 boolean no_window_animation = false; 570 Bundle args = new Bundle(); 571 String argKey = null, argValue = null; 572 IWindowManager wm = IWindowManager.Stub.asInterface(ServiceManager.getService("window")); 573 574 String opt; 575 while ((opt=nextOption()) != null) { 576 if (opt.equals("-p")) { 577 profileFile = nextArgRequired(); 578 } else if (opt.equals("-w")) { 579 wait = true; 580 } else if (opt.equals("-r")) { 581 rawMode = true; 582 } else if (opt.equals("-e")) { 583 argKey = nextArgRequired(); 584 argValue = nextArgRequired(); 585 args.putString(argKey, argValue); 586 } else if (opt.equals("--no_window_animation") 587 || opt.equals("--no-window-animation")) { 588 no_window_animation = true; 589 } else { 590 System.err.println("Error: Unknown option: " + opt); 591 showUsage(); 592 return; 593 } 594 } 595 596 String cnArg = nextArgRequired(); 597 ComponentName cn = ComponentName.unflattenFromString(cnArg); 598 if (cn == null) throw new IllegalArgumentException("Bad component name: " + cnArg); 599 600 InstrumentationWatcher watcher = null; 601 if (wait) { 602 watcher = new InstrumentationWatcher(); 603 watcher.setRawOutput(rawMode); 604 } 605 float[] oldAnims = null; 606 if (no_window_animation) { 607 oldAnims = wm.getAnimationScales(); 608 wm.setAnimationScale(0, 0.0f); 609 wm.setAnimationScale(1, 0.0f); 610 } 611 612 if (!mAm.startInstrumentation(cn, profileFile, 0, args, watcher)) { 613 throw new AndroidException("INSTRUMENTATION_FAILED: " + cn.flattenToString()); 614 } 615 616 if (watcher != null) { 617 if (!watcher.waitForFinish()) { 618 System.out.println("INSTRUMENTATION_ABORTED: System has crashed."); 619 } 620 } 621 622 if (oldAnims != null) { 623 wm.setAnimationScales(oldAnims); 624 } 625 } 626 627 static void removeWallOption() { 628 String props = SystemProperties.get("dalvik.vm.extra-opts"); 629 if (props != null && props.contains("-Xprofile:wallclock")) { 630 props = props.replace("-Xprofile:wallclock", ""); 631 props = props.trim(); 632 SystemProperties.set("dalvik.vm.extra-opts", props); 633 } 634 } 635 636 private void runProfile() throws Exception { 637 String profileFile = null; 638 boolean start = false; 639 boolean wall = false; 640 int profileType = 0; 641 642 String process = null; 643 644 String cmd = nextArgRequired(); 645 if ("looper".equals(cmd)) { 646 cmd = nextArgRequired(); 647 profileType = 1; 648 } 649 650 if ("start".equals(cmd)) { 651 start = true; 652 wall = "--wall".equals(nextOption()); 653 process = nextArgRequired(); 654 } else if ("stop".equals(cmd)) { 655 process = nextArg(); 656 } else { 657 // Compatibility with old syntax: process is specified first. 658 process = cmd; 659 cmd = nextArgRequired(); 660 if ("start".equals(cmd)) { 661 start = true; 662 } else if (!"stop".equals(cmd)) { 663 throw new IllegalArgumentException("Profile command " + process + " not valid"); 664 } 665 } 666 667 ParcelFileDescriptor fd = null; 668 669 if (start) { 670 profileFile = nextArgRequired(); 671 try { 672 fd = ParcelFileDescriptor.open( 673 new File(profileFile), 674 ParcelFileDescriptor.MODE_CREATE | 675 ParcelFileDescriptor.MODE_TRUNCATE | 676 ParcelFileDescriptor.MODE_READ_WRITE); 677 } catch (FileNotFoundException e) { 678 System.err.println("Error: Unable to open file: " + profileFile); 679 return; 680 } 681 } 682 683 try { 684 if (wall) { 685 // XXX doesn't work -- this needs to be set before booting. 686 String props = SystemProperties.get("dalvik.vm.extra-opts"); 687 if (props == null || !props.contains("-Xprofile:wallclock")) { 688 props = props + " -Xprofile:wallclock"; 689 //SystemProperties.set("dalvik.vm.extra-opts", props); 690 } 691 } else if (start) { 692 //removeWallOption(); 693 } 694 if (!mAm.profileControl(process, start, profileFile, fd, profileType)) { 695 wall = false; 696 throw new AndroidException("PROFILE FAILED on process " + process); 697 } 698 } finally { 699 if (!wall) { 700 //removeWallOption(); 701 } 702 } 703 } 704 705 private void runDumpHeap() throws Exception { 706 boolean managed = !"-n".equals(nextOption()); 707 String process = nextArgRequired(); 708 String heapFile = nextArgRequired(); 709 ParcelFileDescriptor fd = null; 710 711 try { 712 fd = ParcelFileDescriptor.open( 713 new File(heapFile), 714 ParcelFileDescriptor.MODE_CREATE | 715 ParcelFileDescriptor.MODE_TRUNCATE | 716 ParcelFileDescriptor.MODE_READ_WRITE); 717 } catch (FileNotFoundException e) { 718 System.err.println("Error: Unable to open file: " + heapFile); 719 return; 720 } 721 722 if (!mAm.dumpHeap(process, managed, heapFile, fd)) { 723 throw new AndroidException("HEAP DUMP FAILED on process " + process); 724 } 725 } 726 727 private void runSetDebugApp() throws Exception { 728 boolean wait = false; 729 boolean persistent = false; 730 731 String opt; 732 while ((opt=nextOption()) != null) { 733 if (opt.equals("-w")) { 734 wait = true; 735 } else if (opt.equals("--persistent")) { 736 persistent = true; 737 } else { 738 System.err.println("Error: Unknown option: " + opt); 739 showUsage(); 740 return; 741 } 742 } 743 744 String pkg = nextArgRequired(); 745 mAm.setDebugApp(pkg, wait, persistent); 746 } 747 748 private void runClearDebugApp() throws Exception { 749 mAm.setDebugApp(null, false, true); 750 } 751 752 private void runSwitchUser() throws Exception { 753 if (android.os.Process.myUid() != 0) { 754 throw new RuntimeException("switchuser can only be run as root"); 755 } 756 String user = nextArgRequired(); 757 mAm.switchUser(Integer.parseInt(user)); 758 } 759 760 class MyActivityController extends IActivityController.Stub { 761 final String mGdbPort; 762 763 static final int STATE_NORMAL = 0; 764 static final int STATE_CRASHED = 1; 765 static final int STATE_EARLY_ANR = 2; 766 static final int STATE_ANR = 3; 767 768 int mState; 769 770 static final int RESULT_DEFAULT = 0; 771 772 static final int RESULT_CRASH_DIALOG = 0; 773 static final int RESULT_CRASH_KILL = 1; 774 775 static final int RESULT_EARLY_ANR_CONTINUE = 0; 776 static final int RESULT_EARLY_ANR_KILL = 1; 777 778 static final int RESULT_ANR_DIALOG = 0; 779 static final int RESULT_ANR_KILL = 1; 780 static final int RESULT_ANR_WAIT = 1; 781 782 int mResult; 783 784 Process mGdbProcess; 785 Thread mGdbThread; 786 boolean mGotGdbPrint; 787 788 MyActivityController(String gdbPort) { 789 mGdbPort = gdbPort; 790 } 791 792 @Override 793 public boolean activityResuming(String pkg) throws RemoteException { 794 synchronized (this) { 795 System.out.println("** Activity resuming: " + pkg); 796 } 797 return true; 798 } 799 800 @Override 801 public boolean activityStarting(Intent intent, String pkg) throws RemoteException { 802 synchronized (this) { 803 System.out.println("** Activity starting: " + pkg); 804 } 805 return true; 806 } 807 808 @Override 809 public boolean appCrashed(String processName, int pid, String shortMsg, String longMsg, 810 long timeMillis, String stackTrace) throws RemoteException { 811 synchronized (this) { 812 System.out.println("** ERROR: PROCESS CRASHED"); 813 System.out.println("processName: " + processName); 814 System.out.println("processPid: " + pid); 815 System.out.println("shortMsg: " + shortMsg); 816 System.out.println("longMsg: " + longMsg); 817 System.out.println("timeMillis: " + timeMillis); 818 System.out.println("stack:"); 819 System.out.print(stackTrace); 820 System.out.println("#"); 821 int result = waitControllerLocked(pid, STATE_CRASHED); 822 return result == RESULT_CRASH_KILL ? false : true; 823 } 824 } 825 826 @Override 827 public int appEarlyNotResponding(String processName, int pid, String annotation) 828 throws RemoteException { 829 synchronized (this) { 830 System.out.println("** ERROR: EARLY PROCESS NOT RESPONDING"); 831 System.out.println("processName: " + processName); 832 System.out.println("processPid: " + pid); 833 System.out.println("annotation: " + annotation); 834 int result = waitControllerLocked(pid, STATE_EARLY_ANR); 835 if (result == RESULT_EARLY_ANR_KILL) return -1; 836 return 0; 837 } 838 } 839 840 @Override 841 public int appNotResponding(String processName, int pid, String processStats) 842 throws RemoteException { 843 synchronized (this) { 844 System.out.println("** ERROR: PROCESS NOT RESPONDING"); 845 System.out.println("processName: " + processName); 846 System.out.println("processPid: " + pid); 847 System.out.println("processStats:"); 848 System.out.print(processStats); 849 System.out.println("#"); 850 int result = waitControllerLocked(pid, STATE_ANR); 851 if (result == RESULT_ANR_KILL) return -1; 852 if (result == RESULT_ANR_WAIT) return 1; 853 return 0; 854 } 855 } 856 857 void killGdbLocked() { 858 mGotGdbPrint = false; 859 if (mGdbProcess != null) { 860 System.out.println("Stopping gdbserver"); 861 mGdbProcess.destroy(); 862 mGdbProcess = null; 863 } 864 if (mGdbThread != null) { 865 mGdbThread.interrupt(); 866 mGdbThread = null; 867 } 868 } 869 870 int waitControllerLocked(int pid, int state) { 871 if (mGdbPort != null) { 872 killGdbLocked(); 873 874 try { 875 System.out.println("Starting gdbserver on port " + mGdbPort); 876 System.out.println("Do the following:"); 877 System.out.println(" adb forward tcp:" + mGdbPort + " tcp:" + mGdbPort); 878 System.out.println(" gdbclient app_process :" + mGdbPort); 879 880 mGdbProcess = Runtime.getRuntime().exec(new String[] { 881 "gdbserver", ":" + mGdbPort, "--attach", Integer.toString(pid) 882 }); 883 final InputStreamReader converter = new InputStreamReader( 884 mGdbProcess.getInputStream()); 885 mGdbThread = new Thread() { 886 @Override 887 public void run() { 888 BufferedReader in = new BufferedReader(converter); 889 String line; 890 int count = 0; 891 while (true) { 892 synchronized (MyActivityController.this) { 893 if (mGdbThread == null) { 894 return; 895 } 896 if (count == 2) { 897 mGotGdbPrint = true; 898 MyActivityController.this.notifyAll(); 899 } 900 } 901 try { 902 line = in.readLine(); 903 if (line == null) { 904 return; 905 } 906 System.out.println("GDB: " + line); 907 count++; 908 } catch (IOException e) { 909 return; 910 } 911 } 912 } 913 }; 914 mGdbThread.start(); 915 916 // Stupid waiting for .5s. Doesn't matter if we end early. 917 try { 918 this.wait(500); 919 } catch (InterruptedException e) { 920 } 921 922 } catch (IOException e) { 923 System.err.println("Failure starting gdbserver: " + e); 924 killGdbLocked(); 925 } 926 } 927 mState = state; 928 System.out.println(""); 929 printMessageForState(); 930 931 while (mState != STATE_NORMAL) { 932 try { 933 wait(); 934 } catch (InterruptedException e) { 935 } 936 } 937 938 killGdbLocked(); 939 940 return mResult; 941 } 942 943 void resumeController(int result) { 944 synchronized (this) { 945 mState = STATE_NORMAL; 946 mResult = result; 947 notifyAll(); 948 } 949 } 950 951 void printMessageForState() { 952 switch (mState) { 953 case STATE_NORMAL: 954 System.out.println("Monitoring activity manager... available commands:"); 955 break; 956 case STATE_CRASHED: 957 System.out.println("Waiting after crash... available commands:"); 958 System.out.println("(c)ontinue: show crash dialog"); 959 System.out.println("(k)ill: immediately kill app"); 960 break; 961 case STATE_EARLY_ANR: 962 System.out.println("Waiting after early ANR... available commands:"); 963 System.out.println("(c)ontinue: standard ANR processing"); 964 System.out.println("(k)ill: immediately kill app"); 965 break; 966 case STATE_ANR: 967 System.out.println("Waiting after ANR... available commands:"); 968 System.out.println("(c)ontinue: show ANR dialog"); 969 System.out.println("(k)ill: immediately kill app"); 970 System.out.println("(w)ait: wait some more"); 971 break; 972 } 973 System.out.println("(q)uit: finish monitoring"); 974 } 975 976 void run() throws RemoteException { 977 try { 978 printMessageForState(); 979 980 mAm.setActivityController(this); 981 mState = STATE_NORMAL; 982 983 InputStreamReader converter = new InputStreamReader(System.in); 984 BufferedReader in = new BufferedReader(converter); 985 String line; 986 987 while ((line = in.readLine()) != null) { 988 boolean addNewline = true; 989 if (line.length() <= 0) { 990 addNewline = false; 991 } else if ("q".equals(line) || "quit".equals(line)) { 992 resumeController(RESULT_DEFAULT); 993 break; 994 } else if (mState == STATE_CRASHED) { 995 if ("c".equals(line) || "continue".equals(line)) { 996 resumeController(RESULT_CRASH_DIALOG); 997 } else if ("k".equals(line) || "kill".equals(line)) { 998 resumeController(RESULT_CRASH_KILL); 999 } else { 1000 System.out.println("Invalid command: " + line); 1001 } 1002 } else if (mState == STATE_ANR) { 1003 if ("c".equals(line) || "continue".equals(line)) { 1004 resumeController(RESULT_ANR_DIALOG); 1005 } else if ("k".equals(line) || "kill".equals(line)) { 1006 resumeController(RESULT_ANR_KILL); 1007 } else if ("w".equals(line) || "wait".equals(line)) { 1008 resumeController(RESULT_ANR_WAIT); 1009 } else { 1010 System.out.println("Invalid command: " + line); 1011 } 1012 } else if (mState == STATE_EARLY_ANR) { 1013 if ("c".equals(line) || "continue".equals(line)) { 1014 resumeController(RESULT_EARLY_ANR_CONTINUE); 1015 } else if ("k".equals(line) || "kill".equals(line)) { 1016 resumeController(RESULT_EARLY_ANR_KILL); 1017 } else { 1018 System.out.println("Invalid command: " + line); 1019 } 1020 } else { 1021 System.out.println("Invalid command: " + line); 1022 } 1023 1024 synchronized (this) { 1025 if (addNewline) { 1026 System.out.println(""); 1027 } 1028 printMessageForState(); 1029 } 1030 } 1031 1032 } catch (IOException e) { 1033 e.printStackTrace(); 1034 } finally { 1035 mAm.setActivityController(null); 1036 } 1037 } 1038 } 1039 1040 private void runMonitor() throws Exception { 1041 String opt; 1042 String gdbPort = null; 1043 while ((opt=nextOption()) != null) { 1044 if (opt.equals("--gdb")) { 1045 gdbPort = nextArgRequired(); 1046 } else { 1047 System.err.println("Error: Unknown option: " + opt); 1048 showUsage(); 1049 return; 1050 } 1051 } 1052 1053 MyActivityController controller = new MyActivityController(gdbPort); 1054 controller.run(); 1055 } 1056 1057 private void runScreenCompat() throws Exception { 1058 String mode = nextArgRequired(); 1059 boolean enabled; 1060 if ("on".equals(mode)) { 1061 enabled = true; 1062 } else if ("off".equals(mode)) { 1063 enabled = false; 1064 } else { 1065 System.err.println("Error: enabled mode must be 'on' or 'off' at " + mode); 1066 showUsage(); 1067 return; 1068 } 1069 1070 String packageName = nextArgRequired(); 1071 do { 1072 try { 1073 mAm.setPackageScreenCompatMode(packageName, enabled 1074 ? ActivityManager.COMPAT_MODE_ENABLED 1075 : ActivityManager.COMPAT_MODE_DISABLED); 1076 } catch (RemoteException e) { 1077 } 1078 packageName = nextArg(); 1079 } while (packageName != null); 1080 } 1081 1082 private void runDisplaySize() throws Exception { 1083 String size = nextArgRequired(); 1084 int m, n; 1085 if ("reset".equals(size)) { 1086 m = n = -1; 1087 } else { 1088 int div = size.indexOf('x'); 1089 if (div <= 0 || div >= (size.length()-1)) { 1090 System.err.println("Error: bad size " + size); 1091 showUsage(); 1092 return; 1093 } 1094 String mstr = size.substring(0, div); 1095 String nstr = size.substring(div+1); 1096 try { 1097 m = Integer.parseInt(mstr); 1098 n = Integer.parseInt(nstr); 1099 } catch (NumberFormatException e) { 1100 System.err.println("Error: bad number " + e); 1101 showUsage(); 1102 return; 1103 } 1104 } 1105 1106 if (m < n) { 1107 int tmp = m; 1108 m = n; 1109 n = tmp; 1110 } 1111 1112 IWindowManager wm = IWindowManager.Stub.asInterface(ServiceManager.checkService( 1113 Context.WINDOW_SERVICE)); 1114 if (wm == null) { 1115 System.err.println(NO_SYSTEM_ERROR_CODE); 1116 throw new AndroidException("Can't connect to window manager; is the system running?"); 1117 } 1118 1119 try { 1120 if (m >= 0 && n >= 0) { 1121 wm.setForcedDisplaySize(m, n); 1122 } else { 1123 wm.clearForcedDisplaySize(); 1124 } 1125 } catch (RemoteException e) { 1126 } 1127 } 1128 1129 private void runToUri(boolean intentScheme) throws Exception { 1130 Intent intent = makeIntent(); 1131 System.out.println(intent.toUri(intentScheme ? Intent.URI_INTENT_SCHEME : 0)); 1132 } 1133 1134 private class IntentReceiver extends IIntentReceiver.Stub { 1135 private boolean mFinished = false; 1136 1137 public synchronized void performReceive( 1138 Intent intent, int rc, String data, Bundle ext, boolean ord, 1139 boolean sticky) { 1140 String line = "Broadcast completed: result=" + rc; 1141 if (data != null) line = line + ", data=\"" + data + "\""; 1142 if (ext != null) line = line + ", extras: " + ext; 1143 System.out.println(line); 1144 mFinished = true; 1145 notifyAll(); 1146 } 1147 1148 public synchronized void waitForFinish() { 1149 try { 1150 while (!mFinished) wait(); 1151 } catch (InterruptedException e) { 1152 throw new IllegalStateException(e); 1153 } 1154 } 1155 } 1156 1157 private class InstrumentationWatcher extends IInstrumentationWatcher.Stub { 1158 private boolean mFinished = false; 1159 private boolean mRawMode = false; 1160 1161 /** 1162 * Set or reset "raw mode". In "raw mode", all bundles are dumped. In "pretty mode", 1163 * if a bundle includes Instrumentation.REPORT_KEY_STREAMRESULT, just print that. 1164 * @param rawMode true for raw mode, false for pretty mode. 1165 */ 1166 public void setRawOutput(boolean rawMode) { 1167 mRawMode = rawMode; 1168 } 1169 1170 public void instrumentationStatus(ComponentName name, int resultCode, Bundle results) { 1171 synchronized (this) { 1172 // pretty printer mode? 1173 String pretty = null; 1174 if (!mRawMode && results != null) { 1175 pretty = results.getString(Instrumentation.REPORT_KEY_STREAMRESULT); 1176 } 1177 if (pretty != null) { 1178 System.out.print(pretty); 1179 } else { 1180 if (results != null) { 1181 for (String key : results.keySet()) { 1182 System.out.println( 1183 "INSTRUMENTATION_STATUS: " + key + "=" + results.get(key)); 1184 } 1185 } 1186 System.out.println("INSTRUMENTATION_STATUS_CODE: " + resultCode); 1187 } 1188 notifyAll(); 1189 } 1190 } 1191 1192 public void instrumentationFinished(ComponentName name, int resultCode, 1193 Bundle results) { 1194 synchronized (this) { 1195 // pretty printer mode? 1196 String pretty = null; 1197 if (!mRawMode && results != null) { 1198 pretty = results.getString(Instrumentation.REPORT_KEY_STREAMRESULT); 1199 } 1200 if (pretty != null) { 1201 System.out.println(pretty); 1202 } else { 1203 if (results != null) { 1204 for (String key : results.keySet()) { 1205 System.out.println( 1206 "INSTRUMENTATION_RESULT: " + key + "=" + results.get(key)); 1207 } 1208 } 1209 System.out.println("INSTRUMENTATION_CODE: " + resultCode); 1210 } 1211 mFinished = true; 1212 notifyAll(); 1213 } 1214 } 1215 1216 public boolean waitForFinish() { 1217 synchronized (this) { 1218 while (!mFinished) { 1219 try { 1220 if (!mAm.asBinder().pingBinder()) { 1221 return false; 1222 } 1223 wait(1000); 1224 } catch (InterruptedException e) { 1225 throw new IllegalStateException(e); 1226 } 1227 } 1228 } 1229 return true; 1230 } 1231 } 1232 1233 private String nextOption() { 1234 if (mCurArgData != null) { 1235 String prev = mArgs[mNextArg - 1]; 1236 throw new IllegalArgumentException("No argument expected after \"" + prev + "\""); 1237 } 1238 if (mNextArg >= mArgs.length) { 1239 return null; 1240 } 1241 String arg = mArgs[mNextArg]; 1242 if (!arg.startsWith("-")) { 1243 return null; 1244 } 1245 mNextArg++; 1246 if (arg.equals("--")) { 1247 return null; 1248 } 1249 if (arg.length() > 1 && arg.charAt(1) != '-') { 1250 if (arg.length() > 2) { 1251 mCurArgData = arg.substring(2); 1252 return arg.substring(0, 2); 1253 } else { 1254 mCurArgData = null; 1255 return arg; 1256 } 1257 } 1258 mCurArgData = null; 1259 return arg; 1260 } 1261 1262 private String nextArg() { 1263 if (mCurArgData != null) { 1264 String arg = mCurArgData; 1265 mCurArgData = null; 1266 return arg; 1267 } else if (mNextArg < mArgs.length) { 1268 return mArgs[mNextArg++]; 1269 } else { 1270 return null; 1271 } 1272 } 1273 1274 private String nextArgRequired() { 1275 String arg = nextArg(); 1276 if (arg == null) { 1277 String prev = mArgs[mNextArg - 1]; 1278 throw new IllegalArgumentException("Argument expected after \"" + prev + "\""); 1279 } 1280 return arg; 1281 } 1282 1283 private static void showUsage() { 1284 System.err.println( 1285 "usage: am [subcommand] [options]\n" + 1286 "usage: am start [-D] [-W] [-P <FILE>] [--start-profiler <FILE>]\n" + 1287 " [--R COUNT] [-S] [--opengl-trace] <INTENT>\n" + 1288 " am startservice <INTENT>\n" + 1289 " am force-stop <PACKAGE>\n" + 1290 " am kill <PACKAGE>\n" + 1291 " am kill-all\n" + 1292 " am broadcast <INTENT>\n" + 1293 " am instrument [-r] [-e <NAME> <VALUE>] [-p <FILE>] [-w]\n" + 1294 " [--no-window-animation] <COMPONENT>\n" + 1295 " am profile [looper] start <PROCESS> <FILE>\n" + 1296 " am profile [looper] stop [<PROCESS>]\n" + 1297 " am dumpheap [flags] <PROCESS> <FILE>\n" + 1298 " am set-debug-app [-w] [--persistent] <PACKAGE>\n" + 1299 " am clear-debug-app\n" + 1300 " am monitor [--gdb <port>]\n" + 1301 " am screen-compat [on|off] <PACKAGE>\n" + 1302 " am display-size [reset|MxN]\n" + 1303 " am to-uri [INTENT]\n" + 1304 " am to-intent-uri [INTENT]\n" + 1305 "\n" + 1306 "am start: start an Activity. Options are:\n" + 1307 " -D: enable debugging\n" + 1308 " -W: wait for launch to complete\n" + 1309 " --start-profiler <FILE>: start profiler and send results to <FILE>\n" + 1310 " -P <FILE>: like above, but profiling stops when app goes idle\n" + 1311 " -R: repeat the activity launch <COUNT> times. Prior to each repeat,\n" + 1312 " the top activity will be finished.\n" + 1313 " -S: force stop the target app before starting the activity\n" + 1314 " --opengl-trace: enable tracing of OpenGL functions\n" + 1315 "\n" + 1316 "am startservice: start a Service.\n" + 1317 "\n" + 1318 "am force-stop: force stop everything associated with <PACKAGE>.\n" + 1319 "\n" + 1320 "am kill: Kill all processes associated with <PACKAGE>. Only kills.\n" + 1321 " processes that are safe to kill -- that is, will not impact the user\n" + 1322 " experience.\n" + 1323 "\n" + 1324 "am kill-all: Kill all background processes.\n" + 1325 "\n" + 1326 "am broadcast: send a broadcast Intent.\n" + 1327 "\n" + 1328 "am instrument: start an Instrumentation. Typically this target <COMPONENT>\n" + 1329 " is the form <TEST_PACKAGE>/<RUNNER_CLASS>. Options are:\n" + 1330 " -r: print raw results (otherwise decode REPORT_KEY_STREAMRESULT). Use with\n" + 1331 " [-e perf true] to generate raw output for performance measurements.\n" + 1332 " -e <NAME> <VALUE>: set argument <NAME> to <VALUE>. For test runners a\n" + 1333 " common form is [-e <testrunner_flag> <value>[,<value>...]].\n" + 1334 " -p <FILE>: write profiling data to <FILE>\n" + 1335 " -w: wait for instrumentation to finish before returning. Required for\n" + 1336 " test runners.\n" + 1337 " --no-window-animation: turn off window animations will running.\n" + 1338 "\n" + 1339 "am profile: start and stop profiler on a process.\n" + 1340 "\n" + 1341 "am dumpheap: dump the heap of a process. Options are:\n" + 1342 " -n: dump native heap instead of managed heap\n" + 1343 "\n" + 1344 "am set-debug-app: set application <PACKAGE> to debug. Options are:\n" + 1345 " -w: wait for debugger when application starts\n" + 1346 " --persistent: retain this value\n" + 1347 "\n" + 1348 "am clear-debug-app: clear the previously set-debug-app.\n" + 1349 "\n" + 1350 "am monitor: start monitoring for crashes or ANRs.\n" + 1351 " --gdb: start gdbserv on the given port at crash/ANR\n" + 1352 "\n" + 1353 "am screen-compat: control screen compatibility mode of <PACKAGE>.\n" + 1354 "\n" + 1355 "am display-size: override display size.\n" + 1356 "\n" + 1357 "am to-uri: print the given Intent specification as a URI.\n" + 1358 "\n" + 1359 "am to-intent-uri: print the given Intent specification as an intent: URI.\n" + 1360 "\n" + 1361 "<INTENT> specifications include these flags and arguments:\n" + 1362 " [-a <ACTION>] [-d <DATA_URI>] [-t <MIME_TYPE>]\n" + 1363 " [-c <CATEGORY> [-c <CATEGORY>] ...]\n" + 1364 " [-e|--es <EXTRA_KEY> <EXTRA_STRING_VALUE> ...]\n" + 1365 " [--esn <EXTRA_KEY> ...]\n" + 1366 " [--ez <EXTRA_KEY> <EXTRA_BOOLEAN_VALUE> ...]\n" + 1367 " [--ei <EXTRA_KEY> <EXTRA_INT_VALUE> ...]\n" + 1368 " [--el <EXTRA_KEY> <EXTRA_LONG_VALUE> ...]\n" + 1369 " [--ef <EXTRA_KEY> <EXTRA_FLOAT_VALUE> ...]\n" + 1370 " [--eu <EXTRA_KEY> <EXTRA_URI_VALUE> ...]\n" + 1371 " [--eia <EXTRA_KEY> <EXTRA_INT_VALUE>[,<EXTRA_INT_VALUE...]]\n" + 1372 " [--ela <EXTRA_KEY> <EXTRA_LONG_VALUE>[,<EXTRA_LONG_VALUE...]]\n" + 1373 " [--efa <EXTRA_KEY> <EXTRA_FLOAT_VALUE>[,<EXTRA_FLOAT_VALUE...]]\n" + 1374 " [-n <COMPONENT>] [-f <FLAGS>]\n" + 1375 " [--grant-read-uri-permission] [--grant-write-uri-permission]\n" + 1376 " [--debug-log-resolution] [--exclude-stopped-packages]\n" + 1377 " [--include-stopped-packages]\n" + 1378 " [--activity-brought-to-front] [--activity-clear-top]\n" + 1379 " [--activity-clear-when-task-reset] [--activity-exclude-from-recents]\n" + 1380 " [--activity-launched-from-history] [--activity-multiple-task]\n" + 1381 " [--activity-no-animation] [--activity-no-history]\n" + 1382 " [--activity-no-user-action] [--activity-previous-is-top]\n" + 1383 " [--activity-reorder-to-front] [--activity-reset-task-if-needed]\n" + 1384 " [--activity-single-top] [--activity-clear-task]\n" + 1385 " [--activity-task-on-home]\n" + 1386 " [--receiver-registered-only] [--receiver-replace-pending]\n" + 1387 " [--selector]\n" + 1388 " [<URI> | <PACKAGE> | <COMPONENT>]\n" 1389 ); 1390 } 1391} 1392