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