PackageManagerShellCommand.java revision 78a72501af2e874868c6885d5af4f9253ce92255
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.PackageParser; 34import android.content.pm.PackageParser.ApkLite; 35import android.content.pm.PackageParser.PackageLite; 36import android.content.pm.PackageParser.PackageParserException; 37import android.content.pm.ParceledListSlice; 38import android.content.pm.PermissionGroupInfo; 39import android.content.pm.PermissionInfo; 40import android.content.pm.PackageInstaller.SessionInfo; 41import android.content.pm.PackageInstaller.SessionParams; 42import android.content.pm.PackageManager.NameNotFoundException; 43import android.content.pm.ResolveInfo; 44import android.content.pm.VersionedPackage; 45import android.content.res.AssetManager; 46import android.content.res.Resources; 47import android.net.Uri; 48import android.os.Binder; 49import android.os.Build; 50import android.os.Bundle; 51import android.os.IBinder; 52import android.os.RemoteException; 53import android.os.ShellCommand; 54import android.os.SystemProperties; 55import android.os.UserHandle; 56import android.text.TextUtils; 57import android.util.ArraySet; 58import android.util.PrintWriterPrinter; 59import com.android.internal.content.PackageHelper; 60import com.android.internal.util.SizedInputStream; 61import com.android.server.SystemConfig; 62 63import dalvik.system.DexFile; 64 65import libcore.io.IoUtils; 66 67import java.io.File; 68import java.io.FileInputStream; 69import java.io.IOException; 70import java.io.InputStream; 71import java.io.OutputStream; 72import java.io.PrintWriter; 73import java.net.URISyntaxException; 74import java.util.ArrayList; 75import java.util.Collections; 76import java.util.Comparator; 77import java.util.List; 78import java.util.WeakHashMap; 79import java.util.concurrent.SynchronousQueue; 80import java.util.concurrent.TimeUnit; 81 82class PackageManagerShellCommand extends ShellCommand { 83 /** Path for streaming APK content */ 84 private static final String STDIN_PATH = "-"; 85 /** Whether or not APK content must be streamed from stdin */ 86 private static final boolean FORCE_STREAM_INSTALL = true; 87 88 final IPackageManager mInterface; 89 final private WeakHashMap<String, Resources> mResourceCache = 90 new WeakHashMap<String, Resources>(); 91 int mTargetUser; 92 boolean mBrief; 93 boolean mComponents; 94 95 PackageManagerShellCommand(PackageManagerService service) { 96 mInterface = service; 97 } 98 99 @Override 100 public int onCommand(String cmd) { 101 if (cmd == null) { 102 return handleDefaultCommands(cmd); 103 } 104 105 final PrintWriter pw = getOutPrintWriter(); 106 try { 107 switch(cmd) { 108 case "install": 109 return runInstall(); 110 case "install-abandon": 111 case "install-destroy": 112 return runInstallAbandon(); 113 case "install-commit": 114 return runInstallCommit(); 115 case "install-create": 116 return runInstallCreate(); 117 case "install-remove": 118 return runInstallRemove(); 119 case "install-write": 120 return runInstallWrite(); 121 case "install-existing": 122 return runInstallExisting(); 123 case "compile": 124 return runCompile(); 125 case "reconcile-secondary-dex-files": 126 return runreconcileSecondaryDexFiles(); 127 case "bg-dexopt-job": 128 return runDexoptJob(); 129 case "dump-profiles": 130 return runDumpProfiles(); 131 case "list": 132 return runList(); 133 case "uninstall": 134 return runUninstall(); 135 case "resolve-activity": 136 return runResolveActivity(); 137 case "query-activities": 138 return runQueryIntentActivities(); 139 case "query-services": 140 return runQueryIntentServices(); 141 case "query-receivers": 142 return runQueryIntentReceivers(); 143 case "suspend": 144 return runSuspend(true); 145 case "unsuspend": 146 return runSuspend(false); 147 case "set-home-activity": 148 return runSetHomeActivity(); 149 case "get-privapp-permissions": 150 return runGetPrivappPermissions(); 151 case "get-instantapp-resolver": 152 return runGetInstantAppResolver(); 153 case "has-feature": 154 return runHasFeature(); 155 default: 156 return handleDefaultCommands(cmd); 157 } 158 } catch (RemoteException e) { 159 pw.println("Remote exception: " + e); 160 } 161 return -1; 162 } 163 164 private void setParamsSize(InstallParams params, String inPath) { 165 // If we're forced to stream the package, the params size 166 // must be set via command-line argument. There's nothing 167 // to do here. 168 if (FORCE_STREAM_INSTALL) { 169 return; 170 } 171 final PrintWriter pw = getOutPrintWriter(); 172 if (params.sessionParams.sizeBytes == -1 && !STDIN_PATH.equals(inPath)) { 173 File file = new File(inPath); 174 if (file.isFile()) { 175 try { 176 ApkLite baseApk = PackageParser.parseApkLite(file, 0); 177 PackageLite pkgLite = new PackageLite(null, baseApk, null, null, null, null, 178 null, null, null); 179 params.sessionParams.setSize(PackageHelper.calculateInstalledSize( 180 pkgLite, false, params.sessionParams.abiOverride)); 181 } catch (PackageParserException | IOException e) { 182 pw.println("Error: Failed to parse APK file: " + file); 183 throw new IllegalArgumentException( 184 "Error: Failed to parse APK file: " + file, e); 185 } 186 } else { 187 pw.println("Error: Can't open non-file: " + inPath); 188 throw new IllegalArgumentException("Error: Can't open non-file: " + inPath); 189 } 190 } 191 } 192 193 private int runInstall() throws RemoteException { 194 final PrintWriter pw = getOutPrintWriter(); 195 final InstallParams params = makeInstallParams(); 196 final String inPath = getNextArg(); 197 198 setParamsSize(params, inPath); 199 final int sessionId = doCreateSession(params.sessionParams, 200 params.installerPackageName, params.userId); 201 boolean abandonSession = true; 202 try { 203 if (inPath == null && params.sessionParams.sizeBytes == -1) { 204 pw.println("Error: must either specify a package size or an APK file"); 205 return 1; 206 } 207 if (doWriteSplit(sessionId, inPath, params.sessionParams.sizeBytes, "base.apk", 208 false /*logSuccess*/) != PackageInstaller.STATUS_SUCCESS) { 209 return 1; 210 } 211 if (doCommitSession(sessionId, false /*logSuccess*/) 212 != PackageInstaller.STATUS_SUCCESS) { 213 return 1; 214 } 215 abandonSession = false; 216 pw.println("Success"); 217 return 0; 218 } finally { 219 if (abandonSession) { 220 try { 221 doAbandonSession(sessionId, false /*logSuccess*/); 222 } catch (Exception ignore) { 223 } 224 } 225 } 226 } 227 228 private int runSuspend(boolean suspendedState) { 229 final PrintWriter pw = getOutPrintWriter(); 230 int userId = UserHandle.USER_SYSTEM; 231 String opt; 232 while ((opt = getNextOption()) != null) { 233 switch (opt) { 234 case "--user": 235 userId = UserHandle.parseUserArg(getNextArgRequired()); 236 break; 237 default: 238 pw.println("Error: Unknown option: " + opt); 239 return 1; 240 } 241 } 242 243 String packageName = getNextArg(); 244 if (packageName == null) { 245 pw.println("Error: package name not specified"); 246 return 1; 247 } 248 249 try { 250 mInterface.setPackagesSuspendedAsUser(new String[]{packageName}, suspendedState, 251 userId); 252 pw.println("Package " + packageName + " new suspended state: " 253 + mInterface.isPackageSuspendedForUser(packageName, userId)); 254 return 0; 255 } catch (RemoteException | IllegalArgumentException e) { 256 pw.println(e.toString()); 257 return 1; 258 } 259 } 260 261 private int runInstallAbandon() throws RemoteException { 262 final int sessionId = Integer.parseInt(getNextArg()); 263 return doAbandonSession(sessionId, true /*logSuccess*/); 264 } 265 266 private int runInstallCommit() throws RemoteException { 267 final int sessionId = Integer.parseInt(getNextArg()); 268 return doCommitSession(sessionId, true /*logSuccess*/); 269 } 270 271 private int runInstallCreate() throws RemoteException { 272 final PrintWriter pw = getOutPrintWriter(); 273 final InstallParams installParams = makeInstallParams(); 274 final int sessionId = doCreateSession(installParams.sessionParams, 275 installParams.installerPackageName, installParams.userId); 276 277 // NOTE: adb depends on parsing this string 278 pw.println("Success: created install session [" + sessionId + "]"); 279 return 0; 280 } 281 282 private int runInstallWrite() throws RemoteException { 283 long sizeBytes = -1; 284 285 String opt; 286 while ((opt = getNextOption()) != null) { 287 if (opt.equals("-S")) { 288 sizeBytes = Long.parseLong(getNextArg()); 289 } else { 290 throw new IllegalArgumentException("Unknown option: " + opt); 291 } 292 } 293 294 final int sessionId = Integer.parseInt(getNextArg()); 295 final String splitName = getNextArg(); 296 final String path = getNextArg(); 297 return doWriteSplit(sessionId, path, sizeBytes, splitName, true /*logSuccess*/); 298 } 299 300 private int runInstallRemove() throws RemoteException { 301 final PrintWriter pw = getOutPrintWriter(); 302 303 final int sessionId = Integer.parseInt(getNextArg()); 304 305 final String splitName = getNextArg(); 306 if (splitName == null) { 307 pw.println("Error: split name not specified"); 308 return 1; 309 } 310 return doRemoveSplit(sessionId, splitName, true /*logSuccess*/); 311 } 312 313 private int runInstallExisting() throws RemoteException { 314 final PrintWriter pw = getOutPrintWriter(); 315 int userId = UserHandle.USER_SYSTEM; 316 int installFlags = 0; 317 String opt; 318 while ((opt = getNextOption()) != null) { 319 switch (opt) { 320 case "--user": 321 userId = UserHandle.parseUserArg(getNextArgRequired()); 322 break; 323 case "--ephemeral": 324 case "--instant": 325 installFlags |= PackageManager.INSTALL_INSTANT_APP; 326 installFlags &= ~PackageManager.INSTALL_FULL_APP; 327 break; 328 case "--full": 329 installFlags &= ~PackageManager.INSTALL_INSTANT_APP; 330 installFlags |= PackageManager.INSTALL_FULL_APP; 331 break; 332 default: 333 pw.println("Error: Unknown option: " + opt); 334 return 1; 335 } 336 } 337 338 final String packageName = getNextArg(); 339 if (packageName == null) { 340 pw.println("Error: package name not specified"); 341 return 1; 342 } 343 344 try { 345 final int res = mInterface.installExistingPackageAsUser(packageName, userId, 346 installFlags, PackageManager.INSTALL_REASON_UNKNOWN); 347 if (res == PackageManager.INSTALL_FAILED_INVALID_URI) { 348 throw new NameNotFoundException("Package " + packageName + " doesn't exist"); 349 } 350 pw.println("Package " + packageName + " installed for user: " + userId); 351 return 0; 352 } catch (RemoteException | NameNotFoundException e) { 353 pw.println(e.toString()); 354 return 1; 355 } 356 } 357 358 private int runCompile() throws RemoteException { 359 final PrintWriter pw = getOutPrintWriter(); 360 boolean checkProfiles = SystemProperties.getBoolean("dalvik.vm.usejitprofiles", false); 361 boolean forceCompilation = false; 362 boolean allPackages = false; 363 boolean clearProfileData = false; 364 String compilerFilter = null; 365 String compilationReason = null; 366 String checkProfilesRaw = null; 367 boolean secondaryDex = false; 368 String split = null; 369 370 String opt; 371 while ((opt = getNextOption()) != null) { 372 switch (opt) { 373 case "-a": 374 allPackages = true; 375 break; 376 case "-c": 377 clearProfileData = true; 378 break; 379 case "-f": 380 forceCompilation = true; 381 break; 382 case "-m": 383 compilerFilter = getNextArgRequired(); 384 break; 385 case "-r": 386 compilationReason = getNextArgRequired(); 387 break; 388 case "--check-prof": 389 checkProfilesRaw = getNextArgRequired(); 390 break; 391 case "--reset": 392 forceCompilation = true; 393 clearProfileData = true; 394 compilationReason = "install"; 395 break; 396 case "--secondary-dex": 397 secondaryDex = true; 398 break; 399 case "--split": 400 split = getNextArgRequired(); 401 break; 402 default: 403 pw.println("Error: Unknown option: " + opt); 404 return 1; 405 } 406 } 407 408 if (checkProfilesRaw != null) { 409 if ("true".equals(checkProfilesRaw)) { 410 checkProfiles = true; 411 } else if ("false".equals(checkProfilesRaw)) { 412 checkProfiles = false; 413 } else { 414 pw.println("Invalid value for \"--check-prof\". Expected \"true\" or \"false\"."); 415 return 1; 416 } 417 } 418 419 if (compilerFilter != null && compilationReason != null) { 420 pw.println("Cannot use compilation filter (\"-m\") and compilation reason (\"-r\") " + 421 "at the same time"); 422 return 1; 423 } 424 if (compilerFilter == null && compilationReason == null) { 425 pw.println("Cannot run without any of compilation filter (\"-m\") and compilation " + 426 "reason (\"-r\") at the same time"); 427 return 1; 428 } 429 430 if (allPackages && split != null) { 431 pw.println("-a cannot be specified together with --split"); 432 return 1; 433 } 434 435 if (secondaryDex && split != null) { 436 pw.println("--secondary-dex cannot be specified together with --split"); 437 return 1; 438 } 439 440 String targetCompilerFilter; 441 if (compilerFilter != null) { 442 if (!DexFile.isValidCompilerFilter(compilerFilter)) { 443 pw.println("Error: \"" + compilerFilter + 444 "\" is not a valid compilation filter."); 445 return 1; 446 } 447 targetCompilerFilter = compilerFilter; 448 } else { 449 int reason = -1; 450 for (int i = 0; i < PackageManagerServiceCompilerMapping.REASON_STRINGS.length; i++) { 451 if (PackageManagerServiceCompilerMapping.REASON_STRINGS[i].equals( 452 compilationReason)) { 453 reason = i; 454 break; 455 } 456 } 457 if (reason == -1) { 458 pw.println("Error: Unknown compilation reason: " + compilationReason); 459 return 1; 460 } 461 targetCompilerFilter = 462 PackageManagerServiceCompilerMapping.getCompilerFilterForReason(reason); 463 } 464 465 466 List<String> packageNames = null; 467 if (allPackages) { 468 packageNames = mInterface.getAllPackages(); 469 } else { 470 String packageName = getNextArg(); 471 if (packageName == null) { 472 pw.println("Error: package name not specified"); 473 return 1; 474 } 475 packageNames = Collections.singletonList(packageName); 476 } 477 478 List<String> failedPackages = new ArrayList<>(); 479 for (String packageName : packageNames) { 480 if (clearProfileData) { 481 mInterface.clearApplicationProfileData(packageName); 482 } 483 484 boolean result = secondaryDex 485 ? mInterface.performDexOptSecondary(packageName, 486 targetCompilerFilter, forceCompilation) 487 : mInterface.performDexOptMode(packageName, 488 checkProfiles, targetCompilerFilter, forceCompilation, 489 true /* bootComplete */, split); 490 if (!result) { 491 failedPackages.add(packageName); 492 } 493 } 494 495 if (failedPackages.isEmpty()) { 496 pw.println("Success"); 497 return 0; 498 } else if (failedPackages.size() == 1) { 499 pw.println("Failure: package " + failedPackages.get(0) + " could not be compiled"); 500 return 1; 501 } else { 502 pw.print("Failure: the following packages could not be compiled: "); 503 boolean is_first = true; 504 for (String packageName : failedPackages) { 505 if (is_first) { 506 is_first = false; 507 } else { 508 pw.print(", "); 509 } 510 pw.print(packageName); 511 } 512 pw.println(); 513 return 1; 514 } 515 } 516 517 private int runreconcileSecondaryDexFiles() throws RemoteException { 518 String packageName = getNextArg(); 519 mInterface.reconcileSecondaryDexFiles(packageName); 520 return 0; 521 } 522 523 private int runDexoptJob() throws RemoteException { 524 boolean result = mInterface.runBackgroundDexoptJob(); 525 return result ? 0 : -1; 526 } 527 528 private int runDumpProfiles() throws RemoteException { 529 String packageName = getNextArg(); 530 mInterface.dumpProfiles(packageName); 531 return 0; 532 } 533 534 private int runList() throws RemoteException { 535 final PrintWriter pw = getOutPrintWriter(); 536 final String type = getNextArg(); 537 if (type == null) { 538 pw.println("Error: didn't specify type of data to list"); 539 return -1; 540 } 541 switch(type) { 542 case "features": 543 return runListFeatures(); 544 case "instrumentation": 545 return runListInstrumentation(); 546 case "libraries": 547 return runListLibraries(); 548 case "package": 549 case "packages": 550 return runListPackages(false /*showSourceDir*/); 551 case "permission-groups": 552 return runListPermissionGroups(); 553 case "permissions": 554 return runListPermissions(); 555 } 556 pw.println("Error: unknown list type '" + type + "'"); 557 return -1; 558 } 559 560 private int runListFeatures() throws RemoteException { 561 final PrintWriter pw = getOutPrintWriter(); 562 final List<FeatureInfo> list = mInterface.getSystemAvailableFeatures().getList(); 563 564 // sort by name 565 Collections.sort(list, new Comparator<FeatureInfo>() { 566 public int compare(FeatureInfo o1, FeatureInfo o2) { 567 if (o1.name == o2.name) return 0; 568 if (o1.name == null) return -1; 569 if (o2.name == null) return 1; 570 return o1.name.compareTo(o2.name); 571 } 572 }); 573 574 final int count = (list != null) ? list.size() : 0; 575 for (int p = 0; p < count; p++) { 576 FeatureInfo fi = list.get(p); 577 pw.print("feature:"); 578 if (fi.name != null) { 579 pw.print(fi.name); 580 if (fi.version > 0) { 581 pw.print("="); 582 pw.print(fi.version); 583 } 584 pw.println(); 585 } else { 586 pw.println("reqGlEsVersion=0x" 587 + Integer.toHexString(fi.reqGlEsVersion)); 588 } 589 } 590 return 0; 591 } 592 593 private int runListInstrumentation() throws RemoteException { 594 final PrintWriter pw = getOutPrintWriter(); 595 boolean showSourceDir = false; 596 String targetPackage = null; 597 598 try { 599 String opt; 600 while ((opt = getNextArg()) != null) { 601 switch (opt) { 602 case "-f": 603 showSourceDir = true; 604 break; 605 default: 606 if (opt.charAt(0) != '-') { 607 targetPackage = opt; 608 } else { 609 pw.println("Error: Unknown option: " + opt); 610 return -1; 611 } 612 break; 613 } 614 } 615 } catch (RuntimeException ex) { 616 pw.println("Error: " + ex.toString()); 617 return -1; 618 } 619 620 final List<InstrumentationInfo> list = 621 mInterface.queryInstrumentation(targetPackage, 0 /*flags*/).getList(); 622 623 // sort by target package 624 Collections.sort(list, new Comparator<InstrumentationInfo>() { 625 public int compare(InstrumentationInfo o1, InstrumentationInfo o2) { 626 return o1.targetPackage.compareTo(o2.targetPackage); 627 } 628 }); 629 630 final int count = (list != null) ? list.size() : 0; 631 for (int p = 0; p < count; p++) { 632 final InstrumentationInfo ii = list.get(p); 633 pw.print("instrumentation:"); 634 if (showSourceDir) { 635 pw.print(ii.sourceDir); 636 pw.print("="); 637 } 638 final ComponentName cn = new ComponentName(ii.packageName, ii.name); 639 pw.print(cn.flattenToShortString()); 640 pw.print(" (target="); 641 pw.print(ii.targetPackage); 642 pw.println(")"); 643 } 644 return 0; 645 } 646 647 private int runListLibraries() throws RemoteException { 648 final PrintWriter pw = getOutPrintWriter(); 649 final List<String> list = new ArrayList<String>(); 650 final String[] rawList = mInterface.getSystemSharedLibraryNames(); 651 for (int i = 0; i < rawList.length; i++) { 652 list.add(rawList[i]); 653 } 654 655 // sort by name 656 Collections.sort(list, new Comparator<String>() { 657 public int compare(String o1, String o2) { 658 if (o1 == o2) return 0; 659 if (o1 == null) return -1; 660 if (o2 == null) return 1; 661 return o1.compareTo(o2); 662 } 663 }); 664 665 final int count = (list != null) ? list.size() : 0; 666 for (int p = 0; p < count; p++) { 667 String lib = list.get(p); 668 pw.print("library:"); 669 pw.println(lib); 670 } 671 return 0; 672 } 673 674 private int runListPackages(boolean showSourceDir) throws RemoteException { 675 final PrintWriter pw = getOutPrintWriter(); 676 int getFlags = 0; 677 boolean listDisabled = false, listEnabled = false; 678 boolean listSystem = false, listThirdParty = false; 679 boolean listInstaller = false; 680 boolean showUid = false; 681 boolean showVersionCode = false; 682 int uid = -1; 683 int userId = UserHandle.USER_SYSTEM; 684 try { 685 String opt; 686 while ((opt = getNextOption()) != null) { 687 switch (opt) { 688 case "-d": 689 listDisabled = true; 690 break; 691 case "-e": 692 listEnabled = true; 693 break; 694 case "-f": 695 showSourceDir = true; 696 break; 697 case "-i": 698 listInstaller = true; 699 break; 700 case "-l": 701 // old compat 702 break; 703 case "-s": 704 listSystem = true; 705 break; 706 case "-U": 707 showUid = true; 708 break; 709 case "-u": 710 getFlags |= PackageManager.MATCH_UNINSTALLED_PACKAGES; 711 break; 712 case "-3": 713 listThirdParty = true; 714 break; 715 case "--show-versioncode": 716 showVersionCode = true; 717 break; 718 case "--user": 719 userId = UserHandle.parseUserArg(getNextArgRequired()); 720 break; 721 case "--uid": 722 showUid = true; 723 uid = Integer.parseInt(getNextArgRequired()); 724 break; 725 default: 726 pw.println("Error: Unknown option: " + opt); 727 return -1; 728 } 729 } 730 } catch (RuntimeException ex) { 731 pw.println("Error: " + ex.toString()); 732 return -1; 733 } 734 735 final String filter = getNextArg(); 736 737 @SuppressWarnings("unchecked") 738 final ParceledListSlice<PackageInfo> slice = 739 mInterface.getInstalledPackages(getFlags, userId); 740 final List<PackageInfo> packages = slice.getList(); 741 742 final int count = packages.size(); 743 for (int p = 0; p < count; p++) { 744 final PackageInfo info = packages.get(p); 745 if (filter != null && !info.packageName.contains(filter)) { 746 continue; 747 } 748 if (uid != -1 && info.applicationInfo.uid != uid) { 749 continue; 750 } 751 final boolean isSystem = 752 (info.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) != 0; 753 if ((!listDisabled || !info.applicationInfo.enabled) && 754 (!listEnabled || info.applicationInfo.enabled) && 755 (!listSystem || isSystem) && 756 (!listThirdParty || !isSystem)) { 757 pw.print("package:"); 758 if (showSourceDir) { 759 pw.print(info.applicationInfo.sourceDir); 760 pw.print("="); 761 } 762 pw.print(info.packageName); 763 if (showVersionCode) { 764 pw.print(" versionCode:"); 765 pw.print(info.applicationInfo.versionCode); 766 } 767 if (listInstaller) { 768 pw.print(" installer="); 769 pw.print(mInterface.getInstallerPackageName(info.packageName)); 770 } 771 if (showUid) { 772 pw.print(" uid:"); 773 pw.print(info.applicationInfo.uid); 774 } 775 pw.println(); 776 } 777 } 778 return 0; 779 } 780 781 private int runListPermissionGroups() throws RemoteException { 782 final PrintWriter pw = getOutPrintWriter(); 783 final List<PermissionGroupInfo> pgs = mInterface.getAllPermissionGroups(0).getList(); 784 785 final int count = pgs.size(); 786 for (int p = 0; p < count ; p++) { 787 final PermissionGroupInfo pgi = pgs.get(p); 788 pw.print("permission group:"); 789 pw.println(pgi.name); 790 } 791 return 0; 792 } 793 794 private int runListPermissions() throws RemoteException { 795 final PrintWriter pw = getOutPrintWriter(); 796 boolean labels = false; 797 boolean groups = false; 798 boolean userOnly = false; 799 boolean summary = false; 800 boolean dangerousOnly = false; 801 String opt; 802 while ((opt = getNextOption()) != null) { 803 switch (opt) { 804 case "-d": 805 dangerousOnly = true; 806 break; 807 case "-f": 808 labels = true; 809 break; 810 case "-g": 811 groups = true; 812 break; 813 case "-s": 814 groups = true; 815 labels = true; 816 summary = true; 817 break; 818 case "-u": 819 userOnly = true; 820 break; 821 default: 822 pw.println("Error: Unknown option: " + opt); 823 return 1; 824 } 825 } 826 827 final ArrayList<String> groupList = new ArrayList<String>(); 828 if (groups) { 829 final List<PermissionGroupInfo> infos = 830 mInterface.getAllPermissionGroups(0 /*flags*/).getList(); 831 final int count = infos.size(); 832 for (int i = 0; i < count; i++) { 833 groupList.add(infos.get(i).name); 834 } 835 groupList.add(null); 836 } else { 837 final String grp = getNextArg(); 838 groupList.add(grp); 839 } 840 841 if (dangerousOnly) { 842 pw.println("Dangerous Permissions:"); 843 pw.println(""); 844 doListPermissions(groupList, groups, labels, summary, 845 PermissionInfo.PROTECTION_DANGEROUS, 846 PermissionInfo.PROTECTION_DANGEROUS); 847 if (userOnly) { 848 pw.println("Normal Permissions:"); 849 pw.println(""); 850 doListPermissions(groupList, groups, labels, summary, 851 PermissionInfo.PROTECTION_NORMAL, 852 PermissionInfo.PROTECTION_NORMAL); 853 } 854 } else if (userOnly) { 855 pw.println("Dangerous and Normal Permissions:"); 856 pw.println(""); 857 doListPermissions(groupList, groups, labels, summary, 858 PermissionInfo.PROTECTION_NORMAL, 859 PermissionInfo.PROTECTION_DANGEROUS); 860 } else { 861 pw.println("All Permissions:"); 862 pw.println(""); 863 doListPermissions(groupList, groups, labels, summary, 864 -10000, 10000); 865 } 866 return 0; 867 } 868 869 private int runUninstall() throws RemoteException { 870 final PrintWriter pw = getOutPrintWriter(); 871 int flags = 0; 872 int userId = UserHandle.USER_ALL; 873 int versionCode = PackageManager.VERSION_CODE_HIGHEST; 874 875 String opt; 876 while ((opt = getNextOption()) != null) { 877 switch (opt) { 878 case "-k": 879 flags |= PackageManager.DELETE_KEEP_DATA; 880 break; 881 case "--user": 882 userId = UserHandle.parseUserArg(getNextArgRequired()); 883 break; 884 case "--versionCode": 885 versionCode = Integer.parseInt(getNextArgRequired()); 886 break; 887 default: 888 pw.println("Error: Unknown option: " + opt); 889 return 1; 890 } 891 } 892 893 final String packageName = getNextArg(); 894 if (packageName == null) { 895 pw.println("Error: package name not specified"); 896 return 1; 897 } 898 899 // if a split is specified, just remove it and not the whole package 900 final String splitName = getNextArg(); 901 if (splitName != null) { 902 return runRemoveSplit(packageName, splitName); 903 } 904 905 userId = translateUserId(userId, "runUninstall"); 906 if (userId == UserHandle.USER_ALL) { 907 userId = UserHandle.USER_SYSTEM; 908 flags |= PackageManager.DELETE_ALL_USERS; 909 } else { 910 final PackageInfo info = mInterface.getPackageInfo(packageName, 911 PackageManager.MATCH_STATIC_SHARED_LIBRARIES, userId); 912 if (info == null) { 913 pw.println("Failure [not installed for " + userId + "]"); 914 return 1; 915 } 916 final boolean isSystem = 917 (info.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0; 918 // If we are being asked to delete a system app for just one 919 // user set flag so it disables rather than reverting to system 920 // version of the app. 921 if (isSystem) { 922 flags |= PackageManager.DELETE_SYSTEM_APP; 923 } 924 } 925 926 final LocalIntentReceiver receiver = new LocalIntentReceiver(); 927 mInterface.getPackageInstaller().uninstall(new VersionedPackage(packageName, 928 versionCode), null /*callerPackageName*/, flags, 929 receiver.getIntentSender(), userId); 930 931 final Intent result = receiver.getResult(); 932 final int status = result.getIntExtra(PackageInstaller.EXTRA_STATUS, 933 PackageInstaller.STATUS_FAILURE); 934 if (status == PackageInstaller.STATUS_SUCCESS) { 935 pw.println("Success"); 936 return 0; 937 } else { 938 pw.println("Failure [" 939 + result.getStringExtra(PackageInstaller.EXTRA_STATUS_MESSAGE) + "]"); 940 return 1; 941 } 942 } 943 944 private int runRemoveSplit(String packageName, String splitName) throws RemoteException { 945 final PrintWriter pw = getOutPrintWriter(); 946 final SessionParams sessionParams = new SessionParams(SessionParams.MODE_INHERIT_EXISTING); 947 sessionParams.installFlags |= PackageManager.INSTALL_REPLACE_EXISTING; 948 sessionParams.appPackageName = packageName; 949 final int sessionId = 950 doCreateSession(sessionParams, null /*installerPackageName*/, UserHandle.USER_ALL); 951 boolean abandonSession = true; 952 try { 953 if (doRemoveSplit(sessionId, splitName, false /*logSuccess*/) 954 != PackageInstaller.STATUS_SUCCESS) { 955 return 1; 956 } 957 if (doCommitSession(sessionId, false /*logSuccess*/) 958 != PackageInstaller.STATUS_SUCCESS) { 959 return 1; 960 } 961 abandonSession = false; 962 pw.println("Success"); 963 return 0; 964 } finally { 965 if (abandonSession) { 966 try { 967 doAbandonSession(sessionId, false /*logSuccess*/); 968 } catch (Exception ignore) { 969 } 970 } 971 } 972 } 973 974 private Intent parseIntentAndUser() throws URISyntaxException { 975 mTargetUser = UserHandle.USER_CURRENT; 976 mBrief = false; 977 mComponents = false; 978 Intent intent = Intent.parseCommandArgs(this, new Intent.CommandOptionHandler() { 979 @Override 980 public boolean handleOption(String opt, ShellCommand cmd) { 981 if ("--user".equals(opt)) { 982 mTargetUser = UserHandle.parseUserArg(cmd.getNextArgRequired()); 983 return true; 984 } else if ("--brief".equals(opt)) { 985 mBrief = true; 986 return true; 987 } else if ("--components".equals(opt)) { 988 mComponents = true; 989 return true; 990 } 991 return false; 992 } 993 }); 994 mTargetUser = ActivityManager.handleIncomingUser(Binder.getCallingPid(), 995 Binder.getCallingUid(), mTargetUser, false, false, null, null); 996 return intent; 997 } 998 999 private void printResolveInfo(PrintWriterPrinter pr, String prefix, ResolveInfo ri, 1000 boolean brief, boolean components) { 1001 if (brief || components) { 1002 final ComponentName comp; 1003 if (ri.activityInfo != null) { 1004 comp = new ComponentName(ri.activityInfo.packageName, ri.activityInfo.name); 1005 } else if (ri.serviceInfo != null) { 1006 comp = new ComponentName(ri.serviceInfo.packageName, ri.serviceInfo.name); 1007 } else if (ri.providerInfo != null) { 1008 comp = new ComponentName(ri.providerInfo.packageName, ri.providerInfo.name); 1009 } else { 1010 comp = null; 1011 } 1012 if (comp != null) { 1013 if (!components) { 1014 pr.println(prefix + "priority=" + ri.priority 1015 + " preferredOrder=" + ri.preferredOrder 1016 + " match=0x" + Integer.toHexString(ri.match) 1017 + " specificIndex=" + ri.specificIndex 1018 + " isDefault=" + ri.isDefault); 1019 } 1020 pr.println(prefix + comp.flattenToShortString()); 1021 return; 1022 } 1023 } 1024 ri.dump(pr, prefix); 1025 } 1026 1027 private int runResolveActivity() { 1028 Intent intent; 1029 try { 1030 intent = parseIntentAndUser(); 1031 } catch (URISyntaxException e) { 1032 throw new RuntimeException(e.getMessage(), e); 1033 } 1034 try { 1035 ResolveInfo ri = mInterface.resolveIntent(intent, intent.getType(), 0, mTargetUser); 1036 PrintWriter pw = getOutPrintWriter(); 1037 if (ri == null) { 1038 pw.println("No activity found"); 1039 } else { 1040 PrintWriterPrinter pr = new PrintWriterPrinter(pw); 1041 printResolveInfo(pr, "", ri, mBrief, mComponents); 1042 } 1043 } catch (RemoteException e) { 1044 throw new RuntimeException("Failed calling service", e); 1045 } 1046 return 0; 1047 } 1048 1049 private int runQueryIntentActivities() { 1050 Intent intent; 1051 try { 1052 intent = parseIntentAndUser(); 1053 } catch (URISyntaxException e) { 1054 throw new RuntimeException(e.getMessage(), e); 1055 } 1056 try { 1057 List<ResolveInfo> result = mInterface.queryIntentActivities(intent, intent.getType(), 0, 1058 mTargetUser).getList(); 1059 PrintWriter pw = getOutPrintWriter(); 1060 if (result == null || result.size() <= 0) { 1061 pw.println("No activities found"); 1062 } else { 1063 if (!mComponents) { 1064 pw.print(result.size()); pw.println(" activities found:"); 1065 PrintWriterPrinter pr = new PrintWriterPrinter(pw); 1066 for (int i = 0; i < result.size(); i++) { 1067 pw.print(" Activity #"); pw.print(i); pw.println(":"); 1068 printResolveInfo(pr, " ", result.get(i), mBrief, mComponents); 1069 } 1070 } else { 1071 PrintWriterPrinter pr = new PrintWriterPrinter(pw); 1072 for (int i = 0; i < result.size(); i++) { 1073 printResolveInfo(pr, "", result.get(i), mBrief, mComponents); 1074 } 1075 } 1076 } 1077 } catch (RemoteException e) { 1078 throw new RuntimeException("Failed calling service", e); 1079 } 1080 return 0; 1081 } 1082 1083 private int runQueryIntentServices() { 1084 Intent intent; 1085 try { 1086 intent = parseIntentAndUser(); 1087 } catch (URISyntaxException e) { 1088 throw new RuntimeException(e.getMessage(), e); 1089 } 1090 try { 1091 List<ResolveInfo> result = mInterface.queryIntentServices(intent, intent.getType(), 0, 1092 mTargetUser).getList(); 1093 PrintWriter pw = getOutPrintWriter(); 1094 if (result == null || result.size() <= 0) { 1095 pw.println("No services found"); 1096 } else { 1097 if (!mComponents) { 1098 pw.print(result.size()); pw.println(" services found:"); 1099 PrintWriterPrinter pr = new PrintWriterPrinter(pw); 1100 for (int i = 0; i < result.size(); i++) { 1101 pw.print(" Service #"); pw.print(i); pw.println(":"); 1102 printResolveInfo(pr, " ", result.get(i), mBrief, mComponents); 1103 } 1104 } else { 1105 PrintWriterPrinter pr = new PrintWriterPrinter(pw); 1106 for (int i = 0; i < result.size(); i++) { 1107 printResolveInfo(pr, "", result.get(i), mBrief, mComponents); 1108 } 1109 } 1110 } 1111 } catch (RemoteException e) { 1112 throw new RuntimeException("Failed calling service", e); 1113 } 1114 return 0; 1115 } 1116 1117 private int runQueryIntentReceivers() { 1118 Intent intent; 1119 try { 1120 intent = parseIntentAndUser(); 1121 } catch (URISyntaxException e) { 1122 throw new RuntimeException(e.getMessage(), e); 1123 } 1124 try { 1125 List<ResolveInfo> result = mInterface.queryIntentReceivers(intent, intent.getType(), 0, 1126 mTargetUser).getList(); 1127 PrintWriter pw = getOutPrintWriter(); 1128 if (result == null || result.size() <= 0) { 1129 pw.println("No receivers found"); 1130 } else { 1131 if (!mComponents) { 1132 pw.print(result.size()); pw.println(" receivers found:"); 1133 PrintWriterPrinter pr = new PrintWriterPrinter(pw); 1134 for (int i = 0; i < result.size(); i++) { 1135 pw.print(" Receiver #"); pw.print(i); pw.println(":"); 1136 printResolveInfo(pr, " ", result.get(i), mBrief, mComponents); 1137 } 1138 } else { 1139 PrintWriterPrinter pr = new PrintWriterPrinter(pw); 1140 for (int i = 0; i < result.size(); i++) { 1141 printResolveInfo(pr, "", result.get(i), mBrief, mComponents); 1142 } 1143 } 1144 } 1145 } catch (RemoteException e) { 1146 throw new RuntimeException("Failed calling service", e); 1147 } 1148 return 0; 1149 } 1150 1151 private static class InstallParams { 1152 SessionParams sessionParams; 1153 String installerPackageName; 1154 int userId = UserHandle.USER_ALL; 1155 } 1156 1157 private InstallParams makeInstallParams() { 1158 final SessionParams sessionParams = new SessionParams(SessionParams.MODE_FULL_INSTALL); 1159 final InstallParams params = new InstallParams(); 1160 params.sessionParams = sessionParams; 1161 String opt; 1162 while ((opt = getNextOption()) != null) { 1163 switch (opt) { 1164 case "-l": 1165 sessionParams.installFlags |= PackageManager.INSTALL_FORWARD_LOCK; 1166 break; 1167 case "-r": 1168 sessionParams.installFlags |= PackageManager.INSTALL_REPLACE_EXISTING; 1169 break; 1170 case "-i": 1171 params.installerPackageName = getNextArg(); 1172 if (params.installerPackageName == null) { 1173 throw new IllegalArgumentException("Missing installer package"); 1174 } 1175 break; 1176 case "-t": 1177 sessionParams.installFlags |= PackageManager.INSTALL_ALLOW_TEST; 1178 break; 1179 case "-s": 1180 sessionParams.installFlags |= PackageManager.INSTALL_EXTERNAL; 1181 break; 1182 case "-f": 1183 sessionParams.installFlags |= PackageManager.INSTALL_INTERNAL; 1184 break; 1185 case "-d": 1186 sessionParams.installFlags |= PackageManager.INSTALL_ALLOW_DOWNGRADE; 1187 break; 1188 case "-g": 1189 sessionParams.installFlags |= PackageManager.INSTALL_GRANT_RUNTIME_PERMISSIONS; 1190 break; 1191 case "--dont-kill": 1192 sessionParams.installFlags |= PackageManager.INSTALL_DONT_KILL_APP; 1193 break; 1194 case "--originating-uri": 1195 sessionParams.originatingUri = Uri.parse(getNextArg()); 1196 break; 1197 case "--referrer": 1198 sessionParams.referrerUri = Uri.parse(getNextArg()); 1199 break; 1200 case "-p": 1201 sessionParams.mode = SessionParams.MODE_INHERIT_EXISTING; 1202 sessionParams.appPackageName = getNextArg(); 1203 if (sessionParams.appPackageName == null) { 1204 throw new IllegalArgumentException("Missing inherit package name"); 1205 } 1206 break; 1207 case "-S": 1208 final long sizeBytes = Long.parseLong(getNextArg()); 1209 if (sizeBytes <= 0) { 1210 throw new IllegalArgumentException("Size must be positive"); 1211 } 1212 sessionParams.setSize(sizeBytes); 1213 break; 1214 case "--abi": 1215 sessionParams.abiOverride = checkAbiArgument(getNextArg()); 1216 break; 1217 case "--ephemeral": 1218 case "--instantapp": 1219 sessionParams.setInstallAsInstantApp(true /*isInstantApp*/); 1220 break; 1221 case "--full": 1222 sessionParams.setInstallAsInstantApp(false /*isInstantApp*/); 1223 break; 1224 case "--preload": 1225 sessionParams.setInstallAsVirtualPreload(); 1226 break; 1227 case "--user": 1228 params.userId = UserHandle.parseUserArg(getNextArgRequired()); 1229 break; 1230 case "--install-location": 1231 sessionParams.installLocation = Integer.parseInt(getNextArg()); 1232 break; 1233 case "--force-uuid": 1234 sessionParams.installFlags |= PackageManager.INSTALL_FORCE_VOLUME_UUID; 1235 sessionParams.volumeUuid = getNextArg(); 1236 if ("internal".equals(sessionParams.volumeUuid)) { 1237 sessionParams.volumeUuid = null; 1238 } 1239 break; 1240 case "--force-sdk": 1241 sessionParams.installFlags |= PackageManager.INSTALL_FORCE_SDK; 1242 break; 1243 default: 1244 throw new IllegalArgumentException("Unknown option " + opt); 1245 } 1246 } 1247 return params; 1248 } 1249 1250 private int runSetHomeActivity() { 1251 final PrintWriter pw = getOutPrintWriter(); 1252 int userId = UserHandle.USER_SYSTEM; 1253 String opt; 1254 while ((opt = getNextOption()) != null) { 1255 switch (opt) { 1256 case "--user": 1257 userId = UserHandle.parseUserArg(getNextArgRequired()); 1258 break; 1259 default: 1260 pw.println("Error: Unknown option: " + opt); 1261 return 1; 1262 } 1263 } 1264 1265 String component = getNextArg(); 1266 ComponentName componentName = 1267 component != null ? ComponentName.unflattenFromString(component) : null; 1268 1269 if (componentName == null) { 1270 pw.println("Error: component name not specified or invalid"); 1271 return 1; 1272 } 1273 1274 try { 1275 mInterface.setHomeActivity(componentName, userId); 1276 pw.println("Success"); 1277 return 0; 1278 } catch (Exception e) { 1279 pw.println(e.toString()); 1280 return 1; 1281 } 1282 } 1283 1284 private int runGetPrivappPermissions() { 1285 final String pkg = getNextArg(); 1286 if (pkg == null) { 1287 System.err.println("Error: no package specified."); 1288 return 1; 1289 } 1290 ArraySet<String> privAppPermissions = SystemConfig.getInstance().getPrivAppPermissions(pkg); 1291 getOutPrintWriter().println(privAppPermissions == null 1292 ? "{}" : privAppPermissions.toString()); 1293 return 0; 1294 } 1295 1296 private int runGetInstantAppResolver() { 1297 final PrintWriter pw = getOutPrintWriter(); 1298 try { 1299 final ComponentName instantAppsResolver = mInterface.getInstantAppResolverComponent(); 1300 if (instantAppsResolver == null) { 1301 return 1; 1302 } 1303 pw.println(instantAppsResolver.flattenToString()); 1304 return 0; 1305 } catch (Exception e) { 1306 pw.println(e.toString()); 1307 return 1; 1308 } 1309 } 1310 1311 private int runHasFeature() { 1312 final PrintWriter err = getErrPrintWriter(); 1313 final String featureName = getNextArg(); 1314 if (featureName == null) { 1315 err.println("Error: expected FEATURE name"); 1316 return 1; 1317 } 1318 final String versionString = getNextArg(); 1319 try { 1320 final int version = (versionString == null) ? 0 : Integer.parseInt(versionString); 1321 final boolean hasFeature = mInterface.hasSystemFeature(featureName, version); 1322 getOutPrintWriter().println(hasFeature); 1323 return hasFeature ? 0 : 1; 1324 } catch (NumberFormatException e) { 1325 err.println("Error: illegal version number " + versionString); 1326 return 1; 1327 } catch (RemoteException e) { 1328 err.println(e.toString()); 1329 return 1; 1330 } 1331 } 1332 1333 private static String checkAbiArgument(String abi) { 1334 if (TextUtils.isEmpty(abi)) { 1335 throw new IllegalArgumentException("Missing ABI argument"); 1336 } 1337 1338 if ("-".equals(abi)) { 1339 return abi; 1340 } 1341 1342 final String[] supportedAbis = Build.SUPPORTED_ABIS; 1343 for (String supportedAbi : supportedAbis) { 1344 if (supportedAbi.equals(abi)) { 1345 return abi; 1346 } 1347 } 1348 1349 throw new IllegalArgumentException("ABI " + abi + " not supported on this device"); 1350 } 1351 1352 private int translateUserId(int userId, String logContext) { 1353 return ActivityManager.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), 1354 userId, true, true, logContext, "pm command"); 1355 } 1356 1357 private int doCreateSession(SessionParams params, String installerPackageName, int userId) 1358 throws RemoteException { 1359 userId = translateUserId(userId, "runInstallCreate"); 1360 if (userId == UserHandle.USER_ALL) { 1361 userId = UserHandle.USER_SYSTEM; 1362 params.installFlags |= PackageManager.INSTALL_ALL_USERS; 1363 } 1364 1365 final int sessionId = mInterface.getPackageInstaller() 1366 .createSession(params, installerPackageName, userId); 1367 return sessionId; 1368 } 1369 1370 private int doWriteSplit(int sessionId, String inPath, long sizeBytes, String splitName, 1371 boolean logSuccess) throws RemoteException { 1372 final PrintWriter pw = getOutPrintWriter(); 1373 if (FORCE_STREAM_INSTALL && inPath != null && !STDIN_PATH.equals(inPath)) { 1374 pw.println("Error: APK content must be streamed"); 1375 return 1; 1376 } 1377 if (STDIN_PATH.equals(inPath)) { 1378 inPath = null; 1379 } else if (inPath != null) { 1380 final File file = new File(inPath); 1381 if (file.isFile()) { 1382 sizeBytes = file.length(); 1383 } 1384 } 1385 if (sizeBytes <= 0) { 1386 pw.println("Error: must specify a APK size"); 1387 return 1; 1388 } 1389 1390 final SessionInfo info = mInterface.getPackageInstaller().getSessionInfo(sessionId); 1391 1392 PackageInstaller.Session session = null; 1393 InputStream in = null; 1394 OutputStream out = null; 1395 try { 1396 session = new PackageInstaller.Session( 1397 mInterface.getPackageInstaller().openSession(sessionId)); 1398 1399 if (inPath != null) { 1400 in = new FileInputStream(inPath); 1401 } else { 1402 in = new SizedInputStream(getRawInputStream(), sizeBytes); 1403 } 1404 out = session.openWrite(splitName, 0, sizeBytes); 1405 1406 int total = 0; 1407 byte[] buffer = new byte[65536]; 1408 int c; 1409 while ((c = in.read(buffer)) != -1) { 1410 total += c; 1411 out.write(buffer, 0, c); 1412 1413 if (info.sizeBytes > 0) { 1414 final float fraction = ((float) c / (float) info.sizeBytes); 1415 session.addProgress(fraction); 1416 } 1417 } 1418 session.fsync(out); 1419 1420 if (logSuccess) { 1421 pw.println("Success: streamed " + total + " bytes"); 1422 } 1423 return 0; 1424 } catch (IOException e) { 1425 pw.println("Error: failed to write; " + e.getMessage()); 1426 return 1; 1427 } finally { 1428 IoUtils.closeQuietly(out); 1429 IoUtils.closeQuietly(in); 1430 IoUtils.closeQuietly(session); 1431 } 1432 } 1433 1434 private int doRemoveSplit(int sessionId, String splitName, boolean logSuccess) 1435 throws RemoteException { 1436 final PrintWriter pw = getOutPrintWriter(); 1437 PackageInstaller.Session session = null; 1438 try { 1439 session = new PackageInstaller.Session( 1440 mInterface.getPackageInstaller().openSession(sessionId)); 1441 session.removeSplit(splitName); 1442 1443 if (logSuccess) { 1444 pw.println("Success"); 1445 } 1446 return 0; 1447 } catch (IOException e) { 1448 pw.println("Error: failed to remove split; " + e.getMessage()); 1449 return 1; 1450 } finally { 1451 IoUtils.closeQuietly(session); 1452 } 1453 } 1454 1455 private int doCommitSession(int sessionId, boolean logSuccess) throws RemoteException { 1456 final PrintWriter pw = getOutPrintWriter(); 1457 PackageInstaller.Session session = null; 1458 try { 1459 session = new PackageInstaller.Session( 1460 mInterface.getPackageInstaller().openSession(sessionId)); 1461 1462 final LocalIntentReceiver receiver = new LocalIntentReceiver(); 1463 session.commit(receiver.getIntentSender()); 1464 1465 final Intent result = receiver.getResult(); 1466 final int status = result.getIntExtra(PackageInstaller.EXTRA_STATUS, 1467 PackageInstaller.STATUS_FAILURE); 1468 if (status == PackageInstaller.STATUS_SUCCESS) { 1469 if (logSuccess) { 1470 pw.println("Success"); 1471 } 1472 } else { 1473 pw.println("Failure [" 1474 + result.getStringExtra(PackageInstaller.EXTRA_STATUS_MESSAGE) + "]"); 1475 } 1476 return status; 1477 } finally { 1478 IoUtils.closeQuietly(session); 1479 } 1480 } 1481 1482 private int doAbandonSession(int sessionId, boolean logSuccess) throws RemoteException { 1483 final PrintWriter pw = getOutPrintWriter(); 1484 PackageInstaller.Session session = null; 1485 try { 1486 session = new PackageInstaller.Session( 1487 mInterface.getPackageInstaller().openSession(sessionId)); 1488 session.abandon(); 1489 if (logSuccess) { 1490 pw.println("Success"); 1491 } 1492 return 0; 1493 } finally { 1494 IoUtils.closeQuietly(session); 1495 } 1496 } 1497 1498 private void doListPermissions(ArrayList<String> groupList, boolean groups, boolean labels, 1499 boolean summary, int startProtectionLevel, int endProtectionLevel) 1500 throws RemoteException { 1501 final PrintWriter pw = getOutPrintWriter(); 1502 final int groupCount = groupList.size(); 1503 for (int i = 0; i < groupCount; i++) { 1504 String groupName = groupList.get(i); 1505 String prefix = ""; 1506 if (groups) { 1507 if (i > 0) { 1508 pw.println(""); 1509 } 1510 if (groupName != null) { 1511 PermissionGroupInfo pgi = 1512 mInterface.getPermissionGroupInfo(groupName, 0 /*flags*/); 1513 if (summary) { 1514 Resources res = getResources(pgi); 1515 if (res != null) { 1516 pw.print(loadText(pgi, pgi.labelRes, pgi.nonLocalizedLabel) + ": "); 1517 } else { 1518 pw.print(pgi.name + ": "); 1519 1520 } 1521 } else { 1522 pw.println((labels ? "+ " : "") + "group:" + pgi.name); 1523 if (labels) { 1524 pw.println(" package:" + pgi.packageName); 1525 Resources res = getResources(pgi); 1526 if (res != null) { 1527 pw.println(" label:" 1528 + loadText(pgi, pgi.labelRes, pgi.nonLocalizedLabel)); 1529 pw.println(" description:" 1530 + loadText(pgi, pgi.descriptionRes, 1531 pgi.nonLocalizedDescription)); 1532 } 1533 } 1534 } 1535 } else { 1536 pw.println(((labels && !summary) ? "+ " : "") + "ungrouped:"); 1537 } 1538 prefix = " "; 1539 } 1540 List<PermissionInfo> ps = 1541 mInterface.queryPermissionsByGroup(groupList.get(i), 0 /*flags*/).getList(); 1542 final int count = ps.size(); 1543 boolean first = true; 1544 for (int p = 0 ; p < count ; p++) { 1545 PermissionInfo pi = ps.get(p); 1546 if (groups && groupName == null && pi.group != null) { 1547 continue; 1548 } 1549 final int base = pi.protectionLevel & PermissionInfo.PROTECTION_MASK_BASE; 1550 if (base < startProtectionLevel 1551 || base > endProtectionLevel) { 1552 continue; 1553 } 1554 if (summary) { 1555 if (first) { 1556 first = false; 1557 } else { 1558 pw.print(", "); 1559 } 1560 Resources res = getResources(pi); 1561 if (res != null) { 1562 pw.print(loadText(pi, pi.labelRes, 1563 pi.nonLocalizedLabel)); 1564 } else { 1565 pw.print(pi.name); 1566 } 1567 } else { 1568 pw.println(prefix + (labels ? "+ " : "") 1569 + "permission:" + pi.name); 1570 if (labels) { 1571 pw.println(prefix + " package:" + pi.packageName); 1572 Resources res = getResources(pi); 1573 if (res != null) { 1574 pw.println(prefix + " label:" 1575 + loadText(pi, pi.labelRes, 1576 pi.nonLocalizedLabel)); 1577 pw.println(prefix + " description:" 1578 + loadText(pi, pi.descriptionRes, 1579 pi.nonLocalizedDescription)); 1580 } 1581 pw.println(prefix + " protectionLevel:" 1582 + PermissionInfo.protectionToString(pi.protectionLevel)); 1583 } 1584 } 1585 } 1586 1587 if (summary) { 1588 pw.println(""); 1589 } 1590 } 1591 } 1592 1593 private String loadText(PackageItemInfo pii, int res, CharSequence nonLocalized) 1594 throws RemoteException { 1595 if (nonLocalized != null) { 1596 return nonLocalized.toString(); 1597 } 1598 if (res != 0) { 1599 Resources r = getResources(pii); 1600 if (r != null) { 1601 try { 1602 return r.getString(res); 1603 } catch (Resources.NotFoundException e) { 1604 } 1605 } 1606 } 1607 return null; 1608 } 1609 1610 private Resources getResources(PackageItemInfo pii) throws RemoteException { 1611 Resources res = mResourceCache.get(pii.packageName); 1612 if (res != null) return res; 1613 1614 ApplicationInfo ai = mInterface.getApplicationInfo(pii.packageName, 0, 0); 1615 AssetManager am = new AssetManager(); 1616 am.addAssetPath(ai.publicSourceDir); 1617 res = new Resources(am, null, null); 1618 mResourceCache.put(pii.packageName, res); 1619 return res; 1620 } 1621 1622 @Override 1623 public void onHelp() { 1624 final PrintWriter pw = getOutPrintWriter(); 1625 pw.println("Package manager (package) commands:"); 1626 pw.println(" help"); 1627 pw.println(" Print this help text."); 1628 pw.println(""); 1629 pw.println(" compile [-m MODE | -r REASON] [-f] [-c] [--split SPLIT_NAME]"); 1630 pw.println(" [--reset] [--check-prof (true | false)] (-a | TARGET-PACKAGE)"); 1631 pw.println(" Trigger compilation of TARGET-PACKAGE or all packages if \"-a\"."); 1632 pw.println(" Options:"); 1633 pw.println(" -a: compile all packages"); 1634 pw.println(" -c: clear profile data before compiling"); 1635 pw.println(" -f: force compilation even if not needed"); 1636 pw.println(" -m: select compilation mode"); 1637 pw.println(" MODE is one of the dex2oat compiler filters:"); 1638 pw.println(" assume-verified"); 1639 pw.println(" extract"); 1640 pw.println(" verify"); 1641 pw.println(" quicken"); 1642 pw.println(" space-profile"); 1643 pw.println(" space"); 1644 pw.println(" speed-profile"); 1645 pw.println(" speed"); 1646 pw.println(" everything"); 1647 pw.println(" -r: select compilation reason"); 1648 pw.println(" REASON is one of:"); 1649 for (int i = 0; i < PackageManagerServiceCompilerMapping.REASON_STRINGS.length; i++) { 1650 pw.println(" " + PackageManagerServiceCompilerMapping.REASON_STRINGS[i]); 1651 } 1652 pw.println(" --reset: restore package to its post-install state"); 1653 pw.println(" --check-prof (true | false): look at profiles when doing dexopt?"); 1654 pw.println(" --secondary-dex: compile app secondary dex files"); 1655 pw.println(" --split SPLIT: compile only the given split name"); 1656 pw.println(" bg-dexopt-job"); 1657 pw.println(" Execute the background optimizations immediately."); 1658 pw.println(" Note that the command only runs the background optimizer logic. It may"); 1659 pw.println(" overlap with the actual job but the job scheduler will not be able to"); 1660 pw.println(" cancel it. It will also run even if the device is not in the idle"); 1661 pw.println(" maintenance mode."); 1662 pw.println(" list features"); 1663 pw.println(" Prints all features of the system."); 1664 pw.println(" list instrumentation [-f] [TARGET-PACKAGE]"); 1665 pw.println(" Prints all test packages; optionally only those targeting TARGET-PACKAGE"); 1666 pw.println(" Options:"); 1667 pw.println(" -f: dump the name of the .apk file containing the test package"); 1668 pw.println(" list libraries"); 1669 pw.println(" Prints all system libraries."); 1670 pw.println(" list packages [-f] [-d] [-e] [-s] [-3] [-i] [-l] [-u] [-U] " 1671 + "[--uid UID] [--user USER_ID] [FILTER]"); 1672 pw.println(" Prints all packages; optionally only those whose name contains"); 1673 pw.println(" the text in FILTER."); 1674 pw.println(" Options:"); 1675 pw.println(" -f: see their associated file"); 1676 pw.println(" -d: filter to only show disabled packages"); 1677 pw.println(" -e: filter to only show enabled packages"); 1678 pw.println(" -s: filter to only show system packages"); 1679 pw.println(" -3: filter to only show third party packages"); 1680 pw.println(" -i: see the installer for the packages"); 1681 pw.println(" -l: ignored (used for compatibility with older releases)"); 1682 pw.println(" -U: also show the package UID"); 1683 pw.println(" -u: also include uninstalled packages"); 1684 pw.println(" --uid UID: filter to only show packages with the given UID"); 1685 pw.println(" --user USER_ID: only list packages belonging to the given user"); 1686 pw.println(" reconcile-secondary-dex-files TARGET-PACKAGE"); 1687 pw.println(" Reconciles the package secondary dex files with the generated oat files."); 1688 pw.println(" list permission-groups"); 1689 pw.println(" Prints all known permission groups."); 1690 pw.println(" list permissions [-g] [-f] [-d] [-u] [GROUP]"); 1691 pw.println(" Prints all known permissions; optionally only those in GROUP."); 1692 pw.println(" Options:"); 1693 pw.println(" -g: organize by group"); 1694 pw.println(" -f: print all information"); 1695 pw.println(" -s: short summary"); 1696 pw.println(" -d: only list dangerous permissions"); 1697 pw.println(" -u: list only the permissions users will see"); 1698 pw.println(" dump-profiles TARGET-PACKAGE"); 1699 pw.println(" Dumps method/class profile files to"); 1700 pw.println(" /data/misc/profman/TARGET-PACKAGE.txt"); 1701 pw.println(" resolve-activity [--brief] [--components] [--user USER_ID] INTENT"); 1702 pw.println(" Prints the activity that resolves to the given Intent."); 1703 pw.println(" query-activities [--brief] [--components] [--user USER_ID] INTENT"); 1704 pw.println(" Prints all activities that can handle the given Intent."); 1705 pw.println(" query-services [--brief] [--components] [--user USER_ID] INTENT"); 1706 pw.println(" Prints all services that can handle the given Intent."); 1707 pw.println(" query-receivers [--brief] [--components] [--user USER_ID] INTENT"); 1708 pw.println(" Prints all broadcast receivers that can handle the given Intent."); 1709 pw.println(" suspend [--user USER_ID] TARGET-PACKAGE"); 1710 pw.println(" Suspends the specified package (as user)."); 1711 pw.println(" unsuspend [--user USER_ID] TARGET-PACKAGE"); 1712 pw.println(" Unsuspends the specified package (as user)."); 1713 pw.println(" set-home-activity [--user USER_ID] TARGET-COMPONENT"); 1714 pw.println(" set the default home activity (aka launcher)."); 1715 pw.println(" has-feature FEATURE_NAME [version]"); 1716 pw.println(" prints true and returns exit status 0 when system has a FEATURE_NAME,"); 1717 pw.println(" otherwise prints false and returns exit status 1"); 1718 pw.println(); 1719 Intent.printIntentArgsHelp(pw , ""); 1720 } 1721 1722 private static class LocalIntentReceiver { 1723 private final SynchronousQueue<Intent> mResult = new SynchronousQueue<>(); 1724 1725 private IIntentSender.Stub mLocalSender = new IIntentSender.Stub() { 1726 @Override 1727 public void send(int code, Intent intent, String resolvedType, IBinder whitelistToken, 1728 IIntentReceiver finishedReceiver, String requiredPermission, Bundle options) { 1729 try { 1730 mResult.offer(intent, 5, TimeUnit.SECONDS); 1731 } catch (InterruptedException e) { 1732 throw new RuntimeException(e); 1733 } 1734 } 1735 }; 1736 1737 public IntentSender getIntentSender() { 1738 return new IntentSender((IIntentSender) mLocalSender); 1739 } 1740 1741 public Intent getResult() { 1742 try { 1743 return mResult.take(); 1744 } catch (InterruptedException e) { 1745 throw new RuntimeException(e); 1746 } 1747 } 1748 } 1749} 1750