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