PackageManagerShellCommand.java revision b1072718130b998e6d25bc3358eefa62b4fa5a2d
1/* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.server.pm; 18 19import android.app.ActivityManager; 20import android.content.ComponentName; 21import android.content.IIntentReceiver; 22import android.content.IIntentSender; 23import android.content.Intent; 24import android.content.IntentSender; 25import android.content.pm.ApplicationInfo; 26import android.content.pm.FeatureInfo; 27import android.content.pm.IPackageManager; 28import android.content.pm.InstrumentationInfo; 29import android.content.pm.PackageInfo; 30import android.content.pm.PackageInstaller; 31import android.content.pm.PackageItemInfo; 32import android.content.pm.PackageManager; 33import android.content.pm.ParceledListSlice; 34import android.content.pm.PermissionGroupInfo; 35import android.content.pm.PermissionInfo; 36import android.content.pm.PackageInstaller.SessionInfo; 37import android.content.pm.PackageInstaller.SessionParams; 38import android.content.pm.ResolveInfo; 39import android.content.res.AssetManager; 40import android.content.res.Resources; 41import android.net.Uri; 42import android.os.Binder; 43import android.os.Build; 44import android.os.Bundle; 45import android.os.RemoteException; 46import android.os.ShellCommand; 47import android.os.SystemProperties; 48import android.os.UserHandle; 49import android.text.TextUtils; 50import android.util.PrintWriterPrinter; 51import com.android.internal.util.SizedInputStream; 52 53import dalvik.system.DexFile; 54 55import libcore.io.IoUtils; 56 57import java.io.File; 58import java.io.FileInputStream; 59import java.io.IOException; 60import java.io.InputStream; 61import java.io.OutputStream; 62import java.io.PrintWriter; 63import java.net.URISyntaxException; 64import java.util.ArrayList; 65import java.util.Collections; 66import java.util.Comparator; 67import java.util.List; 68import java.util.WeakHashMap; 69import java.util.concurrent.SynchronousQueue; 70import java.util.concurrent.TimeUnit; 71 72class PackageManagerShellCommand extends ShellCommand { 73 final IPackageManager mInterface; 74 final private WeakHashMap<String, Resources> mResourceCache = 75 new WeakHashMap<String, Resources>(); 76 int mTargetUser; 77 78 PackageManagerShellCommand(PackageManagerService service) { 79 mInterface = service; 80 } 81 82 @Override 83 public int onCommand(String cmd) { 84 if (cmd == null) { 85 return handleDefaultCommands(cmd); 86 } 87 88 final PrintWriter pw = getOutPrintWriter(); 89 try { 90 switch(cmd) { 91 case "install": 92 return runInstall(); 93 case "install-abandon": 94 case "install-destroy": 95 return runInstallAbandon(); 96 case "install-commit": 97 return runInstallCommit(); 98 case "install-create": 99 return runInstallCreate(); 100 case "install-remove": 101 return runInstallRemove(); 102 case "install-write": 103 return runInstallWrite(); 104 case "compile": 105 return runCompile(); 106 case "list": 107 return runList(); 108 case "uninstall": 109 return runUninstall(); 110 case "resolve-activity": 111 return runResolveActivity(); 112 case "query-activities": 113 return runQueryIntentActivities(); 114 case "query-services": 115 return runQueryIntentServices(); 116 case "query-receivers": 117 return runQueryIntentReceivers(); 118 case "suspend": 119 return runSuspend(true); 120 case "unsuspend": 121 return runSuspend(false); 122 case "set-home-activity": 123 return runSetHomeActivity(); 124 default: 125 return handleDefaultCommands(cmd); 126 } 127 } catch (RemoteException e) { 128 pw.println("Remote exception: " + e); 129 } 130 return -1; 131 } 132 133 private int runInstall() throws RemoteException { 134 final PrintWriter pw = getOutPrintWriter(); 135 final InstallParams params = makeInstallParams(); 136 final int sessionId = doCreateSession(params.sessionParams, 137 params.installerPackageName, params.userId); 138 boolean abandonSession = true; 139 try { 140 final String inPath = getNextArg(); 141 if (inPath == null && params.sessionParams.sizeBytes == 0) { 142 pw.println("Error: must either specify a package size or an APK file"); 143 return 1; 144 } 145 if (doWriteSplit(sessionId, inPath, params.sessionParams.sizeBytes, "base.apk", 146 false /*logSuccess*/) != PackageInstaller.STATUS_SUCCESS) { 147 return 1; 148 } 149 if (doCommitSession(sessionId, false /*logSuccess*/) 150 != PackageInstaller.STATUS_SUCCESS) { 151 return 1; 152 } 153 abandonSession = false; 154 pw.println("Success"); 155 return 0; 156 } finally { 157 if (abandonSession) { 158 try { 159 doAbandonSession(sessionId, false /*logSuccess*/); 160 } catch (Exception ignore) { 161 } 162 } 163 } 164 } 165 166 private int runSuspend(boolean suspendedState) { 167 final PrintWriter pw = getOutPrintWriter(); 168 int userId = UserHandle.USER_SYSTEM; 169 String opt; 170 while ((opt = getNextOption()) != null) { 171 switch (opt) { 172 case "--user": 173 userId = UserHandle.parseUserArg(getNextArgRequired()); 174 break; 175 default: 176 pw.println("Error: Unknown option: " + opt); 177 return 1; 178 } 179 } 180 181 String packageName = getNextArg(); 182 if (packageName == null) { 183 pw.println("Error: package name not specified"); 184 return 1; 185 } 186 187 try { 188 mInterface.setPackagesSuspendedAsUser(new String[]{packageName}, suspendedState, 189 userId); 190 pw.println("Package " + packageName + " new suspended state: " 191 + mInterface.isPackageSuspendedForUser(packageName, userId)); 192 return 0; 193 } catch (RemoteException | IllegalArgumentException e) { 194 pw.println(e.toString()); 195 return 1; 196 } 197 } 198 199 private int runInstallAbandon() throws RemoteException { 200 final int sessionId = Integer.parseInt(getNextArg()); 201 return doAbandonSession(sessionId, true /*logSuccess*/); 202 } 203 204 private int runInstallCommit() throws RemoteException { 205 final int sessionId = Integer.parseInt(getNextArg()); 206 return doCommitSession(sessionId, true /*logSuccess*/); 207 } 208 209 private int runInstallCreate() throws RemoteException { 210 final PrintWriter pw = getOutPrintWriter(); 211 final InstallParams installParams = makeInstallParams(); 212 final int sessionId = doCreateSession(installParams.sessionParams, 213 installParams.installerPackageName, installParams.userId); 214 215 // NOTE: adb depends on parsing this string 216 pw.println("Success: created install session [" + sessionId + "]"); 217 return 0; 218 } 219 220 private int runInstallWrite() throws RemoteException { 221 long sizeBytes = -1; 222 223 String opt; 224 while ((opt = getNextOption()) != null) { 225 if (opt.equals("-S")) { 226 sizeBytes = Long.parseLong(getNextArg()); 227 } else { 228 throw new IllegalArgumentException("Unknown option: " + opt); 229 } 230 } 231 232 final int sessionId = Integer.parseInt(getNextArg()); 233 final String splitName = getNextArg(); 234 final String path = getNextArg(); 235 return doWriteSplit(sessionId, path, sizeBytes, splitName, true /*logSuccess*/); 236 } 237 238 private int runInstallRemove() throws RemoteException { 239 final PrintWriter pw = getOutPrintWriter(); 240 241 final int sessionId = Integer.parseInt(getNextArg()); 242 243 final String splitName = getNextArg(); 244 if (splitName == null) { 245 pw.println("Error: split name not specified"); 246 return 1; 247 } 248 return doRemoveSplit(sessionId, splitName, true /*logSuccess*/); 249 } 250 251 private int runCompile() throws RemoteException { 252 final PrintWriter pw = getOutPrintWriter(); 253 boolean checkProfiles = SystemProperties.getBoolean("dalvik.vm.usejitprofiles", false); 254 boolean forceCompilation = false; 255 boolean allPackages = false; 256 boolean clearProfileData = false; 257 String compilerFilter = null; 258 String compilationReason = null; 259 String checkProfilesRaw = null; 260 261 if (peekNextArg() == null) { 262 // No arguments, show help. 263 pw.println("Usage: cmd package compile [-c] [-f] [--reset] [-m mode] " + 264 "[-r reason] [-a|pkg]"); 265 pw.println(); 266 pw.println(" -c Clear profile data"); 267 pw.println(" -f Force compilation"); 268 pw.println(" --check-prof val Look at profiles when doing dexopt."); 269 pw.println(" Overrides dalvik.vm.usejitprofiles to true of false"); 270 pw.println(" --reset Reset package"); 271 pw.println(" -m mode Compilation mode, one of the dex2oat compiler filters"); 272 pw.println(" verify-none"); 273 pw.println(" verify-at-runtime"); 274 pw.println(" verify-profile"); 275 pw.println(" interpret-only"); 276 pw.println(" space-profile"); 277 pw.println(" space"); 278 pw.println(" speed-profile"); 279 pw.println(" speed"); 280 pw.println(" everything"); 281 pw.println(" -r reason Compiler reason, one of the package manager reasons"); 282 for (int i = 0; i < PackageManagerServiceCompilerMapping.REASON_STRINGS.length; i++) { 283 pw.println(" " + 284 PackageManagerServiceCompilerMapping.REASON_STRINGS[i]); 285 } 286 pw.println(" -a Apply to all packages"); 287 return 1; 288 } 289 290 String opt; 291 while ((opt = getNextOption()) != null) { 292 switch (opt) { 293 case "-a": 294 allPackages = true; 295 break; 296 case "-c": 297 clearProfileData = true; 298 break; 299 case "-f": 300 forceCompilation = true; 301 break; 302 case "-m": 303 compilerFilter = getNextArgRequired(); 304 break; 305 case "-r": 306 compilationReason = getNextArgRequired(); 307 break; 308 case "-check-prof": 309 checkProfilesRaw = getNextArgRequired(); 310 break; 311 case "--reset": 312 forceCompilation = true; 313 clearProfileData = true; 314 compilerFilter = "reset"; 315 break; 316 default: 317 pw.println("Error: Unknown option: " + opt); 318 return 1; 319 } 320 } 321 322 if (checkProfilesRaw != null) { 323 if ("true".equals(checkProfilesRaw)) { 324 checkProfiles = true; 325 } else if ("false".equals(checkProfilesRaw)) { 326 checkProfiles = false; 327 } else { 328 pw.println("Invalid value for \"--check-prof\". Expected \"true\" or \"false\"."); 329 return 1; 330 } 331 } 332 333 if (compilerFilter != null && compilationReason != null) { 334 pw.println("Cannot use compilation filter (\"-m\") and compilation reason (\"-r\") " + 335 "at the same time"); 336 return 1; 337 } 338 if (compilerFilter == null && compilationReason == null) { 339 pw.println("Cannot run without any of compilation filter (\"-m\") and compilation " + 340 "reason (\"-r\") at the same time"); 341 return 1; 342 } 343 344 String targetCompilerFilter; 345 if (compilerFilter != null) { 346 // Specially recognize default and reset. Otherwise, only accept valid modes. 347 if ("default".equals(compilerFilter)) { 348 // Use the default mode for background dexopt. 349 targetCompilerFilter = 350 PackageManagerServiceCompilerMapping.getCompilerFilterForReason( 351 PackageManagerService.REASON_BACKGROUND_DEXOPT); 352 } else if ("reset".equals(compilerFilter)) { 353 // Use the default mode for install. 354 targetCompilerFilter = 355 PackageManagerServiceCompilerMapping.getCompilerFilterForReason( 356 PackageManagerService.REASON_INSTALL); 357 } else { 358 if (!DexFile.isValidCompilerFilter(compilerFilter)) { 359 pw.println("Error: \"" + compilerFilter + 360 "\" is not a valid compilation filter."); 361 return 1; 362 } 363 targetCompilerFilter = compilerFilter; 364 } 365 } else { 366 int reason = -1; 367 for (int i = 0; i < PackageManagerServiceCompilerMapping.REASON_STRINGS.length; i++) { 368 if (PackageManagerServiceCompilerMapping.REASON_STRINGS[i].equals( 369 compilationReason)) { 370 reason = i; 371 break; 372 } 373 } 374 if (reason == -1) { 375 pw.println("Error: Unknown compilation reason: " + compilationReason); 376 return 1; 377 } 378 targetCompilerFilter = 379 PackageManagerServiceCompilerMapping.getCompilerFilterForReason(reason); 380 } 381 382 383 List<String> packageNames = null; 384 if (allPackages) { 385 packageNames = mInterface.getAllPackages(); 386 } else { 387 String packageName = getNextArg(); 388 if (packageName == null) { 389 pw.println("Error: package name not specified"); 390 return 1; 391 } 392 packageNames = Collections.singletonList(packageName); 393 } 394 395 List<String> failedPackages = new ArrayList<>(); 396 for (String packageName : packageNames) { 397 if (clearProfileData) { 398 mInterface.clearApplicationProfileData(packageName); 399 } 400 401 boolean result = mInterface.performDexOptMode(packageName, null /* instructionSet */, 402 checkProfiles, targetCompilerFilter, forceCompilation); 403 if (!result) { 404 failedPackages.add(packageName); 405 } 406 } 407 408 if (failedPackages.isEmpty()) { 409 pw.println("Success"); 410 return 0; 411 } else if (failedPackages.size() == 1) { 412 pw.println("Failure: package " + failedPackages.get(0) + " could not be compiled"); 413 return 1; 414 } else { 415 pw.print("Failure: the following packages could not be compiled: "); 416 boolean is_first = true; 417 for (String packageName : failedPackages) { 418 if (is_first) { 419 is_first = false; 420 } else { 421 pw.print(", "); 422 } 423 pw.print(packageName); 424 } 425 pw.println(); 426 return 1; 427 } 428 } 429 430 private int runList() throws RemoteException { 431 final PrintWriter pw = getOutPrintWriter(); 432 final String type = getNextArg(); 433 if (type == null) { 434 pw.println("Error: didn't specify type of data to list"); 435 return -1; 436 } 437 switch(type) { 438 case "features": 439 return runListFeatures(); 440 case "instrumentation": 441 return runListInstrumentation(); 442 case "libraries": 443 return runListLibraries(); 444 case "package": 445 case "packages": 446 return runListPackages(false /*showSourceDir*/); 447 case "permission-groups": 448 return runListPermissionGroups(); 449 case "permissions": 450 return runListPermissions(); 451 } 452 pw.println("Error: unknown list type '" + type + "'"); 453 return -1; 454 } 455 456 private int runListFeatures() throws RemoteException { 457 final PrintWriter pw = getOutPrintWriter(); 458 final List<FeatureInfo> list = mInterface.getSystemAvailableFeatures().getList(); 459 460 // sort by name 461 Collections.sort(list, new Comparator<FeatureInfo>() { 462 public int compare(FeatureInfo o1, FeatureInfo o2) { 463 if (o1.name == o2.name) return 0; 464 if (o1.name == null) return -1; 465 if (o2.name == null) return 1; 466 return o1.name.compareTo(o2.name); 467 } 468 }); 469 470 final int count = (list != null) ? list.size() : 0; 471 for (int p = 0; p < count; p++) { 472 FeatureInfo fi = list.get(p); 473 pw.print("feature:"); 474 if (fi.name != null) { 475 pw.print(fi.name); 476 if (fi.version > 0) { 477 pw.print("="); 478 pw.print(fi.version); 479 } 480 pw.println(); 481 } else { 482 pw.println("reqGlEsVersion=0x" 483 + Integer.toHexString(fi.reqGlEsVersion)); 484 } 485 } 486 return 0; 487 } 488 489 private int runListInstrumentation() throws RemoteException { 490 final PrintWriter pw = getOutPrintWriter(); 491 boolean showSourceDir = false; 492 String targetPackage = null; 493 494 try { 495 String opt; 496 while ((opt = getNextArg()) != null) { 497 switch (opt) { 498 case "-f": 499 showSourceDir = true; 500 break; 501 default: 502 if (opt.charAt(0) != '-') { 503 targetPackage = opt; 504 } else { 505 pw.println("Error: Unknown option: " + opt); 506 return -1; 507 } 508 break; 509 } 510 } 511 } catch (RuntimeException ex) { 512 pw.println("Error: " + ex.toString()); 513 return -1; 514 } 515 516 final List<InstrumentationInfo> list = 517 mInterface.queryInstrumentation(targetPackage, 0 /*flags*/).getList(); 518 519 // sort by target package 520 Collections.sort(list, new Comparator<InstrumentationInfo>() { 521 public int compare(InstrumentationInfo o1, InstrumentationInfo o2) { 522 return o1.targetPackage.compareTo(o2.targetPackage); 523 } 524 }); 525 526 final int count = (list != null) ? list.size() : 0; 527 for (int p = 0; p < count; p++) { 528 final InstrumentationInfo ii = list.get(p); 529 pw.print("instrumentation:"); 530 if (showSourceDir) { 531 pw.print(ii.sourceDir); 532 pw.print("="); 533 } 534 final ComponentName cn = new ComponentName(ii.packageName, ii.name); 535 pw.print(cn.flattenToShortString()); 536 pw.print(" (target="); 537 pw.print(ii.targetPackage); 538 pw.println(")"); 539 } 540 return 0; 541 } 542 543 private int runListLibraries() throws RemoteException { 544 final PrintWriter pw = getOutPrintWriter(); 545 final List<String> list = new ArrayList<String>(); 546 final String[] rawList = mInterface.getSystemSharedLibraryNames(); 547 for (int i = 0; i < rawList.length; i++) { 548 list.add(rawList[i]); 549 } 550 551 // sort by name 552 Collections.sort(list, new Comparator<String>() { 553 public int compare(String o1, String o2) { 554 if (o1 == o2) return 0; 555 if (o1 == null) return -1; 556 if (o2 == null) return 1; 557 return o1.compareTo(o2); 558 } 559 }); 560 561 final int count = (list != null) ? list.size() : 0; 562 for (int p = 0; p < count; p++) { 563 String lib = list.get(p); 564 pw.print("library:"); 565 pw.println(lib); 566 } 567 return 0; 568 } 569 570 private int runListPackages(boolean showSourceDir) throws RemoteException { 571 final PrintWriter pw = getOutPrintWriter(); 572 int getFlags = 0; 573 boolean listDisabled = false, listEnabled = false; 574 boolean listSystem = false, listThirdParty = false; 575 boolean listInstaller = false; 576 int userId = UserHandle.USER_SYSTEM; 577 try { 578 String opt; 579 while ((opt = getNextOption()) != null) { 580 switch (opt) { 581 case "-d": 582 listDisabled = true; 583 break; 584 case "-e": 585 listEnabled = true; 586 break; 587 case "-f": 588 showSourceDir = true; 589 break; 590 case "-i": 591 listInstaller = true; 592 break; 593 case "-l": 594 // old compat 595 break; 596 case "-lf": 597 showSourceDir = true; 598 break; 599 case "-s": 600 listSystem = true; 601 break; 602 case "-u": 603 getFlags |= PackageManager.GET_UNINSTALLED_PACKAGES; 604 break; 605 case "-3": 606 listThirdParty = true; 607 break; 608 case "--user": 609 userId = UserHandle.parseUserArg(getNextArgRequired()); 610 break; 611 default: 612 pw.println("Error: Unknown option: " + opt); 613 return -1; 614 } 615 } 616 } catch (RuntimeException ex) { 617 pw.println("Error: " + ex.toString()); 618 return -1; 619 } 620 621 final String filter = getNextArg(); 622 623 @SuppressWarnings("unchecked") 624 final ParceledListSlice<PackageInfo> slice = 625 mInterface.getInstalledPackages(getFlags, userId); 626 final List<PackageInfo> packages = slice.getList(); 627 628 final int count = packages.size(); 629 for (int p = 0; p < count; p++) { 630 final PackageInfo info = packages.get(p); 631 if (filter != null && !info.packageName.contains(filter)) { 632 continue; 633 } 634 final boolean isSystem = 635 (info.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) != 0; 636 if ((!listDisabled || !info.applicationInfo.enabled) && 637 (!listEnabled || info.applicationInfo.enabled) && 638 (!listSystem || isSystem) && 639 (!listThirdParty || !isSystem)) { 640 pw.print("package:"); 641 if (showSourceDir) { 642 pw.print(info.applicationInfo.sourceDir); 643 pw.print("="); 644 } 645 pw.print(info.packageName); 646 if (listInstaller) { 647 pw.print(" installer="); 648 pw.print(mInterface.getInstallerPackageName(info.packageName)); 649 } 650 pw.println(); 651 } 652 } 653 return 0; 654 } 655 656 private int runListPermissionGroups() throws RemoteException { 657 final PrintWriter pw = getOutPrintWriter(); 658 final List<PermissionGroupInfo> pgs = mInterface.getAllPermissionGroups(0).getList(); 659 660 final int count = pgs.size(); 661 for (int p = 0; p < count ; p++) { 662 final PermissionGroupInfo pgi = pgs.get(p); 663 pw.print("permission group:"); 664 pw.println(pgi.name); 665 } 666 return 0; 667 } 668 669 private int runListPermissions() throws RemoteException { 670 final PrintWriter pw = getOutPrintWriter(); 671 boolean labels = false; 672 boolean groups = false; 673 boolean userOnly = false; 674 boolean summary = false; 675 boolean dangerousOnly = false; 676 String opt; 677 while ((opt = getNextOption()) != null) { 678 switch (opt) { 679 case "-d": 680 dangerousOnly = true; 681 break; 682 case "-f": 683 labels = true; 684 break; 685 case "-g": 686 groups = true; 687 break; 688 case "-s": 689 groups = true; 690 labels = true; 691 summary = true; 692 break; 693 case "-u": 694 userOnly = true; 695 break; 696 default: 697 pw.println("Error: Unknown option: " + opt); 698 return 1; 699 } 700 } 701 702 final ArrayList<String> groupList = new ArrayList<String>(); 703 if (groups) { 704 final List<PermissionGroupInfo> infos = 705 mInterface.getAllPermissionGroups(0 /*flags*/).getList(); 706 final int count = infos.size(); 707 for (int i = 0; i < count; i++) { 708 groupList.add(infos.get(i).name); 709 } 710 groupList.add(null); 711 } else { 712 final String grp = getNextArg(); 713 groupList.add(grp); 714 } 715 716 if (dangerousOnly) { 717 pw.println("Dangerous Permissions:"); 718 pw.println(""); 719 doListPermissions(groupList, groups, labels, summary, 720 PermissionInfo.PROTECTION_DANGEROUS, 721 PermissionInfo.PROTECTION_DANGEROUS); 722 if (userOnly) { 723 pw.println("Normal Permissions:"); 724 pw.println(""); 725 doListPermissions(groupList, groups, labels, summary, 726 PermissionInfo.PROTECTION_NORMAL, 727 PermissionInfo.PROTECTION_NORMAL); 728 } 729 } else if (userOnly) { 730 pw.println("Dangerous and Normal Permissions:"); 731 pw.println(""); 732 doListPermissions(groupList, groups, labels, summary, 733 PermissionInfo.PROTECTION_NORMAL, 734 PermissionInfo.PROTECTION_DANGEROUS); 735 } else { 736 pw.println("All Permissions:"); 737 pw.println(""); 738 doListPermissions(groupList, groups, labels, summary, 739 -10000, 10000); 740 } 741 return 0; 742 } 743 744 private int runUninstall() throws RemoteException { 745 final PrintWriter pw = getOutPrintWriter(); 746 int flags = 0; 747 int userId = UserHandle.USER_ALL; 748 749 String opt; 750 while ((opt = getNextOption()) != null) { 751 switch (opt) { 752 case "-k": 753 flags |= PackageManager.DELETE_KEEP_DATA; 754 break; 755 case "--user": 756 userId = UserHandle.parseUserArg(getNextArgRequired()); 757 break; 758 default: 759 pw.println("Error: Unknown option: " + opt); 760 return 1; 761 } 762 } 763 764 final String packageName = getNextArg(); 765 if (packageName == null) { 766 pw.println("Error: package name not specified"); 767 return 1; 768 } 769 770 // if a split is specified, just remove it and not the whole package 771 final String splitName = getNextArg(); 772 if (splitName != null) { 773 return runRemoveSplit(packageName, splitName); 774 } 775 776 userId = translateUserId(userId, "runUninstall"); 777 if (userId == UserHandle.USER_ALL) { 778 userId = UserHandle.USER_SYSTEM; 779 flags |= PackageManager.DELETE_ALL_USERS; 780 } else { 781 final PackageInfo info = mInterface.getPackageInfo(packageName, 0, userId); 782 if (info == null) { 783 pw.println("Failure [not installed for " + userId + "]"); 784 return 1; 785 } 786 final boolean isSystem = 787 (info.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0; 788 // If we are being asked to delete a system app for just one 789 // user set flag so it disables rather than reverting to system 790 // version of the app. 791 if (isSystem) { 792 flags |= PackageManager.DELETE_SYSTEM_APP; 793 } 794 } 795 796 final LocalIntentReceiver receiver = new LocalIntentReceiver(); 797 mInterface.getPackageInstaller().uninstall(packageName, null /*callerPackageName*/, flags, 798 receiver.getIntentSender(), userId); 799 800 final Intent result = receiver.getResult(); 801 final int status = result.getIntExtra(PackageInstaller.EXTRA_STATUS, 802 PackageInstaller.STATUS_FAILURE); 803 if (status == PackageInstaller.STATUS_SUCCESS) { 804 pw.println("Success"); 805 return 0; 806 } else { 807 pw.println("Failure [" 808 + result.getStringExtra(PackageInstaller.EXTRA_STATUS_MESSAGE) + "]"); 809 return 1; 810 } 811 } 812 813 private int runRemoveSplit(String packageName, String splitName) throws RemoteException { 814 final PrintWriter pw = getOutPrintWriter(); 815 final SessionParams sessionParams = new SessionParams(SessionParams.MODE_INHERIT_EXISTING); 816 sessionParams.installFlags |= PackageManager.INSTALL_REPLACE_EXISTING; 817 sessionParams.appPackageName = packageName; 818 final int sessionId = 819 doCreateSession(sessionParams, null /*installerPackageName*/, UserHandle.USER_ALL); 820 boolean abandonSession = true; 821 try { 822 if (doRemoveSplit(sessionId, splitName, false /*logSuccess*/) 823 != PackageInstaller.STATUS_SUCCESS) { 824 return 1; 825 } 826 if (doCommitSession(sessionId, false /*logSuccess*/) 827 != PackageInstaller.STATUS_SUCCESS) { 828 return 1; 829 } 830 abandonSession = false; 831 pw.println("Success"); 832 return 0; 833 } finally { 834 if (abandonSession) { 835 try { 836 doAbandonSession(sessionId, false /*logSuccess*/); 837 } catch (Exception ignore) { 838 } 839 } 840 } 841 } 842 843 private Intent parseIntentAndUser() throws URISyntaxException { 844 mTargetUser = UserHandle.USER_CURRENT; 845 Intent intent = Intent.parseCommandArgs(this, new Intent.CommandOptionHandler() { 846 @Override 847 public boolean handleOption(String opt, ShellCommand cmd) { 848 if ("--user".equals(opt)) { 849 mTargetUser = UserHandle.parseUserArg(cmd.getNextArgRequired()); 850 return true; 851 } 852 return false; 853 } 854 }); 855 mTargetUser = ActivityManager.handleIncomingUser(Binder.getCallingPid(), 856 Binder.getCallingUid(), mTargetUser, false, false, null, null); 857 return intent; 858 } 859 860 private int runResolveActivity() { 861 Intent intent; 862 try { 863 intent = parseIntentAndUser(); 864 } catch (URISyntaxException e) { 865 throw new RuntimeException(e.getMessage(), e); 866 } 867 try { 868 ResolveInfo ri = mInterface.resolveIntent(intent, null, 0, mTargetUser); 869 PrintWriter pw = getOutPrintWriter(); 870 if (ri == null) { 871 pw.println("No activity found"); 872 } else { 873 PrintWriterPrinter pr = new PrintWriterPrinter(pw); 874 ri.dump(pr, ""); 875 } 876 } catch (RemoteException e) { 877 throw new RuntimeException("Failed calling service", e); 878 } 879 return 0; 880 } 881 882 private int runQueryIntentActivities() { 883 Intent intent; 884 try { 885 intent = parseIntentAndUser(); 886 } catch (URISyntaxException e) { 887 throw new RuntimeException(e.getMessage(), e); 888 } 889 try { 890 List<ResolveInfo> result = mInterface.queryIntentActivities(intent, null, 0, 891 mTargetUser).getList(); 892 PrintWriter pw = getOutPrintWriter(); 893 if (result == null || result.size() <= 0) { 894 pw.println("No activities found"); 895 } else { 896 pw.print(result.size()); pw.println(" activities found:"); 897 PrintWriterPrinter pr = new PrintWriterPrinter(pw); 898 for (int i=0; i<result.size(); i++) { 899 pw.print(" Activity #"); pw.print(i); pw.println(":"); 900 result.get(i).dump(pr, " "); 901 } 902 } 903 } catch (RemoteException e) { 904 throw new RuntimeException("Failed calling service", e); 905 } 906 return 0; 907 } 908 909 private int runQueryIntentServices() { 910 Intent intent; 911 try { 912 intent = parseIntentAndUser(); 913 } catch (URISyntaxException e) { 914 throw new RuntimeException(e.getMessage(), e); 915 } 916 try { 917 List<ResolveInfo> result = mInterface.queryIntentServices(intent, null, 0, 918 mTargetUser).getList(); 919 PrintWriter pw = getOutPrintWriter(); 920 if (result == null || result.size() <= 0) { 921 pw.println("No services found"); 922 } else { 923 pw.print(result.size()); pw.println(" services found:"); 924 PrintWriterPrinter pr = new PrintWriterPrinter(pw); 925 for (int i=0; i<result.size(); i++) { 926 pw.print(" Service #"); pw.print(i); pw.println(":"); 927 result.get(i).dump(pr, " "); 928 } 929 } 930 } catch (RemoteException e) { 931 throw new RuntimeException("Failed calling service", e); 932 } 933 return 0; 934 } 935 936 private int runQueryIntentReceivers() { 937 Intent intent; 938 try { 939 intent = parseIntentAndUser(); 940 } catch (URISyntaxException e) { 941 throw new RuntimeException(e.getMessage(), e); 942 } 943 try { 944 List<ResolveInfo> result = mInterface.queryIntentReceivers(intent, null, 0, 945 mTargetUser).getList(); 946 PrintWriter pw = getOutPrintWriter(); 947 if (result == null || result.size() <= 0) { 948 pw.println("No receivers found"); 949 } else { 950 pw.print(result.size()); pw.println(" receivers found:"); 951 PrintWriterPrinter pr = new PrintWriterPrinter(pw); 952 for (int i=0; i<result.size(); i++) { 953 pw.print(" Receiver #"); pw.print(i); pw.println(":"); 954 result.get(i).dump(pr, " "); 955 } 956 } 957 } catch (RemoteException e) { 958 throw new RuntimeException("Failed calling service", e); 959 } 960 return 0; 961 } 962 963 private static class InstallParams { 964 SessionParams sessionParams; 965 String installerPackageName; 966 int userId = UserHandle.USER_ALL; 967 } 968 969 private InstallParams makeInstallParams() { 970 final SessionParams sessionParams = new SessionParams(SessionParams.MODE_FULL_INSTALL); 971 final InstallParams params = new InstallParams(); 972 params.sessionParams = sessionParams; 973 String opt; 974 while ((opt = getNextOption()) != null) { 975 switch (opt) { 976 case "-l": 977 sessionParams.installFlags |= PackageManager.INSTALL_FORWARD_LOCK; 978 break; 979 case "-r": 980 sessionParams.installFlags |= PackageManager.INSTALL_REPLACE_EXISTING; 981 break; 982 case "-i": 983 params.installerPackageName = getNextArg(); 984 if (params.installerPackageName == null) { 985 throw new IllegalArgumentException("Missing installer package"); 986 } 987 break; 988 case "-t": 989 sessionParams.installFlags |= PackageManager.INSTALL_ALLOW_TEST; 990 break; 991 case "-s": 992 sessionParams.installFlags |= PackageManager.INSTALL_EXTERNAL; 993 break; 994 case "-f": 995 sessionParams.installFlags |= PackageManager.INSTALL_INTERNAL; 996 break; 997 case "-d": 998 sessionParams.installFlags |= PackageManager.INSTALL_ALLOW_DOWNGRADE; 999 break; 1000 case "-g": 1001 sessionParams.installFlags |= PackageManager.INSTALL_GRANT_RUNTIME_PERMISSIONS; 1002 break; 1003 case "--dont-kill": 1004 sessionParams.installFlags |= PackageManager.INSTALL_DONT_KILL_APP; 1005 break; 1006 case "--originating-uri": 1007 sessionParams.originatingUri = Uri.parse(getNextArg()); 1008 break; 1009 case "--referrer": 1010 sessionParams.referrerUri = Uri.parse(getNextArg()); 1011 break; 1012 case "-p": 1013 sessionParams.mode = SessionParams.MODE_INHERIT_EXISTING; 1014 sessionParams.appPackageName = getNextArg(); 1015 if (sessionParams.appPackageName == null) { 1016 throw new IllegalArgumentException("Missing inherit package name"); 1017 } 1018 break; 1019 case "-S": 1020 sessionParams.setSize(Long.parseLong(getNextArg())); 1021 break; 1022 case "--abi": 1023 sessionParams.abiOverride = checkAbiArgument(getNextArg()); 1024 break; 1025 case "--ephemeral": 1026 sessionParams.installFlags |= PackageManager.INSTALL_EPHEMERAL; 1027 break; 1028 case "--user": 1029 params.userId = UserHandle.parseUserArg(getNextArgRequired()); 1030 break; 1031 case "--install-location": 1032 sessionParams.installLocation = Integer.parseInt(getNextArg()); 1033 break; 1034 case "--force-uuid": 1035 sessionParams.installFlags |= PackageManager.INSTALL_FORCE_VOLUME_UUID; 1036 sessionParams.volumeUuid = getNextArg(); 1037 if ("internal".equals(sessionParams.volumeUuid)) { 1038 sessionParams.volumeUuid = null; 1039 } 1040 break; 1041 case "--force-sdk": 1042 sessionParams.installFlags |= PackageManager.INSTALL_FORCE_SDK; 1043 break; 1044 default: 1045 throw new IllegalArgumentException("Unknown option " + opt); 1046 } 1047 } 1048 return params; 1049 } 1050 1051 private int runSetHomeActivity() { 1052 final PrintWriter pw = getOutPrintWriter(); 1053 int userId = UserHandle.USER_SYSTEM; 1054 String opt; 1055 while ((opt = getNextOption()) != null) { 1056 switch (opt) { 1057 case "--user": 1058 userId = UserHandle.parseUserArg(getNextArgRequired()); 1059 break; 1060 default: 1061 pw.println("Error: Unknown option: " + opt); 1062 return 1; 1063 } 1064 } 1065 1066 String component = getNextArg(); 1067 ComponentName componentName = 1068 component != null ? ComponentName.unflattenFromString(component) : null; 1069 1070 if (componentName == null) { 1071 pw.println("Error: component name not specified or invalid"); 1072 return 1; 1073 } 1074 1075 try { 1076 mInterface.setHomeActivity(componentName, userId); 1077 return 0; 1078 } catch (RemoteException e) { 1079 pw.println(e.toString()); 1080 return 1; 1081 } 1082 } 1083 1084 private static String checkAbiArgument(String abi) { 1085 if (TextUtils.isEmpty(abi)) { 1086 throw new IllegalArgumentException("Missing ABI argument"); 1087 } 1088 1089 if ("-".equals(abi)) { 1090 return abi; 1091 } 1092 1093 final String[] supportedAbis = Build.SUPPORTED_ABIS; 1094 for (String supportedAbi : supportedAbis) { 1095 if (supportedAbi.equals(abi)) { 1096 return abi; 1097 } 1098 } 1099 1100 throw new IllegalArgumentException("ABI " + abi + " not supported on this device"); 1101 } 1102 1103 private int translateUserId(int userId, String logContext) { 1104 return ActivityManager.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), 1105 userId, true, true, logContext, "pm command"); 1106 } 1107 1108 private int doCreateSession(SessionParams params, String installerPackageName, int userId) 1109 throws RemoteException { 1110 userId = translateUserId(userId, "runInstallCreate"); 1111 if (userId == UserHandle.USER_ALL) { 1112 userId = UserHandle.USER_SYSTEM; 1113 params.installFlags |= PackageManager.INSTALL_ALL_USERS; 1114 } 1115 1116 final int sessionId = mInterface.getPackageInstaller() 1117 .createSession(params, installerPackageName, userId); 1118 return sessionId; 1119 } 1120 1121 private int doWriteSplit(int sessionId, String inPath, long sizeBytes, String splitName, 1122 boolean logSuccess) throws RemoteException { 1123 final PrintWriter pw = getOutPrintWriter(); 1124 if ("-".equals(inPath)) { 1125 inPath = null; 1126 } else if (inPath != null) { 1127 final File file = new File(inPath); 1128 if (file.isFile()) { 1129 sizeBytes = file.length(); 1130 } 1131 } 1132 1133 final SessionInfo info = mInterface.getPackageInstaller().getSessionInfo(sessionId); 1134 1135 PackageInstaller.Session session = null; 1136 InputStream in = null; 1137 OutputStream out = null; 1138 try { 1139 session = new PackageInstaller.Session( 1140 mInterface.getPackageInstaller().openSession(sessionId)); 1141 1142 if (inPath != null) { 1143 in = new FileInputStream(inPath); 1144 } else { 1145 in = new SizedInputStream(getRawInputStream(), sizeBytes); 1146 } 1147 out = session.openWrite(splitName, 0, sizeBytes); 1148 1149 int total = 0; 1150 byte[] buffer = new byte[65536]; 1151 int c; 1152 while ((c = in.read(buffer)) != -1) { 1153 total += c; 1154 out.write(buffer, 0, c); 1155 1156 if (info.sizeBytes > 0) { 1157 final float fraction = ((float) c / (float) info.sizeBytes); 1158 session.addProgress(fraction); 1159 } 1160 } 1161 session.fsync(out); 1162 1163 if (logSuccess) { 1164 pw.println("Success: streamed " + total + " bytes"); 1165 } 1166 return 0; 1167 } catch (IOException e) { 1168 pw.println("Error: failed to write; " + e.getMessage()); 1169 return 1; 1170 } finally { 1171 IoUtils.closeQuietly(out); 1172 IoUtils.closeQuietly(in); 1173 IoUtils.closeQuietly(session); 1174 } 1175 } 1176 1177 private int doRemoveSplit(int sessionId, String splitName, boolean logSuccess) 1178 throws RemoteException { 1179 final PrintWriter pw = getOutPrintWriter(); 1180 PackageInstaller.Session session = null; 1181 try { 1182 session = new PackageInstaller.Session( 1183 mInterface.getPackageInstaller().openSession(sessionId)); 1184 session.removeSplit(splitName); 1185 1186 if (logSuccess) { 1187 pw.println("Success"); 1188 } 1189 return 0; 1190 } catch (IOException e) { 1191 pw.println("Error: failed to remove split; " + e.getMessage()); 1192 return 1; 1193 } finally { 1194 IoUtils.closeQuietly(session); 1195 } 1196 } 1197 1198 private int doCommitSession(int sessionId, boolean logSuccess) throws RemoteException { 1199 final PrintWriter pw = getOutPrintWriter(); 1200 PackageInstaller.Session session = null; 1201 try { 1202 session = new PackageInstaller.Session( 1203 mInterface.getPackageInstaller().openSession(sessionId)); 1204 1205 final LocalIntentReceiver receiver = new LocalIntentReceiver(); 1206 session.commit(receiver.getIntentSender()); 1207 1208 final Intent result = receiver.getResult(); 1209 final int status = result.getIntExtra(PackageInstaller.EXTRA_STATUS, 1210 PackageInstaller.STATUS_FAILURE); 1211 if (status == PackageInstaller.STATUS_SUCCESS) { 1212 if (logSuccess) { 1213 System.out.println("Success"); 1214 } 1215 } else { 1216 pw.println("Failure [" 1217 + result.getStringExtra(PackageInstaller.EXTRA_STATUS_MESSAGE) + "]"); 1218 } 1219 return status; 1220 } finally { 1221 IoUtils.closeQuietly(session); 1222 } 1223 } 1224 1225 private int doAbandonSession(int sessionId, boolean logSuccess) throws RemoteException { 1226 final PrintWriter pw = getOutPrintWriter(); 1227 PackageInstaller.Session session = null; 1228 try { 1229 session = new PackageInstaller.Session( 1230 mInterface.getPackageInstaller().openSession(sessionId)); 1231 session.abandon(); 1232 if (logSuccess) { 1233 pw.println("Success"); 1234 } 1235 return 0; 1236 } finally { 1237 IoUtils.closeQuietly(session); 1238 } 1239 } 1240 1241 private void doListPermissions(ArrayList<String> groupList, boolean groups, boolean labels, 1242 boolean summary, int startProtectionLevel, int endProtectionLevel) 1243 throws RemoteException { 1244 final PrintWriter pw = getOutPrintWriter(); 1245 final int groupCount = groupList.size(); 1246 for (int i = 0; i < groupCount; i++) { 1247 String groupName = groupList.get(i); 1248 String prefix = ""; 1249 if (groups) { 1250 if (i > 0) { 1251 pw.println(""); 1252 } 1253 if (groupName != null) { 1254 PermissionGroupInfo pgi = 1255 mInterface.getPermissionGroupInfo(groupName, 0 /*flags*/); 1256 if (summary) { 1257 Resources res = getResources(pgi); 1258 if (res != null) { 1259 pw.print(loadText(pgi, pgi.labelRes, pgi.nonLocalizedLabel) + ": "); 1260 } else { 1261 pw.print(pgi.name + ": "); 1262 1263 } 1264 } else { 1265 pw.println((labels ? "+ " : "") + "group:" + pgi.name); 1266 if (labels) { 1267 pw.println(" package:" + pgi.packageName); 1268 Resources res = getResources(pgi); 1269 if (res != null) { 1270 pw.println(" label:" 1271 + loadText(pgi, pgi.labelRes, pgi.nonLocalizedLabel)); 1272 pw.println(" description:" 1273 + loadText(pgi, pgi.descriptionRes, 1274 pgi.nonLocalizedDescription)); 1275 } 1276 } 1277 } 1278 } else { 1279 pw.println(((labels && !summary) ? "+ " : "") + "ungrouped:"); 1280 } 1281 prefix = " "; 1282 } 1283 List<PermissionInfo> ps = 1284 mInterface.queryPermissionsByGroup(groupList.get(i), 0 /*flags*/).getList(); 1285 final int count = ps.size(); 1286 boolean first = true; 1287 for (int p = 0 ; p < count ; p++) { 1288 PermissionInfo pi = ps.get(p); 1289 if (groups && groupName == null && pi.group != null) { 1290 continue; 1291 } 1292 final int base = pi.protectionLevel & PermissionInfo.PROTECTION_MASK_BASE; 1293 if (base < startProtectionLevel 1294 || base > endProtectionLevel) { 1295 continue; 1296 } 1297 if (summary) { 1298 if (first) { 1299 first = false; 1300 } else { 1301 pw.print(", "); 1302 } 1303 Resources res = getResources(pi); 1304 if (res != null) { 1305 pw.print(loadText(pi, pi.labelRes, 1306 pi.nonLocalizedLabel)); 1307 } else { 1308 pw.print(pi.name); 1309 } 1310 } else { 1311 pw.println(prefix + (labels ? "+ " : "") 1312 + "permission:" + pi.name); 1313 if (labels) { 1314 pw.println(prefix + " package:" + pi.packageName); 1315 Resources res = getResources(pi); 1316 if (res != null) { 1317 pw.println(prefix + " label:" 1318 + loadText(pi, pi.labelRes, 1319 pi.nonLocalizedLabel)); 1320 pw.println(prefix + " description:" 1321 + loadText(pi, pi.descriptionRes, 1322 pi.nonLocalizedDescription)); 1323 } 1324 pw.println(prefix + " protectionLevel:" 1325 + PermissionInfo.protectionToString(pi.protectionLevel)); 1326 } 1327 } 1328 } 1329 1330 if (summary) { 1331 pw.println(""); 1332 } 1333 } 1334 } 1335 1336 private String loadText(PackageItemInfo pii, int res, CharSequence nonLocalized) 1337 throws RemoteException { 1338 if (nonLocalized != null) { 1339 return nonLocalized.toString(); 1340 } 1341 if (res != 0) { 1342 Resources r = getResources(pii); 1343 if (r != null) { 1344 try { 1345 return r.getString(res); 1346 } catch (Resources.NotFoundException e) { 1347 } 1348 } 1349 } 1350 return null; 1351 } 1352 1353 private Resources getResources(PackageItemInfo pii) throws RemoteException { 1354 Resources res = mResourceCache.get(pii.packageName); 1355 if (res != null) return res; 1356 1357 ApplicationInfo ai = mInterface.getApplicationInfo(pii.packageName, 0, 0); 1358 AssetManager am = new AssetManager(); 1359 am.addAssetPath(ai.publicSourceDir); 1360 res = new Resources(am, null, null); 1361 mResourceCache.put(pii.packageName, res); 1362 return res; 1363 } 1364 1365 @Override 1366 public void onHelp() { 1367 final PrintWriter pw = getOutPrintWriter(); 1368 pw.println("Package manager (package) commands:"); 1369 pw.println(" help"); 1370 pw.println(" Print this help text."); 1371 pw.println(""); 1372 pw.println(" compile [-m MODE] [-f] [-c] [--reset] (-a | TARGET-PACKAGE)"); 1373 pw.println(" Trigger compilation of TARGET-PACKAGE or all packages if \"-a\"."); 1374 pw.println(" Options:"); 1375 pw.println(" -a: compile all packages"); 1376 pw.println(" -c: clear profile data before compiling"); 1377 pw.println(" -f: force compilation even if not needed"); 1378 pw.println(" -m: select compilation mode"); 1379 pw.println(" MODE can be one of \"default\", \"full\", \"profile\"," + 1380 " and \"extract\""); 1381 pw.println(" --reset: restore package to its post-install state"); 1382 pw.println(" shorthand for \"-c -f -m extract\""); 1383 pw.println(" list features"); 1384 pw.println(" Prints all features of the system."); 1385 pw.println(" list instrumentation [-f] [TARGET-PACKAGE]"); 1386 pw.println(" Prints all test packages; optionally only those targeting TARGET-PACKAGE"); 1387 pw.println(" Options:"); 1388 pw.println(" -f: dump the name of the .apk file containing the test package"); 1389 pw.println(" list libraries"); 1390 pw.println(" Prints all system libraries."); 1391 pw.println(" list packages [-f] [-d] [-e] [-s] [-3] [-i] [-u] [--user USER_ID] [FILTER]"); 1392 pw.println(" Prints all packages; optionally only those whose name contains"); 1393 pw.println(" the text in FILTER."); 1394 pw.println(" Options:"); 1395 pw.println(" -f: see their associated file"); 1396 pw.println(" -d: filter to only show disabled packages"); 1397 pw.println(" -e: filter to only show enabled packages"); 1398 pw.println(" -s: filter to only show system packages"); 1399 pw.println(" -3: filter to only show third party packages"); 1400 pw.println(" -i: see the installer for the packages"); 1401 pw.println(" -u: also include uninstalled packages"); 1402 pw.println(" list permission-groups"); 1403 pw.println(" Prints all known permission groups."); 1404 pw.println(" list permissions [-g] [-f] [-d] [-u] [GROUP]"); 1405 pw.println(" Prints all known permissions; optionally only those in GROUP."); 1406 pw.println(" Options:"); 1407 pw.println(" -g: organize by group"); 1408 pw.println(" -f: print all information"); 1409 pw.println(" -s: short summary"); 1410 pw.println(" -d: only list dangerous permissions"); 1411 pw.println(" -u: list only the permissions users will see"); 1412 pw.println(" resolve-activity [--user USER_ID] INTENT"); 1413 pw.println(" Prints the activity that resolves to the given Intent."); 1414 pw.println(" query-activities [--user USER_ID] INTENT"); 1415 pw.println(" Prints all activities that can handle the given Intent."); 1416 pw.println(" query-services [--user USER_ID] INTENT"); 1417 pw.println(" Prints all services that can handle the given Intent."); 1418 pw.println(" query-receivers [--user USER_ID] INTENT"); 1419 pw.println(" Prints all broadcast receivers that can handle the given Intent."); 1420 pw.println(" suspend [--user USER_ID] TARGET-PACKAGE"); 1421 pw.println(" Suspends the specified package (as user)."); 1422 pw.println(" unsuspend [--user USER_ID] TARGET-PACKAGE"); 1423 pw.println(" Unsuspends the specified package (as user)."); 1424 pw.println(" set-home-activity [--user USER_ID] TARGET-COMPONENT"); 1425 pw.println(" set the default home activity (aka launcher)."); 1426 pw.println(); 1427 Intent.printIntentArgsHelp(pw , ""); 1428 } 1429 1430 private static class LocalIntentReceiver { 1431 private final SynchronousQueue<Intent> mResult = new SynchronousQueue<>(); 1432 1433 private IIntentSender.Stub mLocalSender = new IIntentSender.Stub() { 1434 @Override 1435 public int send(int code, Intent intent, String resolvedType, 1436 IIntentReceiver finishedReceiver, String requiredPermission, Bundle options) { 1437 try { 1438 mResult.offer(intent, 5, TimeUnit.SECONDS); 1439 } catch (InterruptedException e) { 1440 throw new RuntimeException(e); 1441 } 1442 return 0; 1443 } 1444 }; 1445 1446 public IntentSender getIntentSender() { 1447 return new IntentSender((IIntentSender) mLocalSender); 1448 } 1449 1450 public Intent getResult() { 1451 try { 1452 return mResult.take(); 1453 } catch (InterruptedException e) { 1454 throw new RuntimeException(e); 1455 } 1456 } 1457 } 1458} 1459