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 17 package com.android.server.pm; 18 19 import static android.content.pm.PackageInstaller.LOCATION_DATA_APP; 20 import static android.content.pm.PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED; 21 import static android.content.pm.PackageManager.FLAG_PERMISSION_REVOKED_COMPAT; 22 import static android.content.pm.PackageManager.FLAG_PERMISSION_REVOKE_WHEN_REQUESTED; 23 import static android.content.pm.PackageManager.FLAG_PERMISSION_USER_FIXED; 24 import static android.content.pm.PackageManager.FLAG_PERMISSION_USER_SET; 25 26 import android.accounts.IAccountManager; 27 import android.annotation.NonNull; 28 import android.annotation.UserIdInt; 29 import android.app.ActivityManager; 30 import android.app.ActivityManagerInternal; 31 import android.app.role.RoleManager; 32 import android.content.ComponentName; 33 import android.content.Context; 34 import android.content.IIntentReceiver; 35 import android.content.IIntentSender; 36 import android.content.Intent; 37 import android.content.IntentSender; 38 import android.content.pm.ApplicationInfo; 39 import android.content.pm.FeatureInfo; 40 import android.content.pm.IPackageDataObserver; 41 import android.content.pm.IPackageInstaller; 42 import android.content.pm.IPackageManager; 43 import android.content.pm.InstrumentationInfo; 44 import android.content.pm.ModuleInfo; 45 import android.content.pm.PackageInfo; 46 import android.content.pm.PackageInstaller; 47 import android.content.pm.PackageInstaller.SessionInfo; 48 import android.content.pm.PackageInstaller.SessionParams; 49 import android.content.pm.PackageItemInfo; 50 import android.content.pm.PackageManager; 51 import android.content.pm.PackageManager.NameNotFoundException; 52 import android.content.pm.PackageManagerInternal; 53 import android.content.pm.ParceledListSlice; 54 import android.content.pm.PermissionGroupInfo; 55 import android.content.pm.PermissionInfo; 56 import android.content.pm.ResolveInfo; 57 import android.content.pm.SharedLibraryInfo; 58 import android.content.pm.SuspendDialogInfo; 59 import android.content.pm.UserInfo; 60 import android.content.pm.VersionedPackage; 61 import android.content.pm.dex.ArtManager; 62 import android.content.pm.dex.DexMetadataHelper; 63 import android.content.pm.dex.ISnapshotRuntimeProfileCallback; 64 import android.content.pm.parsing.ApkLite; 65 import android.content.pm.parsing.ApkLiteParseUtils; 66 import android.content.pm.parsing.PackageLite; 67 import android.content.pm.parsing.result.ParseResult; 68 import android.content.pm.parsing.result.ParseTypeImpl; 69 import android.content.res.AssetManager; 70 import android.content.res.Resources; 71 import android.content.rollback.PackageRollbackInfo; 72 import android.content.rollback.RollbackInfo; 73 import android.content.rollback.RollbackManager; 74 import android.net.Uri; 75 import android.os.Binder; 76 import android.os.Build; 77 import android.os.Bundle; 78 import android.os.IBinder; 79 import android.os.IUserManager; 80 import android.os.ParcelFileDescriptor; 81 import android.os.ParcelFileDescriptor.AutoCloseInputStream; 82 import android.os.PersistableBundle; 83 import android.os.Process; 84 import android.os.RemoteException; 85 import android.os.ServiceManager; 86 import android.os.ServiceSpecificException; 87 import android.os.ShellCommand; 88 import android.os.SystemClock; 89 import android.os.SystemProperties; 90 import android.os.Trace; 91 import android.os.UserHandle; 92 import android.os.UserManager; 93 import android.os.incremental.V4Signature; 94 import android.os.storage.StorageManager; 95 import android.permission.PermissionManager; 96 import android.system.ErrnoException; 97 import android.system.Os; 98 import android.text.TextUtils; 99 import android.text.format.DateUtils; 100 import android.util.ArrayMap; 101 import android.util.ArraySet; 102 import android.util.IntArray; 103 import android.util.PrintWriterPrinter; 104 import android.util.Slog; 105 import android.util.SparseArray; 106 107 import com.android.internal.content.InstallLocationUtils; 108 import com.android.internal.util.ArrayUtils; 109 import com.android.internal.util.IndentingPrintWriter; 110 import com.android.internal.util.Preconditions; 111 import com.android.server.FgThread; 112 import com.android.server.LocalServices; 113 import com.android.server.SystemConfig; 114 import com.android.server.pm.PackageManagerShellCommandDataLoader.Metadata; 115 import com.android.server.pm.permission.LegacyPermissionManagerInternal; 116 import com.android.server.pm.verify.domain.DomainVerificationShell; 117 118 import dalvik.system.DexFile; 119 120 import libcore.io.IoUtils; 121 import libcore.io.Streams; 122 123 import java.io.File; 124 import java.io.FileOutputStream; 125 import java.io.IOException; 126 import java.io.InputStream; 127 import java.io.OutputStream; 128 import java.io.PrintWriter; 129 import java.net.URISyntaxException; 130 import java.security.SecureRandom; 131 import java.util.ArrayList; 132 import java.util.Arrays; 133 import java.util.Base64; 134 import java.util.Collection; 135 import java.util.Collections; 136 import java.util.Comparator; 137 import java.util.HashMap; 138 import java.util.List; 139 import java.util.Map; 140 import java.util.Objects; 141 import java.util.Set; 142 import java.util.WeakHashMap; 143 import java.util.concurrent.CompletableFuture; 144 import java.util.concurrent.CountDownLatch; 145 import java.util.concurrent.LinkedBlockingQueue; 146 import java.util.concurrent.TimeUnit; 147 148 class PackageManagerShellCommand extends ShellCommand { 149 /** Path for streaming APK content */ 150 private static final String STDIN_PATH = "-"; 151 /** Path where ART profiles snapshots are dumped for the shell user */ 152 private final static String ART_PROFILE_SNAPSHOT_DEBUG_LOCATION = "/data/misc/profman/"; 153 private static final int DEFAULT_STAGED_READY_TIMEOUT_MS = 60 * 1000; 154 private static final String TAG = "PackageManagerShellCommand"; 155 private static final Set<String> UNSUPPORTED_INSTALL_CMD_OPTS = Set.of( 156 "--multi-package" 157 ); 158 private static final Set<String> UNSUPPORTED_SESSION_CREATE_OPTS = Collections.emptySet(); 159 private static final Map<String, Integer> SUPPORTED_PERMISSION_FLAGS = new ArrayMap<>(); 160 private static final List<String> SUPPORTED_PERMISSION_FLAGS_LIST; 161 static { 162 SUPPORTED_PERMISSION_FLAGS_LIST = List.of("review-required", "revoked-compat", 163 "revoke-when-requested", "user-fixed", "user-set"); 164 SUPPORTED_PERMISSION_FLAGS.put("user-set", FLAG_PERMISSION_USER_SET); 165 SUPPORTED_PERMISSION_FLAGS.put("user-fixed", FLAG_PERMISSION_USER_FIXED); 166 SUPPORTED_PERMISSION_FLAGS.put("revoked-compat", FLAG_PERMISSION_REVOKED_COMPAT); 167 SUPPORTED_PERMISSION_FLAGS.put("review-required", FLAG_PERMISSION_REVIEW_REQUIRED); 168 SUPPORTED_PERMISSION_FLAGS.put("revoke-when-requested", 169 FLAG_PERMISSION_REVOKE_WHEN_REQUESTED); 170 } 171 172 final IPackageManager mInterface; 173 final LegacyPermissionManagerInternal mLegacyPermissionManager; 174 final PermissionManager mPermissionManager; 175 final Context mContext; 176 final DomainVerificationShell mDomainVerificationShell; 177 final private WeakHashMap<String, Resources> mResourceCache = 178 new WeakHashMap<String, Resources>(); 179 int mTargetUser; 180 boolean mBrief; 181 boolean mComponents; 182 int mQueryFlags; 183 184 private static final SecureRandom RANDOM = new SecureRandom(); 185 PackageManagerShellCommand(@onNull IPackageManager packageManager, @NonNull Context context, @NonNull DomainVerificationShell domainVerificationShell)186 PackageManagerShellCommand(@NonNull IPackageManager packageManager, 187 @NonNull Context context, @NonNull DomainVerificationShell domainVerificationShell) { 188 mInterface = packageManager; 189 mLegacyPermissionManager = LocalServices.getService(LegacyPermissionManagerInternal.class); 190 mPermissionManager = context.getSystemService(PermissionManager.class); 191 mContext = context; 192 mDomainVerificationShell = domainVerificationShell; 193 } 194 195 @Override onCommand(String cmd)196 public int onCommand(String cmd) { 197 if (cmd == null) { 198 return handleDefaultCommands(cmd); 199 } 200 201 final PrintWriter pw = getOutPrintWriter(); 202 try { 203 switch (cmd) { 204 case "path": 205 return runPath(); 206 case "dump": 207 return runDump(); 208 case "list": 209 return runList(); 210 case "gc": 211 return runGc(); 212 case "resolve-activity": 213 return runResolveActivity(); 214 case "query-activities": 215 return runQueryIntentActivities(); 216 case "query-services": 217 return runQueryIntentServices(); 218 case "query-receivers": 219 return runQueryIntentReceivers(); 220 case "install": 221 return runInstall(); 222 case "install-streaming": 223 return runStreamingInstall(); 224 case "install-incremental": 225 return runIncrementalInstall(); 226 case "install-abandon": 227 case "install-destroy": 228 return runInstallAbandon(); 229 case "install-commit": 230 return runInstallCommit(); 231 case "install-create": 232 return runInstallCreate(); 233 case "install-remove": 234 return runInstallRemove(); 235 case "install-write": 236 return runInstallWrite(); 237 case "install-existing": 238 return runInstallExisting(); 239 case "set-install-location": 240 return runSetInstallLocation(); 241 case "get-install-location": 242 return runGetInstallLocation(); 243 case "install-add-session": 244 return runInstallAddSession(); 245 case "move-package": 246 return runMovePackage(); 247 case "move-primary-storage": 248 return runMovePrimaryStorage(); 249 case "compile": 250 return runCompile(); 251 case "reconcile-secondary-dex-files": 252 return runreconcileSecondaryDexFiles(); 253 case "force-dex-opt": 254 return runForceDexOpt(); 255 case "bg-dexopt-job": 256 return runDexoptJob(); 257 case "cancel-bg-dexopt-job": 258 return cancelBgDexOptJob(); 259 case "delete-dexopt": 260 return runDeleteDexOpt(); 261 case "dump-profiles": 262 return runDumpProfiles(); 263 case "snapshot-profile": 264 return runSnapshotProfile(); 265 case "uninstall": 266 return runUninstall(); 267 case "clear": 268 return runClear(); 269 case "enable": 270 return runSetEnabledSetting(PackageManager.COMPONENT_ENABLED_STATE_ENABLED); 271 case "disable": 272 return runSetEnabledSetting(PackageManager.COMPONENT_ENABLED_STATE_DISABLED); 273 case "disable-user": 274 return runSetEnabledSetting( 275 PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER); 276 case "disable-until-used": 277 return runSetEnabledSetting( 278 PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED); 279 case "default-state": 280 return runSetEnabledSetting(PackageManager.COMPONENT_ENABLED_STATE_DEFAULT); 281 case "hide": 282 return runSetHiddenSetting(true); 283 case "unhide": 284 return runSetHiddenSetting(false); 285 case "suspend": 286 return runSuspend(true); 287 case "unsuspend": 288 return runSuspend(false); 289 case "set-distracting-restriction": 290 return runSetDistractingRestriction(); 291 case "grant": 292 return runGrantRevokePermission(true); 293 case "revoke": 294 return runGrantRevokePermission(false); 295 case "reset-permissions": 296 return runResetPermissions(); 297 case "set-permission-flags": 298 return setOrClearPermissionFlags(true); 299 case "clear-permission-flags": 300 return setOrClearPermissionFlags(false); 301 case "set-permission-enforced": 302 return runSetPermissionEnforced(); 303 case "get-privapp-permissions": 304 return runGetPrivappPermissions(); 305 case "get-privapp-deny-permissions": 306 return runGetPrivappDenyPermissions(); 307 case "get-oem-permissions": 308 return runGetOemPermissions(); 309 case "trim-caches": 310 return runTrimCaches(); 311 case "create-user": 312 return runCreateUser(); 313 case "remove-user": 314 return runRemoveUser(); 315 case "set-user-restriction": 316 return runSetUserRestriction(); 317 case "get-max-users": 318 return runGetMaxUsers(); 319 case "get-max-running-users": 320 return runGetMaxRunningUsers(); 321 case "set-home-activity": 322 return runSetHomeActivity(); 323 case "set-installer": 324 return runSetInstaller(); 325 case "get-instantapp-resolver": 326 return runGetInstantAppResolver(); 327 case "has-feature": 328 return runHasFeature(); 329 case "set-harmful-app-warning": 330 return runSetHarmfulAppWarning(); 331 case "get-harmful-app-warning": 332 return runGetHarmfulAppWarning(); 333 case "get-stagedsessions": 334 return runListStagedSessions(); 335 case "uninstall-system-updates": 336 String packageName = getNextArg(); 337 return uninstallSystemUpdates(packageName); 338 case "rollback-app": 339 return runRollbackApp(); 340 case "get-moduleinfo": 341 return runGetModuleInfo(); 342 case "log-visibility": 343 return runLogVisibility(); 344 case "bypass-staged-installer-check": 345 return runBypassStagedInstallerCheck(); 346 case "bypass-allowed-apex-update-check": 347 return runBypassAllowedApexUpdateCheck(); 348 case "set-silent-updates-policy": 349 return runSetSilentUpdatesPolicy(); 350 default: { 351 Boolean domainVerificationResult = 352 mDomainVerificationShell.runCommand(this, cmd); 353 if (domainVerificationResult != null) { 354 return domainVerificationResult ? 0 : 1; 355 } 356 357 String nextArg = getNextArg(); 358 if (nextArg == null) { 359 if (cmd.equalsIgnoreCase("-l")) { 360 return runListPackages(false); 361 } else if (cmd.equalsIgnoreCase("-lf")) { 362 return runListPackages(true); 363 } 364 } else if (getNextArg() == null) { 365 if (cmd.equalsIgnoreCase("-p")) { 366 return displayPackageFilePath(nextArg, UserHandle.USER_SYSTEM); 367 } 368 } 369 return handleDefaultCommands(cmd); 370 } 371 } 372 } catch (RemoteException e) { 373 pw.println("Remote exception: " + e); 374 } 375 return -1; 376 } 377 378 /** 379 * Shows module info 380 * 381 * Usage: get-moduleinfo [--all | --installed] [module-name] 382 * Example: get-moduleinfo, get-moduleinfo --all, get-moduleinfo xyz 383 */ runGetModuleInfo()384 private int runGetModuleInfo() { 385 final PrintWriter pw = getOutPrintWriter(); 386 int flags = 0; 387 388 String opt; 389 while ((opt = getNextOption()) != null) { 390 switch (opt) { 391 case "--all": 392 flags |= PackageManager.MATCH_ALL; 393 break; 394 case "--installed": 395 break; 396 default: 397 pw.println("Error: Unknown option: " + opt); 398 return -1; 399 } 400 } 401 402 String moduleName = getNextArg(); 403 try { 404 if (moduleName != null) { 405 ModuleInfo m = mInterface.getModuleInfo(moduleName, flags); 406 pw.println(m.toString() + " packageName: " + m.getPackageName()); 407 408 } else { 409 List<ModuleInfo> modules = mInterface.getInstalledModules(flags); 410 for (ModuleInfo m: modules) { 411 pw.println(m.toString() + " packageName: " + m.getPackageName()); 412 } 413 } 414 } catch (RemoteException e) { 415 pw.println("Failure [" + e.getClass().getName() + " - " + e.getMessage() + "]"); 416 return -1; 417 } 418 return 1; 419 } 420 runLogVisibility()421 private int runLogVisibility() { 422 final PrintWriter pw = getOutPrintWriter(); 423 boolean enable = true; 424 425 String opt; 426 while ((opt = getNextOption()) != null) { 427 switch (opt) { 428 case "--disable": 429 enable = false; 430 break; 431 case "--enable": 432 enable = true; 433 break; 434 default: 435 pw.println("Error: Unknown option: " + opt); 436 return -1; 437 } 438 } 439 440 String packageName = getNextArg(); 441 if (packageName != null) { 442 LocalServices.getService(PackageManagerInternal.class) 443 .setVisibilityLogging(packageName, enable); 444 } else { 445 getErrPrintWriter().println("Error: no package specified"); 446 return -1; 447 } 448 return 1; 449 } 450 runBypassStagedInstallerCheck()451 private int runBypassStagedInstallerCheck() { 452 final PrintWriter pw = getOutPrintWriter(); 453 try { 454 mInterface.getPackageInstaller() 455 .bypassNextStagedInstallerCheck(Boolean.parseBoolean(getNextArg())); 456 return 0; 457 } catch (RemoteException e) { 458 pw.println("Failure [" 459 + e.getClass().getName() + " - " 460 + e.getMessage() + "]"); 461 return -1; 462 } 463 } 464 runBypassAllowedApexUpdateCheck()465 private int runBypassAllowedApexUpdateCheck() { 466 final PrintWriter pw = getOutPrintWriter(); 467 try { 468 mInterface.getPackageInstaller() 469 .bypassNextAllowedApexUpdateCheck(Boolean.parseBoolean(getNextArg())); 470 return 0; 471 } catch (RemoteException e) { 472 pw.println("Failure [" 473 + e.getClass().getName() + " - " 474 + e.getMessage() + "]"); 475 return -1; 476 } 477 } 478 uninstallSystemUpdates(String packageName)479 private int uninstallSystemUpdates(String packageName) { 480 final PrintWriter pw = getOutPrintWriter(); 481 boolean failedUninstalls = false; 482 try { 483 final IPackageInstaller installer = mInterface.getPackageInstaller(); 484 final List<ApplicationInfo> list; 485 if (packageName == null) { 486 final ParceledListSlice<ApplicationInfo> packages = 487 mInterface.getInstalledApplications(PackageManager.MATCH_SYSTEM_ONLY 488 | PackageManager.MATCH_UNINSTALLED_PACKAGES, 489 UserHandle.USER_SYSTEM); 490 list = packages.getList(); 491 } else { 492 list = new ArrayList<>(1); 493 list.add(mInterface.getApplicationInfo(packageName, PackageManager.MATCH_SYSTEM_ONLY 494 | PackageManager.MATCH_UNINSTALLED_PACKAGES, 495 UserHandle.USER_SYSTEM)); 496 } 497 for (ApplicationInfo info : list) { 498 if (info.isUpdatedSystemApp()) { 499 pw.println("Uninstalling updates to " + info.packageName + "..."); 500 final LocalIntentReceiver receiver = new LocalIntentReceiver(); 501 installer.uninstall(new VersionedPackage(info.packageName, 502 info.versionCode), null /*callerPackageName*/, 0 /* flags */, 503 receiver.getIntentSender(), 0); 504 505 final Intent result = receiver.getResult(); 506 final int status = result.getIntExtra(PackageInstaller.EXTRA_STATUS, 507 PackageInstaller.STATUS_FAILURE); 508 if (status != PackageInstaller.STATUS_SUCCESS) { 509 failedUninstalls = true; 510 pw.println("Couldn't uninstall package: " + info.packageName); 511 } 512 } 513 } 514 } catch (RemoteException e) { 515 pw.println("Failure [" 516 + e.getClass().getName() + " - " 517 + e.getMessage() + "]"); 518 return 0; 519 } 520 if (failedUninstalls) { 521 return 0; 522 } 523 pw.println("Success"); 524 return 1; 525 } 526 runRollbackApp()527 private int runRollbackApp() throws RemoteException { 528 final PrintWriter pw = getOutPrintWriter(); 529 530 String opt; 531 long stagedReadyTimeoutMs = DEFAULT_STAGED_READY_TIMEOUT_MS; 532 while ((opt = getNextOption()) != null) { 533 switch (opt) { 534 case "--staged-ready-timeout": 535 stagedReadyTimeoutMs = Long.parseLong(getNextArgRequired()); 536 break; 537 default: 538 throw new IllegalArgumentException("Unknown option: " + opt); 539 } 540 } 541 final String packageName = getNextArgRequired(); 542 if (packageName == null) { 543 pw.println("Error: package name not specified"); 544 return 1; 545 } 546 547 final Context shellPackageContext; 548 try { 549 shellPackageContext = mContext.createPackageContextAsUser( 550 "com.android.shell", 0, Binder.getCallingUserHandle()); 551 } catch (NameNotFoundException e) { 552 // should not happen 553 throw new RuntimeException(e); 554 } 555 556 final LocalIntentReceiver receiver = new LocalIntentReceiver(); 557 RollbackManager rm = shellPackageContext.getSystemService(RollbackManager.class); 558 RollbackInfo rollback = null; 559 for (RollbackInfo r : rm.getAvailableRollbacks()) { 560 for (PackageRollbackInfo info : r.getPackages()) { 561 if (packageName.equals(info.getPackageName())) { 562 rollback = r; 563 break; 564 } 565 } 566 } 567 568 if (rollback == null) { 569 pw.println("No available rollbacks for: " + packageName); 570 return 1; 571 } 572 573 rm.commitRollback(rollback.getRollbackId(), 574 Collections.emptyList(), receiver.getIntentSender()); 575 576 final Intent result = receiver.getResult(); 577 final int status = result.getIntExtra(RollbackManager.EXTRA_STATUS, 578 RollbackManager.STATUS_FAILURE); 579 580 if (status != RollbackManager.STATUS_SUCCESS) { 581 pw.println("Failure [" 582 + result.getStringExtra(RollbackManager.EXTRA_STATUS_MESSAGE) + "]"); 583 return 1; 584 } 585 586 if (rollback.isStaged() && stagedReadyTimeoutMs > 0) { 587 final int committedSessionId = rollback.getCommittedSessionId(); 588 return doWaitForStagedSessionReady(committedSessionId, stagedReadyTimeoutMs, pw); 589 } 590 591 pw.println("Success"); 592 return 0; 593 594 } 595 setParamsSize(InstallParams params, List<String> inPaths)596 private void setParamsSize(InstallParams params, List<String> inPaths) { 597 if (params.sessionParams.sizeBytes != -1 || STDIN_PATH.equals(inPaths.get(0))) { 598 return; 599 } 600 601 long sessionSize = 0; 602 603 ParseTypeImpl input = ParseTypeImpl.forDefaultParsing(); 604 for (String inPath : inPaths) { 605 final ParcelFileDescriptor fd = openFileForSystem(inPath, "r"); 606 if (fd == null) { 607 getErrPrintWriter().println("Error: Can't open file: " + inPath); 608 throw new IllegalArgumentException("Error: Can't open file: " + inPath); 609 } 610 try { 611 ParseResult<ApkLite> apkLiteResult = ApkLiteParseUtils.parseApkLite( 612 input.reset(), fd.getFileDescriptor(), inPath, 0); 613 if (apkLiteResult.isError()) { 614 throw new IllegalArgumentException( 615 "Error: Failed to parse APK file: " + inPath + ": " 616 + apkLiteResult.getErrorMessage(), 617 apkLiteResult.getException()); 618 } 619 final ApkLite apkLite = apkLiteResult.getResult(); 620 final PackageLite pkgLite = new PackageLite(null, apkLite.getPath(), apkLite, 621 null /* splitNames */, null /* isFeatureSplits */, 622 null /* usesSplitNames */, null /* configForSplit */, 623 null /* splitApkPaths */, null /* splitRevisionCodes */, 624 apkLite.getTargetSdkVersion(), null /* requiredSplitTypes */, 625 null /* splitTypes */); 626 sessionSize += InstallLocationUtils.calculateInstalledSize(pkgLite, 627 params.sessionParams.abiOverride, fd.getFileDescriptor()); 628 } catch (IOException e) { 629 getErrPrintWriter().println("Error: Failed to parse APK file: " + inPath); 630 throw new IllegalArgumentException( 631 "Error: Failed to parse APK file: " + inPath, e); 632 } finally { 633 try { 634 fd.close(); 635 } catch (IOException e) { 636 } 637 } 638 } 639 640 params.sessionParams.setSize(sessionSize); 641 } 642 /** 643 * Displays the package file for a package. 644 * @param pckg 645 */ displayPackageFilePath(String pckg, int userId)646 private int displayPackageFilePath(String pckg, int userId) throws RemoteException { 647 PackageInfo info = mInterface.getPackageInfo(pckg, PackageManager.MATCH_APEX, userId); 648 if (info != null && info.applicationInfo != null) { 649 final PrintWriter pw = getOutPrintWriter(); 650 pw.print("package:"); 651 pw.println(info.applicationInfo.sourceDir); 652 if (!ArrayUtils.isEmpty(info.applicationInfo.splitSourceDirs)) { 653 for (String splitSourceDir : info.applicationInfo.splitSourceDirs) { 654 pw.print("package:"); 655 pw.println(splitSourceDir); 656 } 657 } 658 return 0; 659 } 660 return 1; 661 } 662 runPath()663 private int runPath() throws RemoteException { 664 int userId = UserHandle.USER_SYSTEM; 665 String option = getNextOption(); 666 if (option != null && option.equals("--user")) { 667 userId = UserHandle.parseUserArg(getNextArgRequired()); 668 } 669 670 String pkg = getNextArgRequired(); 671 if (pkg == null) { 672 getErrPrintWriter().println("Error: no package specified"); 673 return 1; 674 } 675 final int translatedUserId = 676 translateUserId(userId, UserHandle.USER_NULL, "runPath"); 677 return displayPackageFilePath(pkg, translatedUserId); 678 } 679 runList()680 private int runList() throws RemoteException { 681 final PrintWriter pw = getOutPrintWriter(); 682 final String type = getNextArg(); 683 if (type == null) { 684 pw.println("Error: didn't specify type of data to list"); 685 return -1; 686 } 687 switch(type) { 688 case "features": 689 return runListFeatures(); 690 case "instrumentation": 691 return runListInstrumentation(); 692 case "libraries": 693 return runListLibraries(); 694 case "package": 695 case "packages": 696 return runListPackages(false /*showSourceDir*/); 697 case "permission-groups": 698 return runListPermissionGroups(); 699 case "permissions": 700 return runListPermissions(); 701 case "staged-sessions": 702 return runListStagedSessions(); 703 case "sdks": 704 return runListSdks(); 705 case "users": 706 ServiceManager.getService("user").shellCommand( 707 getInFileDescriptor(), getOutFileDescriptor(), getErrFileDescriptor(), 708 new String[] { "list" }, getShellCallback(), adoptResultReceiver()); 709 return 0; 710 } 711 pw.println("Error: unknown list type '" + type + "'"); 712 return -1; 713 } 714 runGc()715 private int runGc() throws RemoteException { 716 Runtime.getRuntime().gc(); 717 final PrintWriter pw = getOutPrintWriter(); 718 pw.println("Ok"); 719 return 0; 720 } 721 runListFeatures()722 private int runListFeatures() throws RemoteException { 723 final PrintWriter pw = getOutPrintWriter(); 724 final List<FeatureInfo> list = mInterface.getSystemAvailableFeatures().getList(); 725 726 // sort by name 727 Collections.sort(list, new Comparator<FeatureInfo>() { 728 public int compare(FeatureInfo o1, FeatureInfo o2) { 729 if (o1.name == o2.name) return 0; 730 if (o1.name == null) return -1; 731 if (o2.name == null) return 1; 732 return o1.name.compareTo(o2.name); 733 } 734 }); 735 736 final int count = (list != null) ? list.size() : 0; 737 for (int p = 0; p < count; p++) { 738 FeatureInfo fi = list.get(p); 739 pw.print("feature:"); 740 if (fi.name != null) { 741 pw.print(fi.name); 742 if (fi.version > 0) { 743 pw.print("="); 744 pw.print(fi.version); 745 } 746 pw.println(); 747 } else { 748 pw.println("reqGlEsVersion=0x" 749 + Integer.toHexString(fi.reqGlEsVersion)); 750 } 751 } 752 return 0; 753 } 754 runListInstrumentation()755 private int runListInstrumentation() throws RemoteException { 756 final PrintWriter pw = getOutPrintWriter(); 757 boolean showSourceDir = false; 758 String targetPackage = null; 759 760 try { 761 String opt; 762 while ((opt = getNextArg()) != null) { 763 switch (opt) { 764 case "-f": 765 showSourceDir = true; 766 break; 767 default: 768 if (opt.charAt(0) != '-') { 769 targetPackage = opt; 770 } else { 771 pw.println("Error: Unknown option: " + opt); 772 return -1; 773 } 774 break; 775 } 776 } 777 } catch (RuntimeException ex) { 778 pw.println("Error: " + ex.toString()); 779 return -1; 780 } 781 782 final List<InstrumentationInfo> list = 783 mInterface.queryInstrumentation(targetPackage, 0 /*flags*/).getList(); 784 785 // sort by target package 786 Collections.sort(list, new Comparator<InstrumentationInfo>() { 787 public int compare(InstrumentationInfo o1, InstrumentationInfo o2) { 788 return o1.targetPackage.compareTo(o2.targetPackage); 789 } 790 }); 791 792 final int count = (list != null) ? list.size() : 0; 793 for (int p = 0; p < count; p++) { 794 final InstrumentationInfo ii = list.get(p); 795 pw.print("instrumentation:"); 796 if (showSourceDir) { 797 pw.print(ii.sourceDir); 798 pw.print("="); 799 } 800 final ComponentName cn = new ComponentName(ii.packageName, ii.name); 801 pw.print(cn.flattenToShortString()); 802 pw.print(" (target="); 803 pw.print(ii.targetPackage); 804 pw.println(")"); 805 } 806 return 0; 807 } 808 runListLibraries()809 private int runListLibraries() throws RemoteException { 810 final PrintWriter pw = getOutPrintWriter(); 811 final List<String> list = new ArrayList<String>(); 812 final String[] rawList = mInterface.getSystemSharedLibraryNames(); 813 for (int i = 0; i < rawList.length; i++) { 814 list.add(rawList[i]); 815 } 816 817 // sort by name 818 Collections.sort(list, new Comparator<String>() { 819 public int compare(String o1, String o2) { 820 if (o1 == o2) return 0; 821 if (o1 == null) return -1; 822 if (o2 == null) return 1; 823 return o1.compareTo(o2); 824 } 825 }); 826 827 final int count = (list != null) ? list.size() : 0; 828 for (int p = 0; p < count; p++) { 829 String lib = list.get(p); 830 pw.print("library:"); 831 pw.println(lib); 832 } 833 return 0; 834 } 835 runListPackages(boolean showSourceDir)836 private int runListPackages(boolean showSourceDir) throws RemoteException { 837 return runListPackages(showSourceDir, false); 838 } 839 runListSdks()840 private int runListSdks() throws RemoteException { 841 return runListPackages(false, true); 842 } 843 runListPackages(boolean showSourceDir, boolean showSdks)844 private int runListPackages(boolean showSourceDir, boolean showSdks) throws RemoteException { 845 final String prefix = showSdks ? "sdk:" : "package:"; 846 final PrintWriter pw = getOutPrintWriter(); 847 int getFlags = 0; 848 boolean listDisabled = false, listEnabled = false; 849 boolean listSystem = false, listThirdParty = false; 850 boolean listInstaller = false; 851 boolean showUid = false; 852 boolean showVersionCode = false; 853 boolean listApexOnly = false; 854 int uid = -1; 855 int defaultUserId = UserHandle.USER_ALL; 856 try { 857 String opt; 858 while ((opt = getNextOption()) != null) { 859 switch (opt) { 860 case "-d": 861 listDisabled = true; 862 break; 863 case "-e": 864 listEnabled = true; 865 break; 866 case "-a": 867 getFlags |= PackageManager.MATCH_KNOWN_PACKAGES; 868 getFlags |= PackageManager.MATCH_HIDDEN_UNTIL_INSTALLED_COMPONENTS; 869 break; 870 case "-f": 871 showSourceDir = true; 872 break; 873 case "-i": 874 listInstaller = true; 875 break; 876 case "-l": 877 // old compat 878 break; 879 case "-s": 880 listSystem = true; 881 break; 882 case "-U": 883 showUid = true; 884 break; 885 case "-u": 886 getFlags |= PackageManager.MATCH_UNINSTALLED_PACKAGES; 887 break; 888 case "-3": 889 listThirdParty = true; 890 break; 891 case "--show-versioncode": 892 showVersionCode = true; 893 break; 894 case "--apex-only": 895 getFlags |= PackageManager.MATCH_APEX; 896 listApexOnly = true; 897 break; 898 case "--user": 899 defaultUserId = UserHandle.parseUserArg(getNextArgRequired()); 900 break; 901 case "--uid": 902 showUid = true; 903 uid = Integer.parseInt(getNextArgRequired()); 904 break; 905 default: 906 pw.println("Error: Unknown option: " + opt); 907 return -1; 908 } 909 } 910 } catch (RuntimeException ex) { 911 pw.println("Error: " + ex.toString()); 912 return -1; 913 } 914 915 final String filter = getNextArg(); 916 917 int[] userIds = {defaultUserId}; 918 if (defaultUserId == UserHandle.USER_ALL) { 919 final UserManagerInternal umi = LocalServices.getService(UserManagerInternal.class); 920 userIds = umi.getUserIds(); 921 } 922 if (showSdks) { 923 getFlags |= PackageManager.MATCH_STATIC_SHARED_AND_SDK_LIBRARIES; 924 } 925 926 // Build a map of packages to a list of corresponding uids. Keys are strings containing 927 // the sdk or package name along with optional additional information based on opt. 928 final Map<String, List<String>> out = new HashMap<>(); 929 for (int userId : userIds) { 930 final int translatedUserId = 931 translateUserId(userId, UserHandle.USER_SYSTEM, "runListPackages"); 932 @SuppressWarnings("unchecked") final ParceledListSlice<PackageInfo> slice = 933 mInterface.getInstalledPackages(getFlags, translatedUserId); 934 final List<PackageInfo> packages = slice.getList(); 935 936 final int count = packages.size(); 937 for (int p = 0; p < count; p++) { 938 final PackageInfo info = packages.get(p); 939 final StringBuilder stringBuilder = new StringBuilder(); 940 if (filter != null && !info.packageName.contains(filter)) { 941 continue; 942 } 943 final boolean isApex = info.isApex; 944 if (uid != -1 && !isApex && info.applicationInfo.uid != uid) { 945 continue; 946 } 947 948 final boolean isSystem = !isApex 949 && (info.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0; 950 final boolean isEnabled = !isApex && info.applicationInfo.enabled; 951 if ((listDisabled && isEnabled) 952 || (listEnabled && !isEnabled) 953 || (listSystem && !isSystem) 954 || (listThirdParty && isSystem) 955 || (listApexOnly && !isApex)) { 956 continue; 957 } 958 959 String name = null; 960 if (showSdks) { 961 final ParceledListSlice<SharedLibraryInfo> libsSlice = 962 mInterface.getDeclaredSharedLibraries( 963 info.packageName, getFlags, userId 964 ); 965 if (libsSlice == null) { 966 continue; 967 } 968 final List<SharedLibraryInfo> libs = libsSlice.getList(); 969 for (int l = 0, lsize = libs.size(); l < lsize; ++l) { 970 SharedLibraryInfo lib = libs.get(l); 971 if (lib.getType() == SharedLibraryInfo.TYPE_SDK_PACKAGE) { 972 name = lib.getName() + ":" + lib.getLongVersion(); 973 break; 974 } 975 } 976 if (name == null) { 977 continue; 978 } 979 } else { 980 name = info.packageName; 981 } 982 983 stringBuilder.append(prefix); 984 if (showSourceDir) { 985 stringBuilder.append(info.applicationInfo.sourceDir); 986 stringBuilder.append("="); 987 } 988 stringBuilder.append(name); 989 if (showVersionCode) { 990 stringBuilder.append(" versionCode:"); 991 if (info.applicationInfo != null) { 992 stringBuilder.append(info.applicationInfo.longVersionCode); 993 } else { 994 stringBuilder.append(info.getLongVersionCode()); 995 } 996 } 997 if (listInstaller) { 998 stringBuilder.append(" installer="); 999 stringBuilder.append(mInterface.getInstallerPackageName(info.packageName)); 1000 } 1001 List<String> uids = out.computeIfAbsent( 1002 stringBuilder.toString(), k -> new ArrayList<>() 1003 ); 1004 if (showUid && !isApex) { 1005 uids.add(String.valueOf(info.applicationInfo.uid)); 1006 } 1007 } 1008 } 1009 for (Map.Entry<String, List<String>> entry : out.entrySet()) { 1010 pw.print(entry.getKey()); 1011 List<String> uids = entry.getValue(); 1012 if (!uids.isEmpty()) { 1013 pw.print(" uid:"); 1014 pw.print(String.join(",", uids)); 1015 } 1016 pw.println(); 1017 } 1018 return 0; 1019 } 1020 runListPermissionGroups()1021 private int runListPermissionGroups() throws RemoteException { 1022 final PrintWriter pw = getOutPrintWriter(); 1023 final List<PermissionGroupInfo> pgs = mPermissionManager.getAllPermissionGroups(0); 1024 1025 final int count = pgs.size(); 1026 for (int p = 0; p < count ; p++) { 1027 final PermissionGroupInfo pgi = pgs.get(p); 1028 pw.print("permission group:"); 1029 pw.println(pgi.name); 1030 } 1031 return 0; 1032 } 1033 runListPermissions()1034 private int runListPermissions() throws RemoteException { 1035 final PrintWriter pw = getOutPrintWriter(); 1036 boolean labels = false; 1037 boolean groups = false; 1038 boolean userOnly = false; 1039 boolean summary = false; 1040 boolean dangerousOnly = false; 1041 String opt; 1042 while ((opt = getNextOption()) != null) { 1043 switch (opt) { 1044 case "-d": 1045 dangerousOnly = true; 1046 break; 1047 case "-f": 1048 labels = true; 1049 break; 1050 case "-g": 1051 groups = true; 1052 break; 1053 case "-s": 1054 groups = true; 1055 labels = true; 1056 summary = true; 1057 break; 1058 case "-u": 1059 userOnly = true; 1060 break; 1061 default: 1062 pw.println("Error: Unknown option: " + opt); 1063 return 1; 1064 } 1065 } 1066 1067 final ArrayList<String> groupList = new ArrayList<String>(); 1068 if (groups) { 1069 final List<PermissionGroupInfo> infos = 1070 mPermissionManager.getAllPermissionGroups(0 /*flags*/); 1071 final int count = infos.size(); 1072 for (int i = 0; i < count; i++) { 1073 groupList.add(infos.get(i).name); 1074 } 1075 groupList.add(null); 1076 } else { 1077 final String grp = getNextArg(); 1078 groupList.add(grp); 1079 } 1080 1081 if (dangerousOnly) { 1082 pw.println("Dangerous Permissions:"); 1083 pw.println(""); 1084 doListPermissions(groupList, groups, labels, summary, 1085 PermissionInfo.PROTECTION_DANGEROUS, 1086 PermissionInfo.PROTECTION_DANGEROUS); 1087 if (userOnly) { 1088 pw.println("Normal Permissions:"); 1089 pw.println(""); 1090 doListPermissions(groupList, groups, labels, summary, 1091 PermissionInfo.PROTECTION_NORMAL, 1092 PermissionInfo.PROTECTION_NORMAL); 1093 } 1094 } else if (userOnly) { 1095 pw.println("Dangerous and Normal Permissions:"); 1096 pw.println(""); 1097 doListPermissions(groupList, groups, labels, summary, 1098 PermissionInfo.PROTECTION_NORMAL, 1099 PermissionInfo.PROTECTION_DANGEROUS); 1100 } else { 1101 pw.println("All Permissions:"); 1102 pw.println(""); 1103 doListPermissions(groupList, groups, labels, summary, 1104 -10000, 10000); 1105 } 1106 return 0; 1107 } 1108 1109 private static class SessionDump { 1110 boolean onlyParent; // Show parent sessions only 1111 boolean onlyReady; // Show only staged sessions that are in ready state 1112 boolean onlySessionId; // Show sessionId only 1113 } 1114 1115 // Returns true if the provided flag is a session flag and given SessionDump was updated setSessionFlag(String flag, SessionDump sessionDump)1116 private boolean setSessionFlag(String flag, SessionDump sessionDump) { 1117 switch (flag) { 1118 case "--only-parent": 1119 sessionDump.onlyParent = true; 1120 break; 1121 case "--only-ready": 1122 sessionDump.onlyReady = true; 1123 break; 1124 case "--only-sessionid": 1125 sessionDump.onlySessionId = true; 1126 break; 1127 default: 1128 return false; 1129 } 1130 return true; 1131 } 1132 runListStagedSessions()1133 private int runListStagedSessions() { 1134 try (IndentingPrintWriter pw = new IndentingPrintWriter( 1135 getOutPrintWriter(), /* singleIndent */ " ", /* wrapLength */ 120)) { 1136 final SessionDump sessionDump = new SessionDump(); 1137 String opt; 1138 while ((opt = getNextOption()) != null) { 1139 if (!setSessionFlag(opt, sessionDump)) { 1140 pw.println("Error: Unknown option: " + opt); 1141 return -1; 1142 } 1143 } 1144 1145 try { 1146 final List<SessionInfo> stagedSessions = 1147 mInterface.getPackageInstaller().getStagedSessions().getList(); 1148 printSessionList(pw, stagedSessions, sessionDump); 1149 } catch (RemoteException e) { 1150 pw.println("Failure [" 1151 + e.getClass().getName() + " - " 1152 + e.getMessage() + "]"); 1153 return -1; 1154 } 1155 return 1; 1156 } 1157 } 1158 printSessionList(IndentingPrintWriter pw, List<SessionInfo> stagedSessions, SessionDump sessionDump)1159 private void printSessionList(IndentingPrintWriter pw, List<SessionInfo> stagedSessions, 1160 SessionDump sessionDump) { 1161 final SparseArray<SessionInfo> sessionById = new SparseArray<>(stagedSessions.size()); 1162 for (SessionInfo session : stagedSessions) { 1163 sessionById.put(session.getSessionId(), session); 1164 } 1165 for (SessionInfo session: stagedSessions) { 1166 if (sessionDump.onlyReady && !session.isStagedSessionReady()) { 1167 continue; 1168 } 1169 if (session.getParentSessionId() != SessionInfo.INVALID_ID) { 1170 continue; 1171 } 1172 printSession(pw, session, sessionDump); 1173 if (session.isMultiPackage() && !sessionDump.onlyParent) { 1174 pw.increaseIndent(); 1175 final int[] childIds = session.getChildSessionIds(); 1176 for (int i = 0; i < childIds.length; i++) { 1177 final SessionInfo childSession = sessionById.get(childIds[i]); 1178 if (childSession == null) { 1179 if (sessionDump.onlySessionId) { 1180 pw.println(childIds[i]); 1181 } else { 1182 pw.println("sessionId = " + childIds[i] + "; not found"); 1183 } 1184 } else { 1185 printSession(pw, childSession, sessionDump); 1186 } 1187 } 1188 pw.decreaseIndent(); 1189 } 1190 } 1191 } 1192 printSession(PrintWriter pw, SessionInfo session, SessionDump sessionDump)1193 private static void printSession(PrintWriter pw, SessionInfo session, SessionDump sessionDump) { 1194 if (sessionDump.onlySessionId) { 1195 pw.println(session.getSessionId()); 1196 return; 1197 } 1198 pw.println("sessionId = " + session.getSessionId() 1199 + "; appPackageName = " + session.getAppPackageName() 1200 + "; isStaged = " + session.isStaged() 1201 + "; isReady = " + session.isStagedSessionReady() 1202 + "; isApplied = " + session.isStagedSessionApplied() 1203 + "; isFailed = " + session.isStagedSessionFailed() 1204 + "; errorMsg = " + session.getStagedSessionErrorMessage() 1205 + ";"); 1206 } 1207 parseIntentAndUser()1208 private Intent parseIntentAndUser() throws URISyntaxException { 1209 mTargetUser = UserHandle.USER_CURRENT; 1210 mBrief = false; 1211 mComponents = false; 1212 Intent intent = Intent.parseCommandArgs(this, new Intent.CommandOptionHandler() { 1213 @Override 1214 public boolean handleOption(String opt, ShellCommand cmd) { 1215 if ("--user".equals(opt)) { 1216 mTargetUser = UserHandle.parseUserArg(cmd.getNextArgRequired()); 1217 return true; 1218 } else if ("--brief".equals(opt)) { 1219 mBrief = true; 1220 return true; 1221 } else if ("--components".equals(opt)) { 1222 mComponents = true; 1223 return true; 1224 } else if ("--query-flags".equals(opt)) { 1225 mQueryFlags = Integer.decode(cmd.getNextArgRequired()); 1226 return true; 1227 } 1228 return false; 1229 } 1230 }); 1231 mTargetUser = ActivityManager.handleIncomingUser(Binder.getCallingPid(), 1232 Binder.getCallingUid(), mTargetUser, false, false, null, null); 1233 return intent; 1234 } 1235 printResolveInfo(PrintWriterPrinter pr, String prefix, ResolveInfo ri, boolean brief, boolean components)1236 private void printResolveInfo(PrintWriterPrinter pr, String prefix, ResolveInfo ri, 1237 boolean brief, boolean components) { 1238 if (brief || components) { 1239 final ComponentName comp; 1240 if (ri.activityInfo != null) { 1241 comp = new ComponentName(ri.activityInfo.packageName, ri.activityInfo.name); 1242 } else if (ri.serviceInfo != null) { 1243 comp = new ComponentName(ri.serviceInfo.packageName, ri.serviceInfo.name); 1244 } else if (ri.providerInfo != null) { 1245 comp = new ComponentName(ri.providerInfo.packageName, ri.providerInfo.name); 1246 } else { 1247 comp = null; 1248 } 1249 if (comp != null) { 1250 if (!components) { 1251 pr.println(prefix + "priority=" + ri.priority 1252 + " preferredOrder=" + ri.preferredOrder 1253 + " match=0x" + Integer.toHexString(ri.match) 1254 + " specificIndex=" + ri.specificIndex 1255 + " isDefault=" + ri.isDefault); 1256 } 1257 pr.println(prefix + comp.flattenToShortString()); 1258 return; 1259 } 1260 } 1261 ri.dump(pr, prefix); 1262 } 1263 runResolveActivity()1264 private int runResolveActivity() { 1265 Intent intent; 1266 try { 1267 intent = parseIntentAndUser(); 1268 } catch (URISyntaxException e) { 1269 throw new RuntimeException(e.getMessage(), e); 1270 } 1271 try { 1272 ResolveInfo ri = mInterface.resolveIntent(intent, intent.getType(), mQueryFlags, 1273 mTargetUser); 1274 PrintWriter pw = getOutPrintWriter(); 1275 if (ri == null) { 1276 pw.println("No activity found"); 1277 } else { 1278 PrintWriterPrinter pr = new PrintWriterPrinter(pw); 1279 printResolveInfo(pr, "", ri, mBrief, mComponents); 1280 } 1281 } catch (RemoteException e) { 1282 throw new RuntimeException("Failed calling service", e); 1283 } 1284 return 0; 1285 } 1286 runQueryIntentActivities()1287 private int runQueryIntentActivities() { 1288 Intent intent; 1289 try { 1290 intent = parseIntentAndUser(); 1291 } catch (URISyntaxException e) { 1292 throw new RuntimeException(e.getMessage(), e); 1293 } 1294 try { 1295 List<ResolveInfo> result = mInterface.queryIntentActivities(intent, intent.getType(), 1296 mQueryFlags, mTargetUser).getList(); 1297 PrintWriter pw = getOutPrintWriter(); 1298 if (result == null || result.size() <= 0) { 1299 pw.println("No activities found"); 1300 } else { 1301 if (!mComponents) { 1302 pw.print(result.size()); pw.println(" activities found:"); 1303 PrintWriterPrinter pr = new PrintWriterPrinter(pw); 1304 for (int i = 0; i < result.size(); i++) { 1305 pw.print(" Activity #"); pw.print(i); pw.println(":"); 1306 printResolveInfo(pr, " ", result.get(i), mBrief, mComponents); 1307 } 1308 } else { 1309 PrintWriterPrinter pr = new PrintWriterPrinter(pw); 1310 for (int i = 0; i < result.size(); i++) { 1311 printResolveInfo(pr, "", result.get(i), mBrief, mComponents); 1312 } 1313 } 1314 } 1315 } catch (RemoteException e) { 1316 throw new RuntimeException("Failed calling service", e); 1317 } 1318 return 0; 1319 } 1320 runQueryIntentServices()1321 private int runQueryIntentServices() { 1322 Intent intent; 1323 try { 1324 intent = parseIntentAndUser(); 1325 } catch (URISyntaxException e) { 1326 throw new RuntimeException(e.getMessage(), e); 1327 } 1328 try { 1329 List<ResolveInfo> result = mInterface.queryIntentServices(intent, intent.getType(), 1330 mQueryFlags, mTargetUser).getList(); 1331 PrintWriter pw = getOutPrintWriter(); 1332 if (result == null || result.size() <= 0) { 1333 pw.println("No services found"); 1334 } else { 1335 if (!mComponents) { 1336 pw.print(result.size()); pw.println(" services found:"); 1337 PrintWriterPrinter pr = new PrintWriterPrinter(pw); 1338 for (int i = 0; i < result.size(); i++) { 1339 pw.print(" Service #"); pw.print(i); pw.println(":"); 1340 printResolveInfo(pr, " ", result.get(i), mBrief, mComponents); 1341 } 1342 } else { 1343 PrintWriterPrinter pr = new PrintWriterPrinter(pw); 1344 for (int i = 0; i < result.size(); i++) { 1345 printResolveInfo(pr, "", result.get(i), mBrief, mComponents); 1346 } 1347 } 1348 } 1349 } catch (RemoteException e) { 1350 throw new RuntimeException("Failed calling service", e); 1351 } 1352 return 0; 1353 } 1354 runQueryIntentReceivers()1355 private int runQueryIntentReceivers() { 1356 Intent intent; 1357 try { 1358 intent = parseIntentAndUser(); 1359 } catch (URISyntaxException e) { 1360 throw new RuntimeException(e.getMessage(), e); 1361 } 1362 try { 1363 List<ResolveInfo> result = mInterface.queryIntentReceivers(intent, intent.getType(), 1364 mQueryFlags, mTargetUser).getList(); 1365 PrintWriter pw = getOutPrintWriter(); 1366 if (result == null || result.size() <= 0) { 1367 pw.println("No receivers found"); 1368 } else { 1369 if (!mComponents) { 1370 pw.print(result.size()); pw.println(" receivers found:"); 1371 PrintWriterPrinter pr = new PrintWriterPrinter(pw); 1372 for (int i = 0; i < result.size(); i++) { 1373 pw.print(" Receiver #"); pw.print(i); pw.println(":"); 1374 printResolveInfo(pr, " ", result.get(i), mBrief, mComponents); 1375 } 1376 } else { 1377 PrintWriterPrinter pr = new PrintWriterPrinter(pw); 1378 for (int i = 0; i < result.size(); i++) { 1379 printResolveInfo(pr, "", result.get(i), mBrief, mComponents); 1380 } 1381 } 1382 } 1383 } catch (RemoteException e) { 1384 throw new RuntimeException("Failed calling service", e); 1385 } 1386 return 0; 1387 } 1388 runStreamingInstall()1389 private int runStreamingInstall() throws RemoteException { 1390 final InstallParams params = makeInstallParams(UNSUPPORTED_INSTALL_CMD_OPTS); 1391 if (params.sessionParams.dataLoaderParams == null) { 1392 params.sessionParams.setDataLoaderParams( 1393 PackageManagerShellCommandDataLoader.getStreamingDataLoaderParams(this)); 1394 } 1395 return doRunInstall(params); 1396 } 1397 runIncrementalInstall()1398 private int runIncrementalInstall() throws RemoteException { 1399 final InstallParams params = makeInstallParams(UNSUPPORTED_INSTALL_CMD_OPTS); 1400 if (params.sessionParams.dataLoaderParams == null) { 1401 params.sessionParams.setDataLoaderParams( 1402 PackageManagerShellCommandDataLoader.getIncrementalDataLoaderParams(this)); 1403 } 1404 return doRunInstall(params); 1405 } 1406 runInstall()1407 private int runInstall() throws RemoteException { 1408 return doRunInstall(makeInstallParams(UNSUPPORTED_INSTALL_CMD_OPTS)); 1409 } 1410 doRunInstall(final InstallParams params)1411 private int doRunInstall(final InstallParams params) throws RemoteException { 1412 final PrintWriter pw = getOutPrintWriter(); 1413 1414 final boolean isStreaming = params.sessionParams.dataLoaderParams != null; 1415 final boolean isApex = 1416 (params.sessionParams.installFlags & PackageManager.INSTALL_APEX) != 0; 1417 1418 ArrayList<String> args = getRemainingArgs(); 1419 1420 final boolean fromStdIn = args.isEmpty() || STDIN_PATH.equals(args.get(0)); 1421 final boolean hasSplits = args.size() > 1; 1422 1423 if (fromStdIn && params.sessionParams.sizeBytes == -1) { 1424 pw.println("Error: must either specify a package size or an APK file"); 1425 return 1; 1426 } 1427 1428 if (isApex && hasSplits) { 1429 pw.println("Error: can't specify SPLIT(s) for APEX"); 1430 return 1; 1431 } 1432 1433 if (!isStreaming) { 1434 if (fromStdIn && hasSplits) { 1435 pw.println("Error: can't specify SPLIT(s) along with STDIN"); 1436 return 1; 1437 } 1438 1439 if (args.isEmpty()) { 1440 args.add(STDIN_PATH); 1441 } else { 1442 setParamsSize(params, args); 1443 } 1444 } 1445 1446 final int sessionId = doCreateSession(params.sessionParams, 1447 params.installerPackageName, params.userId); 1448 boolean abandonSession = true; 1449 try { 1450 if (isStreaming) { 1451 if (doAddFiles(sessionId, args, params.sessionParams.sizeBytes, isApex) 1452 != PackageInstaller.STATUS_SUCCESS) { 1453 return 1; 1454 } 1455 } else { 1456 if (doWriteSplits(sessionId, args, params.sessionParams.sizeBytes, isApex) 1457 != PackageInstaller.STATUS_SUCCESS) { 1458 return 1; 1459 } 1460 } 1461 if (doCommitSession(sessionId, false /*logSuccess*/) 1462 != PackageInstaller.STATUS_SUCCESS) { 1463 return 1; 1464 } 1465 abandonSession = false; 1466 1467 if (params.sessionParams.isStaged && params.stagedReadyTimeoutMs > 0) { 1468 return doWaitForStagedSessionReady(sessionId, params.stagedReadyTimeoutMs, pw); 1469 } 1470 1471 pw.println("Success"); 1472 return 0; 1473 } finally { 1474 if (abandonSession) { 1475 try { 1476 doAbandonSession(sessionId, false /*logSuccess*/); 1477 } catch (Exception ignore) { 1478 } 1479 } 1480 } 1481 } 1482 doWaitForStagedSessionReady(int sessionId, long timeoutMs, PrintWriter pw)1483 private int doWaitForStagedSessionReady(int sessionId, long timeoutMs, PrintWriter pw) 1484 throws RemoteException { 1485 Preconditions.checkArgument(timeoutMs > 0); 1486 PackageInstaller.SessionInfo si = mInterface.getPackageInstaller() 1487 .getSessionInfo(sessionId); 1488 if (si == null) { 1489 pw.println("Failure [Unknown session " + sessionId + "]"); 1490 return 1; 1491 } 1492 if (!si.isStaged()) { 1493 pw.println("Failure [Session " + sessionId + " is not a staged session]"); 1494 return 1; 1495 } 1496 long currentTime = System.currentTimeMillis(); 1497 long endTime = currentTime + timeoutMs; 1498 // Using a loop instead of BroadcastReceiver since we can receive session update 1499 // broadcast only if packageInstallerName is "android". We can't always force 1500 // "android" as packageIntallerName, e.g, rollback auto implies 1501 // "-i com.android.shell". 1502 while (currentTime < endTime) { 1503 if (si != null && (si.isStagedSessionReady() || si.isStagedSessionFailed())) { 1504 break; 1505 } 1506 SystemClock.sleep(Math.min(endTime - currentTime, 100)); 1507 currentTime = System.currentTimeMillis(); 1508 si = mInterface.getPackageInstaller().getSessionInfo(sessionId); 1509 } 1510 if (si == null) { 1511 pw.println("Failure [failed to retrieve SessionInfo]"); 1512 return 1; 1513 } 1514 if (!si.isStagedSessionReady() && !si.isStagedSessionFailed()) { 1515 pw.println("Failure [timed out after " + timeoutMs + " ms]"); 1516 return 1; 1517 } 1518 if (!si.isStagedSessionReady()) { 1519 pw.println("Error [" + si.getStagedSessionErrorCode() + "] [" 1520 + si.getStagedSessionErrorMessage() + "]"); 1521 return 1; 1522 } 1523 pw.println("Success. Reboot device to apply staged session"); 1524 return 0; 1525 } 1526 runInstallAbandon()1527 private int runInstallAbandon() throws RemoteException { 1528 final int sessionId = Integer.parseInt(getNextArg()); 1529 return doAbandonSession(sessionId, true /*logSuccess*/); 1530 } 1531 runInstallCommit()1532 private int runInstallCommit() throws RemoteException { 1533 final PrintWriter pw = getOutPrintWriter(); 1534 String opt; 1535 long stagedReadyTimeoutMs = DEFAULT_STAGED_READY_TIMEOUT_MS; 1536 while ((opt = getNextOption()) != null) { 1537 switch (opt) { 1538 case "--staged-ready-timeout": 1539 stagedReadyTimeoutMs = Long.parseLong(getNextArgRequired()); 1540 break; 1541 default: 1542 throw new IllegalArgumentException("Unknown option: " + opt); 1543 } 1544 } 1545 final int sessionId = Integer.parseInt(getNextArg()); 1546 if (doCommitSession(sessionId, false /*logSuccess*/) != PackageInstaller.STATUS_SUCCESS) { 1547 return 1; 1548 } 1549 final PackageInstaller.SessionInfo si = mInterface.getPackageInstaller() 1550 .getSessionInfo(sessionId); 1551 if (si != null && si.isStaged() && stagedReadyTimeoutMs > 0) { 1552 return doWaitForStagedSessionReady(sessionId, stagedReadyTimeoutMs, pw); 1553 } 1554 pw.println("Success"); 1555 return 0; 1556 } 1557 runInstallCreate()1558 private int runInstallCreate() throws RemoteException { 1559 final PrintWriter pw = getOutPrintWriter(); 1560 final InstallParams installParams = makeInstallParams(UNSUPPORTED_SESSION_CREATE_OPTS); 1561 final int sessionId = doCreateSession(installParams.sessionParams, 1562 installParams.installerPackageName, installParams.userId); 1563 1564 // NOTE: adb depends on parsing this string 1565 pw.println("Success: created install session [" + sessionId + "]"); 1566 return 0; 1567 } 1568 runInstallWrite()1569 private int runInstallWrite() throws RemoteException { 1570 long sizeBytes = -1; 1571 1572 String opt; 1573 while ((opt = getNextOption()) != null) { 1574 if (opt.equals("-S")) { 1575 sizeBytes = Long.parseLong(getNextArg()); 1576 } else { 1577 throw new IllegalArgumentException("Unknown option: " + opt); 1578 } 1579 } 1580 1581 final int sessionId = Integer.parseInt(getNextArg()); 1582 final String splitName = getNextArg(); 1583 final String path = getNextArg(); 1584 return doWriteSplit(sessionId, path, sizeBytes, splitName, true /*logSuccess*/); 1585 } 1586 runInstallAddSession()1587 private int runInstallAddSession() throws RemoteException { 1588 final PrintWriter pw = getOutPrintWriter(); 1589 final int parentSessionId = Integer.parseInt(getNextArg()); 1590 1591 IntArray otherSessionIds = new IntArray(); 1592 String opt; 1593 while ((opt = getNextArg()) != null) { 1594 otherSessionIds.add(Integer.parseInt(opt)); 1595 } 1596 if (otherSessionIds.size() == 0) { 1597 pw.println("Error: At least two sessions are required."); 1598 return 1; 1599 } 1600 return doInstallAddSession(parentSessionId, otherSessionIds.toArray(), 1601 true /*logSuccess*/); 1602 } 1603 runInstallRemove()1604 private int runInstallRemove() throws RemoteException { 1605 final PrintWriter pw = getOutPrintWriter(); 1606 1607 final int sessionId = Integer.parseInt(getNextArg()); 1608 1609 ArrayList<String> splitNames = getRemainingArgs(); 1610 if (splitNames.isEmpty()) { 1611 pw.println("Error: split name not specified"); 1612 return 1; 1613 } 1614 return doRemoveSplits(sessionId, splitNames, true /*logSuccess*/); 1615 } 1616 runInstallExisting()1617 private int runInstallExisting() throws RemoteException { 1618 final PrintWriter pw = getOutPrintWriter(); 1619 int userId = UserHandle.USER_CURRENT; 1620 int installFlags = PackageManager.INSTALL_ALL_WHITELIST_RESTRICTED_PERMISSIONS; 1621 String opt; 1622 boolean waitTillComplete = false; 1623 while ((opt = getNextOption()) != null) { 1624 switch (opt) { 1625 case "--user": 1626 userId = UserHandle.parseUserArg(getNextArgRequired()); 1627 break; 1628 case "--ephemeral": 1629 case "--instant": 1630 installFlags |= PackageManager.INSTALL_INSTANT_APP; 1631 installFlags &= ~PackageManager.INSTALL_FULL_APP; 1632 break; 1633 case "--full": 1634 installFlags &= ~PackageManager.INSTALL_INSTANT_APP; 1635 installFlags |= PackageManager.INSTALL_FULL_APP; 1636 break; 1637 case "--wait": 1638 waitTillComplete = true; 1639 break; 1640 case "--restrict-permissions": 1641 installFlags &= ~PackageManager.INSTALL_ALL_WHITELIST_RESTRICTED_PERMISSIONS; 1642 break; 1643 default: 1644 pw.println("Error: Unknown option: " + opt); 1645 return 1; 1646 } 1647 } 1648 1649 final String packageName = getNextArg(); 1650 if (packageName == null) { 1651 pw.println("Error: package name not specified"); 1652 return 1; 1653 } 1654 final int translatedUserId = 1655 translateUserId(userId, UserHandle.USER_NULL, "runInstallExisting"); 1656 1657 int installReason = PackageManager.INSTALL_REASON_UNKNOWN; 1658 try { 1659 if (waitTillComplete) { 1660 final LocalIntentReceiver receiver = new LocalIntentReceiver(); 1661 final IPackageInstaller installer = mInterface.getPackageInstaller(); 1662 pw.println("Installing package " + packageName + " for user: " + translatedUserId); 1663 installer.installExistingPackage(packageName, installFlags, installReason, 1664 receiver.getIntentSender(), translatedUserId, null); 1665 final Intent result = receiver.getResult(); 1666 final int status = result.getIntExtra(PackageInstaller.EXTRA_STATUS, 1667 PackageInstaller.STATUS_FAILURE); 1668 pw.println("Received intent for package install"); 1669 return status == PackageInstaller.STATUS_SUCCESS ? 0 : 1; 1670 } 1671 1672 final int res = mInterface.installExistingPackageAsUser(packageName, translatedUserId, 1673 installFlags, installReason, null); 1674 if (res == PackageManager.INSTALL_FAILED_INVALID_URI) { 1675 throw new NameNotFoundException("Package " + packageName + " doesn't exist"); 1676 } 1677 pw.println("Package " + packageName + " installed for user: " + translatedUserId); 1678 return 0; 1679 } catch (RemoteException | NameNotFoundException e) { 1680 pw.println(e.toString()); 1681 return 1; 1682 } 1683 } 1684 runSetInstallLocation()1685 private int runSetInstallLocation() throws RemoteException { 1686 int loc; 1687 1688 String arg = getNextArg(); 1689 if (arg == null) { 1690 getErrPrintWriter().println("Error: no install location specified."); 1691 return 1; 1692 } 1693 try { 1694 loc = Integer.parseInt(arg); 1695 } catch (NumberFormatException e) { 1696 getErrPrintWriter().println("Error: install location has to be a number."); 1697 return 1; 1698 } 1699 if (!mInterface.setInstallLocation(loc)) { 1700 getErrPrintWriter().println("Error: install location has to be a number."); 1701 return 1; 1702 } 1703 return 0; 1704 } 1705 runGetInstallLocation()1706 private int runGetInstallLocation() throws RemoteException { 1707 int loc = mInterface.getInstallLocation(); 1708 String locStr = "invalid"; 1709 if (loc == InstallLocationUtils.APP_INSTALL_AUTO) { 1710 locStr = "auto"; 1711 } else if (loc == InstallLocationUtils.APP_INSTALL_INTERNAL) { 1712 locStr = "internal"; 1713 } else if (loc == InstallLocationUtils.APP_INSTALL_EXTERNAL) { 1714 locStr = "external"; 1715 } 1716 getOutPrintWriter().println(loc + "[" + locStr + "]"); 1717 return 0; 1718 } 1719 runMovePackage()1720 public int runMovePackage() throws RemoteException { 1721 final String packageName = getNextArg(); 1722 if (packageName == null) { 1723 getErrPrintWriter().println("Error: package name not specified"); 1724 return 1; 1725 } 1726 String volumeUuid = getNextArg(); 1727 if ("internal".equals(volumeUuid)) { 1728 volumeUuid = null; 1729 } 1730 1731 final int moveId = mInterface.movePackage(packageName, volumeUuid); 1732 1733 int status = mInterface.getMoveStatus(moveId); 1734 while (!PackageManager.isMoveStatusFinished(status)) { 1735 SystemClock.sleep(DateUtils.SECOND_IN_MILLIS); 1736 status = mInterface.getMoveStatus(moveId); 1737 } 1738 1739 if (status == PackageManager.MOVE_SUCCEEDED) { 1740 getOutPrintWriter().println("Success"); 1741 return 0; 1742 } else { 1743 getErrPrintWriter().println("Failure [" + status + "]"); 1744 return 1; 1745 } 1746 } 1747 runMovePrimaryStorage()1748 public int runMovePrimaryStorage() throws RemoteException { 1749 String volumeUuid = getNextArg(); 1750 if ("internal".equals(volumeUuid)) { 1751 volumeUuid = null; 1752 } 1753 1754 final int moveId = mInterface.movePrimaryStorage(volumeUuid); 1755 1756 int status = mInterface.getMoveStatus(moveId); 1757 while (!PackageManager.isMoveStatusFinished(status)) { 1758 SystemClock.sleep(DateUtils.SECOND_IN_MILLIS); 1759 status = mInterface.getMoveStatus(moveId); 1760 } 1761 1762 if (status == PackageManager.MOVE_SUCCEEDED) { 1763 getOutPrintWriter().println("Success"); 1764 return 0; 1765 } else { 1766 getErrPrintWriter().println("Failure [" + status + "]"); 1767 return 1; 1768 } 1769 } 1770 runCompile()1771 private int runCompile() throws RemoteException { 1772 final PrintWriter pw = getOutPrintWriter(); 1773 boolean checkProfiles = SystemProperties.getBoolean("dalvik.vm.usejitprofiles", false); 1774 boolean forceCompilation = false; 1775 boolean allPackages = false; 1776 boolean clearProfileData = false; 1777 String compilerFilter = null; 1778 String compilationReason = null; 1779 String checkProfilesRaw = null; 1780 boolean secondaryDex = false; 1781 String split = null; 1782 boolean compileLayouts = false; 1783 1784 String opt; 1785 while ((opt = getNextOption()) != null) { 1786 switch (opt) { 1787 case "-a": 1788 allPackages = true; 1789 break; 1790 case "-c": 1791 clearProfileData = true; 1792 break; 1793 case "-f": 1794 forceCompilation = true; 1795 break; 1796 case "-m": 1797 compilerFilter = getNextArgRequired(); 1798 break; 1799 case "-r": 1800 compilationReason = getNextArgRequired(); 1801 break; 1802 case "--compile-layouts": 1803 compileLayouts = true; 1804 break; 1805 case "--check-prof": 1806 checkProfilesRaw = getNextArgRequired(); 1807 break; 1808 case "--reset": 1809 forceCompilation = true; 1810 clearProfileData = true; 1811 compilationReason = "install"; 1812 break; 1813 case "--secondary-dex": 1814 secondaryDex = true; 1815 break; 1816 case "--split": 1817 split = getNextArgRequired(); 1818 break; 1819 default: 1820 pw.println("Error: Unknown option: " + opt); 1821 return 1; 1822 } 1823 } 1824 1825 if (checkProfilesRaw != null) { 1826 if ("true".equals(checkProfilesRaw)) { 1827 checkProfiles = true; 1828 } else if ("false".equals(checkProfilesRaw)) { 1829 checkProfiles = false; 1830 } else { 1831 pw.println("Invalid value for \"--check-prof\". Expected \"true\" or \"false\"."); 1832 return 1; 1833 } 1834 } 1835 1836 final boolean compilerFilterGiven = compilerFilter != null; 1837 final boolean compilationReasonGiven = compilationReason != null; 1838 // Make sure exactly one of -m, -r, or --compile-layouts is given. 1839 if ((!compilerFilterGiven && !compilationReasonGiven && !compileLayouts) 1840 || (!compilerFilterGiven && compilationReasonGiven && compileLayouts) 1841 || (compilerFilterGiven && !compilationReasonGiven && compileLayouts) 1842 || (compilerFilterGiven && compilationReasonGiven && !compileLayouts) 1843 || (compilerFilterGiven && compilationReasonGiven && compileLayouts)) { 1844 pw.println("Must specify exactly one of compilation filter (\"-m\"), compilation " + 1845 "reason (\"-r\"), or compile layouts (\"--compile-layouts\")"); 1846 return 1; 1847 } 1848 1849 if (allPackages && split != null) { 1850 pw.println("-a cannot be specified together with --split"); 1851 return 1; 1852 } 1853 1854 if (secondaryDex && split != null) { 1855 pw.println("--secondary-dex cannot be specified together with --split"); 1856 return 1; 1857 } 1858 1859 String targetCompilerFilter = null; 1860 if (compilerFilterGiven) { 1861 if (!DexFile.isValidCompilerFilter(compilerFilter)) { 1862 pw.println("Error: \"" + compilerFilter + 1863 "\" is not a valid compilation filter."); 1864 return 1; 1865 } 1866 targetCompilerFilter = compilerFilter; 1867 } 1868 if (compilationReasonGiven) { 1869 int reason = -1; 1870 for (int i = 0; i < PackageManagerServiceCompilerMapping.REASON_STRINGS.length; i++) { 1871 if (PackageManagerServiceCompilerMapping.REASON_STRINGS[i].equals( 1872 compilationReason)) { 1873 reason = i; 1874 break; 1875 } 1876 } 1877 if (reason == -1) { 1878 pw.println("Error: Unknown compilation reason: " + compilationReason); 1879 return 1; 1880 } 1881 targetCompilerFilter = 1882 PackageManagerServiceCompilerMapping.getCompilerFilterForReason(reason); 1883 } 1884 1885 1886 List<String> packageNames = null; 1887 if (allPackages) { 1888 packageNames = mInterface.getAllPackages(); 1889 } else { 1890 String packageName = getNextArg(); 1891 if (packageName == null) { 1892 pw.println("Error: package name not specified"); 1893 return 1; 1894 } 1895 packageNames = Collections.singletonList(packageName); 1896 } 1897 1898 List<String> failedPackages = new ArrayList<>(); 1899 int index = 0; 1900 for (String packageName : packageNames) { 1901 if (clearProfileData) { 1902 mInterface.clearApplicationProfileData(packageName); 1903 } 1904 1905 if (allPackages) { 1906 pw.println(++index + "/" + packageNames.size() + ": " + packageName); 1907 pw.flush(); 1908 } 1909 1910 boolean result = true; 1911 if (compileLayouts) { 1912 PackageManagerInternal internal = LocalServices.getService( 1913 PackageManagerInternal.class); 1914 result = internal.compileLayouts(packageName); 1915 } else { 1916 result = secondaryDex 1917 ? mInterface.performDexOptSecondary(packageName, 1918 targetCompilerFilter, forceCompilation) 1919 : mInterface.performDexOptMode(packageName, 1920 checkProfiles, targetCompilerFilter, forceCompilation, 1921 true /* bootComplete */, split); 1922 } 1923 if (!result) { 1924 failedPackages.add(packageName); 1925 } 1926 } 1927 1928 if (failedPackages.isEmpty()) { 1929 pw.println("Success"); 1930 return 0; 1931 } else if (failedPackages.size() == 1) { 1932 pw.println("Failure: package " + failedPackages.get(0) + " could not be compiled"); 1933 return 1; 1934 } else { 1935 pw.print("Failure: the following packages could not be compiled: "); 1936 boolean is_first = true; 1937 for (String packageName : failedPackages) { 1938 if (is_first) { 1939 is_first = false; 1940 } else { 1941 pw.print(", "); 1942 } 1943 pw.print(packageName); 1944 } 1945 pw.println(); 1946 return 1; 1947 } 1948 } 1949 runreconcileSecondaryDexFiles()1950 private int runreconcileSecondaryDexFiles() throws RemoteException { 1951 String packageName = getNextArg(); 1952 mInterface.reconcileSecondaryDexFiles(packageName); 1953 return 0; 1954 } 1955 runForceDexOpt()1956 public int runForceDexOpt() throws RemoteException { 1957 mInterface.forceDexOpt(getNextArgRequired()); 1958 return 0; 1959 } 1960 runDexoptJob()1961 private int runDexoptJob() throws RemoteException { 1962 String arg; 1963 List<String> packageNames = new ArrayList<>(); 1964 while ((arg = getNextArg()) != null) { 1965 packageNames.add(arg); 1966 } 1967 boolean result = BackgroundDexOptService.getService().runBackgroundDexoptJob( 1968 packageNames.isEmpty() ? null : packageNames); 1969 getOutPrintWriter().println(result ? "Success" : "Failure"); 1970 return result ? 0 : -1; 1971 } 1972 cancelBgDexOptJob()1973 private int cancelBgDexOptJob() throws RemoteException { 1974 BackgroundDexOptService.getService().cancelBackgroundDexoptJob(); 1975 getOutPrintWriter().println("Success"); 1976 return 0; 1977 } 1978 runDeleteDexOpt()1979 private int runDeleteDexOpt() throws RemoteException { 1980 PrintWriter pw = getOutPrintWriter(); 1981 String packageName = getNextArg(); 1982 if (TextUtils.isEmpty(packageName)) { 1983 pw.println("Error: no package name"); 1984 return 1; 1985 } 1986 long freedBytes = LocalServices.getService( 1987 PackageManagerInternal.class).deleteOatArtifactsOfPackage(packageName); 1988 if (freedBytes < 0) { 1989 pw.println("Error: delete failed"); 1990 return 1; 1991 } 1992 pw.println("Success: freed " + freedBytes + " bytes"); 1993 Slog.i(TAG, "delete-dexopt " + packageName + " ,freed " + freedBytes + " bytes"); 1994 return 0; 1995 } 1996 runDumpProfiles()1997 private int runDumpProfiles() throws RemoteException { 1998 final PrintWriter pw = getOutPrintWriter(); 1999 boolean dumpClassesAndMethods = false; 2000 2001 String opt; 2002 while ((opt = getNextOption()) != null) { 2003 switch (opt) { 2004 case "--dump-classes-and-methods": 2005 dumpClassesAndMethods = true; 2006 break; 2007 default: 2008 pw.println("Error: Unknown option: " + opt); 2009 return 1; 2010 } 2011 } 2012 2013 String packageName = getNextArg(); 2014 mInterface.dumpProfiles(packageName, dumpClassesAndMethods); 2015 return 0; 2016 } 2017 runSnapshotProfile()2018 private int runSnapshotProfile() throws RemoteException { 2019 PrintWriter pw = getOutPrintWriter(); 2020 2021 // Parse the arguments 2022 final String packageName = getNextArg(); 2023 final boolean isBootImage = "android".equals(packageName); 2024 2025 String codePath = null; 2026 String opt; 2027 while ((opt = getNextArg()) != null) { 2028 switch (opt) { 2029 case "--code-path": 2030 if (isBootImage) { 2031 pw.write("--code-path cannot be used for the boot image."); 2032 return -1; 2033 } 2034 codePath = getNextArg(); 2035 break; 2036 default: 2037 pw.write("Unknown arg: " + opt); 2038 return -1; 2039 } 2040 } 2041 2042 // If no code path was explicitly requested, select the base code path. 2043 String baseCodePath = null; 2044 if (!isBootImage) { 2045 PackageInfo packageInfo = mInterface.getPackageInfo(packageName, /* flags */ 0, 2046 /* userId */0); 2047 if (packageInfo == null) { 2048 pw.write("Package not found " + packageName); 2049 return -1; 2050 } 2051 baseCodePath = packageInfo.applicationInfo.getBaseCodePath(); 2052 if (codePath == null) { 2053 codePath = baseCodePath; 2054 } 2055 } 2056 2057 // Create the profile snapshot. 2058 final SnapshotRuntimeProfileCallback callback = new SnapshotRuntimeProfileCallback(); 2059 // The calling package is needed to debug permission access. 2060 final String callingPackage = (Binder.getCallingUid() == Process.ROOT_UID) 2061 ? "root" : "com.android.shell"; 2062 final int profileType = isBootImage 2063 ? ArtManager.PROFILE_BOOT_IMAGE : ArtManager.PROFILE_APPS; 2064 if (!mInterface.getArtManager().isRuntimeProfilingEnabled(profileType, callingPackage)) { 2065 pw.println("Error: Runtime profiling is not enabled"); 2066 return -1; 2067 } 2068 mInterface.getArtManager().snapshotRuntimeProfile(profileType, packageName, 2069 codePath, callback, callingPackage); 2070 if (!callback.waitTillDone()) { 2071 pw.println("Error: callback not called"); 2072 return callback.mErrCode; 2073 } 2074 2075 // Copy the snapshot profile to the output profile file. 2076 try (InputStream inStream = new AutoCloseInputStream(callback.mProfileReadFd)) { 2077 final String outputFileSuffix = isBootImage || Objects.equals(baseCodePath, codePath) 2078 ? "" : ("-" + new File(codePath).getName()); 2079 final String outputProfilePath = 2080 ART_PROFILE_SNAPSHOT_DEBUG_LOCATION + packageName + outputFileSuffix + ".prof"; 2081 try (OutputStream outStream = new FileOutputStream(outputProfilePath)) { 2082 Streams.copy(inStream, outStream); 2083 } 2084 // Give read permissions to the other group. 2085 Os.chmod(outputProfilePath, /*mode*/ 0644 ); 2086 } catch (IOException | ErrnoException e) { 2087 pw.println("Error when reading the profile fd: " + e.getMessage()); 2088 e.printStackTrace(pw); 2089 return -1; 2090 } 2091 return 0; 2092 } 2093 getRemainingArgs()2094 private ArrayList<String> getRemainingArgs() { 2095 ArrayList<String> args = new ArrayList<>(); 2096 String arg; 2097 while ((arg = getNextArg()) != null) { 2098 args.add(arg); 2099 } 2100 return args; 2101 } 2102 2103 private static class SnapshotRuntimeProfileCallback 2104 extends ISnapshotRuntimeProfileCallback.Stub { 2105 private boolean mSuccess = false; 2106 private int mErrCode = -1; 2107 private ParcelFileDescriptor mProfileReadFd = null; 2108 private CountDownLatch mDoneSignal = new CountDownLatch(1); 2109 2110 @Override onSuccess(ParcelFileDescriptor profileReadFd)2111 public void onSuccess(ParcelFileDescriptor profileReadFd) { 2112 mSuccess = true; 2113 try { 2114 // We need to dup the descriptor. We are in the same process as system server 2115 // and we will be receiving the same object (which will be closed on the 2116 // server side). 2117 mProfileReadFd = profileReadFd.dup(); 2118 } catch (IOException e) { 2119 e.printStackTrace(); 2120 } 2121 mDoneSignal.countDown(); 2122 } 2123 2124 @Override onError(int errCode)2125 public void onError(int errCode) { 2126 mSuccess = false; 2127 mErrCode = errCode; 2128 mDoneSignal.countDown(); 2129 } 2130 waitTillDone()2131 boolean waitTillDone() { 2132 boolean done = false; 2133 try { 2134 // The time-out is an arbitrary large value. Since this is a local call the result 2135 // will come very fast. 2136 done = mDoneSignal.await(10000000, TimeUnit.MILLISECONDS); 2137 } catch (InterruptedException ignored) { 2138 } 2139 return done && mSuccess; 2140 } 2141 } 2142 runUninstall()2143 private int runUninstall() throws RemoteException { 2144 final PrintWriter pw = getOutPrintWriter(); 2145 int flags = 0; 2146 int userId = UserHandle.USER_ALL; 2147 long versionCode = PackageManager.VERSION_CODE_HIGHEST; 2148 2149 String opt; 2150 while ((opt = getNextOption()) != null) { 2151 switch (opt) { 2152 case "-k": 2153 flags |= PackageManager.DELETE_KEEP_DATA; 2154 break; 2155 case "--user": 2156 userId = UserHandle.parseUserArg(getNextArgRequired()); 2157 break; 2158 case "--versionCode": 2159 versionCode = Long.parseLong(getNextArgRequired()); 2160 break; 2161 default: 2162 pw.println("Error: Unknown option: " + opt); 2163 return 1; 2164 } 2165 } 2166 2167 final String packageName = getNextArg(); 2168 if (packageName == null) { 2169 pw.println("Error: package name not specified"); 2170 return 1; 2171 } 2172 2173 // if a split is specified, just remove it and not the whole package 2174 ArrayList<String> splitNames = getRemainingArgs(); 2175 if (!splitNames.isEmpty()) { 2176 return runRemoveSplits(packageName, splitNames); 2177 } 2178 2179 if (userId == UserHandle.USER_ALL) { 2180 flags |= PackageManager.DELETE_ALL_USERS; 2181 } 2182 final int translatedUserId = 2183 translateUserId(userId, UserHandle.USER_SYSTEM, "runUninstall"); 2184 final LocalIntentReceiver receiver = new LocalIntentReceiver(); 2185 final PackageManagerInternal internal = 2186 LocalServices.getService(PackageManagerInternal.class); 2187 2188 if (internal.isApexPackage(packageName)) { 2189 internal.uninstallApex( 2190 packageName, versionCode, translatedUserId, receiver.getIntentSender(), flags); 2191 } else { 2192 if ((flags & PackageManager.DELETE_ALL_USERS) == 0) { 2193 final PackageInfo info = mInterface.getPackageInfo(packageName, 2194 PackageManager.MATCH_STATIC_SHARED_AND_SDK_LIBRARIES, translatedUserId); 2195 if (info == null) { 2196 pw.println("Failure [not installed for " + translatedUserId + "]"); 2197 return 1; 2198 } 2199 final boolean isSystem = 2200 (info.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0; 2201 // If we are being asked to delete a system app for just one 2202 // user set flag so it disables rather than reverting to system 2203 // version of the app. 2204 if (isSystem) { 2205 flags |= PackageManager.DELETE_SYSTEM_APP; 2206 } 2207 } 2208 mInterface.getPackageInstaller().uninstall(new VersionedPackage(packageName, 2209 versionCode), null /*callerPackageName*/, flags, 2210 receiver.getIntentSender(), translatedUserId); 2211 } 2212 2213 final Intent result = receiver.getResult(); 2214 final int status = result.getIntExtra(PackageInstaller.EXTRA_STATUS, 2215 PackageInstaller.STATUS_FAILURE); 2216 if (status == PackageInstaller.STATUS_SUCCESS) { 2217 pw.println("Success"); 2218 return 0; 2219 } else { 2220 pw.println("Failure [" 2221 + result.getStringExtra(PackageInstaller.EXTRA_STATUS_MESSAGE) + "]"); 2222 return 1; 2223 } 2224 } 2225 runRemoveSplits(String packageName, Collection<String> splitNames)2226 private int runRemoveSplits(String packageName, Collection<String> splitNames) 2227 throws RemoteException { 2228 final PrintWriter pw = getOutPrintWriter(); 2229 final SessionParams sessionParams = new SessionParams(SessionParams.MODE_INHERIT_EXISTING); 2230 sessionParams.installFlags |= PackageManager.INSTALL_REPLACE_EXISTING; 2231 sessionParams.appPackageName = packageName; 2232 final int sessionId = 2233 doCreateSession(sessionParams, null /*installerPackageName*/, UserHandle.USER_ALL); 2234 boolean abandonSession = true; 2235 try { 2236 if (doRemoveSplits(sessionId, splitNames, false /*logSuccess*/) 2237 != PackageInstaller.STATUS_SUCCESS) { 2238 return 1; 2239 } 2240 if (doCommitSession(sessionId, false /*logSuccess*/) 2241 != PackageInstaller.STATUS_SUCCESS) { 2242 return 1; 2243 } 2244 abandonSession = false; 2245 pw.println("Success"); 2246 return 0; 2247 } finally { 2248 if (abandonSession) { 2249 try { 2250 doAbandonSession(sessionId, false /*logSuccess*/); 2251 } catch (Exception ignore) { 2252 } 2253 } 2254 } 2255 } 2256 2257 static class ClearDataObserver extends IPackageDataObserver.Stub { 2258 boolean finished; 2259 boolean result; 2260 2261 @Override onRemoveCompleted(String packageName, boolean succeeded)2262 public void onRemoveCompleted(String packageName, boolean succeeded) throws RemoteException { 2263 synchronized (this) { 2264 finished = true; 2265 result = succeeded; 2266 notifyAll(); 2267 } 2268 } 2269 } 2270 runClear()2271 private int runClear() throws RemoteException { 2272 final PrintWriter pw = getOutPrintWriter(); 2273 int userId = UserHandle.USER_SYSTEM; 2274 boolean cacheOnly = false; 2275 2276 String opt; 2277 while ((opt = getNextOption()) != null) { 2278 switch (opt) { 2279 case "--user": 2280 userId = UserHandle.parseUserArg(getNextArgRequired()); 2281 break; 2282 case "--cache-only": 2283 cacheOnly = true; 2284 break; 2285 default: 2286 pw.println("Error: Unknown option: " + opt); 2287 return 1; 2288 } 2289 } 2290 2291 String pkg = getNextArg(); 2292 if (pkg == null) { 2293 getErrPrintWriter().println("Error: no package specified"); 2294 return 1; 2295 } 2296 2297 final int translatedUserId = 2298 translateUserId(userId, UserHandle.USER_NULL, "runClear"); 2299 final ClearDataObserver obs = new ClearDataObserver(); 2300 if (!cacheOnly) { 2301 ActivityManager.getService() 2302 .clearApplicationUserData(pkg, false, obs, translatedUserId); 2303 } else { 2304 mInterface.deleteApplicationCacheFilesAsUser(pkg, translatedUserId, obs); 2305 } 2306 synchronized (obs) { 2307 while (!obs.finished) { 2308 try { 2309 obs.wait(); 2310 } catch (InterruptedException e) { 2311 } 2312 } 2313 } 2314 2315 if (obs.result) { 2316 getOutPrintWriter().println("Success"); 2317 return 0; 2318 } else { 2319 getErrPrintWriter().println("Failed"); 2320 return 1; 2321 } 2322 } 2323 enabledSettingToString(int state)2324 private static String enabledSettingToString(int state) { 2325 switch (state) { 2326 case PackageManager.COMPONENT_ENABLED_STATE_DEFAULT: 2327 return "default"; 2328 case PackageManager.COMPONENT_ENABLED_STATE_ENABLED: 2329 return "enabled"; 2330 case PackageManager.COMPONENT_ENABLED_STATE_DISABLED: 2331 return "disabled"; 2332 case PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER: 2333 return "disabled-user"; 2334 case PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED: 2335 return "disabled-until-used"; 2336 } 2337 return "unknown"; 2338 } 2339 runSetEnabledSetting(int state)2340 private int runSetEnabledSetting(int state) throws RemoteException { 2341 int userId = UserHandle.USER_SYSTEM; 2342 String option = getNextOption(); 2343 if (option != null && option.equals("--user")) { 2344 userId = UserHandle.parseUserArg(getNextArgRequired()); 2345 } 2346 2347 final String pkg = getNextArg(); 2348 if (pkg == null) { 2349 getErrPrintWriter().println("Error: no package or component specified"); 2350 return 1; 2351 } 2352 final int translatedUserId = 2353 translateUserId(userId, UserHandle.USER_NULL, "runSetEnabledSetting"); 2354 final ComponentName cn = ComponentName.unflattenFromString(pkg); 2355 if (cn == null) { 2356 mInterface.setApplicationEnabledSetting(pkg, state, 0, translatedUserId, 2357 "shell:" + android.os.Process.myUid()); 2358 getOutPrintWriter().println("Package " + pkg + " new state: " 2359 + enabledSettingToString( 2360 mInterface.getApplicationEnabledSetting(pkg, translatedUserId))); 2361 return 0; 2362 } else { 2363 mInterface.setComponentEnabledSetting(cn, state, 0, translatedUserId); 2364 getOutPrintWriter().println("Component " + cn.toShortString() + " new state: " 2365 + enabledSettingToString( 2366 mInterface.getComponentEnabledSetting(cn, translatedUserId))); 2367 return 0; 2368 } 2369 } 2370 runSetHiddenSetting(boolean state)2371 private int runSetHiddenSetting(boolean state) throws RemoteException { 2372 int userId = UserHandle.USER_SYSTEM; 2373 String option = getNextOption(); 2374 if (option != null && option.equals("--user")) { 2375 userId = UserHandle.parseUserArg(getNextArgRequired()); 2376 } 2377 2378 String pkg = getNextArg(); 2379 if (pkg == null) { 2380 getErrPrintWriter().println("Error: no package or component specified"); 2381 return 1; 2382 } 2383 final int translatedUserId = 2384 translateUserId(userId, UserHandle.USER_NULL, "runSetHiddenSetting"); 2385 mInterface.setApplicationHiddenSettingAsUser(pkg, state, translatedUserId); 2386 getOutPrintWriter().println("Package " + pkg + " new hidden state: " 2387 + mInterface.getApplicationHiddenSettingAsUser(pkg, translatedUserId)); 2388 return 0; 2389 } 2390 runSetDistractingRestriction()2391 private int runSetDistractingRestriction() { 2392 final PrintWriter pw = getOutPrintWriter(); 2393 int userId = UserHandle.USER_SYSTEM; 2394 String opt; 2395 int flags = 0; 2396 while ((opt = getNextOption()) != null) { 2397 switch (opt) { 2398 case "--user": 2399 userId = UserHandle.parseUserArg(getNextArgRequired()); 2400 break; 2401 case "--flag": 2402 final String flag = getNextArgRequired(); 2403 switch (flag) { 2404 case "hide-notifications": 2405 flags |= PackageManager.RESTRICTION_HIDE_NOTIFICATIONS; 2406 break; 2407 case "hide-from-suggestions": 2408 flags |= PackageManager.RESTRICTION_HIDE_FROM_SUGGESTIONS; 2409 break; 2410 default: 2411 pw.println("Unrecognized flag: " + flag); 2412 return 1; 2413 } 2414 break; 2415 default: 2416 pw.println("Error: Unknown option: " + opt); 2417 return 1; 2418 } 2419 } 2420 2421 final List<String> packageNames = getRemainingArgs(); 2422 if (packageNames.isEmpty()) { 2423 pw.println("Error: package name not specified"); 2424 return 1; 2425 } 2426 try { 2427 final int translatedUserId = translateUserId(userId, UserHandle.USER_NULL, 2428 "set-distracting"); 2429 final String[] errored = mInterface.setDistractingPackageRestrictionsAsUser( 2430 packageNames.toArray(new String[]{}), flags, translatedUserId); 2431 if (errored.length > 0) { 2432 pw.println("Could not set restriction for: " + Arrays.toString(errored)); 2433 return 1; 2434 } 2435 return 0; 2436 } catch (RemoteException | IllegalArgumentException e) { 2437 pw.println(e.toString()); 2438 return 1; 2439 } 2440 } 2441 runSuspend(boolean suspendedState)2442 private int runSuspend(boolean suspendedState) { 2443 final PrintWriter pw = getOutPrintWriter(); 2444 int userId = UserHandle.USER_SYSTEM; 2445 String dialogMessage = null; 2446 final PersistableBundle appExtras = new PersistableBundle(); 2447 final PersistableBundle launcherExtras = new PersistableBundle(); 2448 String opt; 2449 while ((opt = getNextOption()) != null) { 2450 switch (opt) { 2451 case "--user": 2452 userId = UserHandle.parseUserArg(getNextArgRequired()); 2453 break; 2454 case "--dialogMessage": 2455 dialogMessage = getNextArgRequired(); 2456 break; 2457 case "--ael": 2458 case "--aes": 2459 case "--aed": 2460 case "--lel": 2461 case "--les": 2462 case "--led": 2463 final String key = getNextArgRequired(); 2464 final String val = getNextArgRequired(); 2465 if (!suspendedState) { 2466 break; 2467 } 2468 final PersistableBundle bundleToInsert = 2469 opt.startsWith("--a") ? appExtras : launcherExtras; 2470 switch (opt.charAt(4)) { 2471 case 'l': 2472 bundleToInsert.putLong(key, Long.valueOf(val)); 2473 break; 2474 case 'd': 2475 bundleToInsert.putDouble(key, Double.valueOf(val)); 2476 break; 2477 case 's': 2478 bundleToInsert.putString(key, val); 2479 break; 2480 } 2481 break; 2482 default: 2483 pw.println("Error: Unknown option: " + opt); 2484 return 1; 2485 } 2486 } 2487 2488 final List<String> packageNames = getRemainingArgs(); 2489 if (packageNames.isEmpty()) { 2490 pw.println("Error: package name not specified"); 2491 return 1; 2492 } 2493 final String callingPackage = 2494 (Binder.getCallingUid() == Process.ROOT_UID) ? "root" : "com.android.shell"; 2495 2496 final SuspendDialogInfo info; 2497 if (!TextUtils.isEmpty(dialogMessage)) { 2498 info = new SuspendDialogInfo.Builder() 2499 .setMessage(dialogMessage) 2500 .build(); 2501 } else { 2502 info = null; 2503 } 2504 try { 2505 final int translatedUserId = 2506 translateUserId(userId, UserHandle.USER_NULL, "runSuspend"); 2507 mInterface.setPackagesSuspendedAsUser(packageNames.toArray(new String[] {}), 2508 suspendedState, ((appExtras.size() > 0) ? appExtras : null), 2509 ((launcherExtras.size() > 0) ? launcherExtras : null), 2510 info, callingPackage, translatedUserId); 2511 for (int i = 0; i < packageNames.size(); i++) { 2512 final String packageName = packageNames.get(i); 2513 pw.println("Package " + packageName + " new suspended state: " 2514 + mInterface.isPackageSuspendedForUser(packageName, translatedUserId)); 2515 } 2516 return 0; 2517 } catch (RemoteException | IllegalArgumentException e) { 2518 pw.println(e.toString()); 2519 return 1; 2520 } 2521 } 2522 runGrantRevokePermission(boolean grant)2523 private int runGrantRevokePermission(boolean grant) throws RemoteException { 2524 int userId = UserHandle.USER_SYSTEM; 2525 2526 String opt = null; 2527 while ((opt = getNextOption()) != null) { 2528 if (opt.equals("--user")) { 2529 userId = UserHandle.parseUserArg(getNextArgRequired()); 2530 } 2531 } 2532 2533 String pkg = getNextArg(); 2534 if (pkg == null) { 2535 getErrPrintWriter().println("Error: no package specified"); 2536 return 1; 2537 } 2538 String perm = getNextArg(); 2539 if (perm == null) { 2540 getErrPrintWriter().println("Error: no permission specified"); 2541 return 1; 2542 } 2543 final UserHandle translatedUser = UserHandle.of(translateUserId(userId, 2544 UserHandle.USER_NULL, "runGrantRevokePermission")); 2545 if (grant) { 2546 mPermissionManager.grantRuntimePermission(pkg, perm, translatedUser); 2547 } else { 2548 mPermissionManager.revokeRuntimePermission(pkg, perm, translatedUser, null); 2549 } 2550 return 0; 2551 } 2552 runResetPermissions()2553 private int runResetPermissions() throws RemoteException { 2554 mLegacyPermissionManager.resetRuntimePermissions(); 2555 return 0; 2556 } 2557 setOrClearPermissionFlags(boolean setFlags)2558 private int setOrClearPermissionFlags(boolean setFlags) { 2559 int userId = UserHandle.USER_SYSTEM; 2560 2561 String opt; 2562 while ((opt = getNextOption()) != null) { 2563 if (opt.equals("--user")) { 2564 userId = UserHandle.parseUserArg(getNextArgRequired()); 2565 } 2566 } 2567 2568 String pkg = getNextArg(); 2569 if (pkg == null) { 2570 getErrPrintWriter().println("Error: no package specified"); 2571 return 1; 2572 } 2573 String perm = getNextArg(); 2574 if (perm == null) { 2575 getErrPrintWriter().println("Error: no permission specified"); 2576 return 1; 2577 } 2578 2579 int flagMask = 0; 2580 String flagName = getNextArg(); 2581 if (flagName == null) { 2582 getErrPrintWriter().println("Error: no permission flags specified"); 2583 return 1; 2584 } 2585 while (flagName != null) { 2586 if (!SUPPORTED_PERMISSION_FLAGS.containsKey(flagName)) { 2587 getErrPrintWriter().println("Error: specified flag " + flagName + " is not one of " 2588 + SUPPORTED_PERMISSION_FLAGS_LIST); 2589 return 1; 2590 } 2591 flagMask |= SUPPORTED_PERMISSION_FLAGS.get(flagName); 2592 flagName = getNextArg(); 2593 } 2594 2595 final UserHandle translatedUser = UserHandle.of(translateUserId(userId, 2596 UserHandle.USER_NULL, "runGrantRevokePermission")); 2597 int flagSet = setFlags ? flagMask : 0; 2598 mPermissionManager.updatePermissionFlags(pkg, perm, flagMask, flagSet, translatedUser); 2599 return 0; 2600 } 2601 runSetPermissionEnforced()2602 private int runSetPermissionEnforced() throws RemoteException { 2603 final String permission = getNextArg(); 2604 if (permission == null) { 2605 getErrPrintWriter().println("Error: no permission specified"); 2606 return 1; 2607 } 2608 final String enforcedRaw = getNextArg(); 2609 if (enforcedRaw == null) { 2610 getErrPrintWriter().println("Error: no enforcement specified"); 2611 return 1; 2612 } 2613 // Permissions are always enforced now. 2614 return 0; 2615 } 2616 isVendorApp(String pkg)2617 private boolean isVendorApp(String pkg) { 2618 try { 2619 final PackageInfo info = mInterface.getPackageInfo( 2620 pkg, PackageManager.MATCH_ANY_USER, UserHandle.USER_SYSTEM); 2621 return info != null && info.applicationInfo.isVendor(); 2622 } catch (RemoteException e) { 2623 return false; 2624 } 2625 } 2626 isProductApp(String pkg)2627 private boolean isProductApp(String pkg) { 2628 try { 2629 final PackageInfo info = mInterface.getPackageInfo( 2630 pkg, PackageManager.MATCH_ANY_USER, UserHandle.USER_SYSTEM); 2631 return info != null && info.applicationInfo.isProduct(); 2632 } catch (RemoteException e) { 2633 return false; 2634 } 2635 } 2636 isSystemExtApp(String pkg)2637 private boolean isSystemExtApp(String pkg) { 2638 try { 2639 final PackageInfo info = mInterface.getPackageInfo( 2640 pkg, PackageManager.MATCH_ANY_USER, UserHandle.USER_SYSTEM); 2641 return info != null && info.applicationInfo.isSystemExt(); 2642 } catch (RemoteException e) { 2643 return false; 2644 } 2645 } 2646 getApexPackageNameContainingPackage(String pkg)2647 private String getApexPackageNameContainingPackage(String pkg) { 2648 ApexManager apexManager = ApexManager.getInstance(); 2649 return apexManager.getActiveApexPackageNameContainingPackage(pkg); 2650 } 2651 isApexApp(String pkg)2652 private boolean isApexApp(String pkg) { 2653 return getApexPackageNameContainingPackage(pkg) != null; 2654 } 2655 runGetPrivappPermissions()2656 private int runGetPrivappPermissions() { 2657 final String pkg = getNextArg(); 2658 if (pkg == null) { 2659 getErrPrintWriter().println("Error: no package specified."); 2660 return 1; 2661 } 2662 2663 ArraySet<String> privAppPermissions = null; 2664 if (isVendorApp(pkg)) { 2665 privAppPermissions = SystemConfig.getInstance().getVendorPrivAppPermissions(pkg); 2666 } else if (isProductApp(pkg)) { 2667 privAppPermissions = SystemConfig.getInstance().getProductPrivAppPermissions(pkg); 2668 } else if (isSystemExtApp(pkg)) { 2669 privAppPermissions = SystemConfig.getInstance() 2670 .getSystemExtPrivAppPermissions(pkg); 2671 } else if (isApexApp(pkg)) { 2672 final String apexName = ApexManager.getInstance().getApexModuleNameForPackageName( 2673 getApexPackageNameContainingPackage(pkg)); 2674 privAppPermissions = SystemConfig.getInstance() 2675 .getApexPrivAppPermissions(apexName, pkg); 2676 } else { 2677 privAppPermissions = SystemConfig.getInstance().getPrivAppPermissions(pkg); 2678 } 2679 2680 getOutPrintWriter().println(privAppPermissions == null 2681 ? "{}" : privAppPermissions.toString()); 2682 return 0; 2683 } 2684 runGetPrivappDenyPermissions()2685 private int runGetPrivappDenyPermissions() { 2686 final String pkg = getNextArg(); 2687 if (pkg == null) { 2688 getErrPrintWriter().println("Error: no package specified."); 2689 return 1; 2690 } 2691 2692 ArraySet<String> privAppPermissions = null; 2693 if (isVendorApp(pkg)) { 2694 privAppPermissions = SystemConfig.getInstance().getVendorPrivAppDenyPermissions(pkg); 2695 } else if (isProductApp(pkg)) { 2696 privAppPermissions = SystemConfig.getInstance().getProductPrivAppDenyPermissions(pkg); 2697 } else if (isSystemExtApp(pkg)) { 2698 privAppPermissions = SystemConfig.getInstance() 2699 .getSystemExtPrivAppDenyPermissions(pkg); 2700 } else if (isApexApp(pkg)) { 2701 final String apexName = ApexManager.getInstance().getApexModuleNameForPackageName( 2702 getApexPackageNameContainingPackage(pkg)); 2703 privAppPermissions = SystemConfig.getInstance() 2704 .getApexPrivAppDenyPermissions(apexName, pkg); 2705 } else { 2706 privAppPermissions = SystemConfig.getInstance().getPrivAppDenyPermissions(pkg); 2707 } 2708 2709 getOutPrintWriter().println(privAppPermissions == null 2710 ? "{}" : privAppPermissions.toString()); 2711 return 0; 2712 } 2713 runGetOemPermissions()2714 private int runGetOemPermissions() { 2715 final String pkg = getNextArg(); 2716 if (pkg == null) { 2717 getErrPrintWriter().println("Error: no package specified."); 2718 return 1; 2719 } 2720 final Map<String, Boolean> oemPermissions = SystemConfig.getInstance() 2721 .getOemPermissions(pkg); 2722 if (oemPermissions == null || oemPermissions.isEmpty()) { 2723 getOutPrintWriter().println("{}"); 2724 } else { 2725 oemPermissions.forEach((permission, granted) -> 2726 getOutPrintWriter().println(permission + " granted:" + granted) 2727 ); 2728 } 2729 return 0; 2730 } 2731 runTrimCaches()2732 private int runTrimCaches() throws RemoteException { 2733 String size = getNextArg(); 2734 if (size == null) { 2735 getErrPrintWriter().println("Error: no size specified"); 2736 return 1; 2737 } 2738 long multiplier = 1; 2739 int len = size.length(); 2740 char c = size.charAt(len - 1); 2741 if (c < '0' || c > '9') { 2742 if (c == 'K' || c == 'k') { 2743 multiplier = 1024L; 2744 } else if (c == 'M' || c == 'm') { 2745 multiplier = 1024L*1024L; 2746 } else if (c == 'G' || c == 'g') { 2747 multiplier = 1024L*1024L*1024L; 2748 } else { 2749 getErrPrintWriter().println("Invalid suffix: " + c); 2750 return 1; 2751 } 2752 size = size.substring(0, len-1); 2753 } 2754 long sizeVal; 2755 try { 2756 sizeVal = Long.parseLong(size) * multiplier; 2757 } catch (NumberFormatException e) { 2758 getErrPrintWriter().println("Error: expected number at: " + size); 2759 return 1; 2760 } 2761 String volumeUuid = getNextArg(); 2762 if ("internal".equals(volumeUuid)) { 2763 volumeUuid = null; 2764 } 2765 ClearDataObserver obs = new ClearDataObserver(); 2766 mInterface.freeStorageAndNotify(volumeUuid, sizeVal, 2767 StorageManager.FLAG_ALLOCATE_DEFY_ALL_RESERVED, obs); 2768 synchronized (obs) { 2769 while (!obs.finished) { 2770 try { 2771 obs.wait(); 2772 } catch (InterruptedException e) { 2773 } 2774 } 2775 } 2776 return 0; 2777 } 2778 isNumber(String s)2779 private static boolean isNumber(String s) { 2780 try { 2781 Integer.parseInt(s); 2782 } catch (NumberFormatException nfe) { 2783 return false; 2784 } 2785 return true; 2786 } 2787 runCreateUser()2788 public int runCreateUser() throws RemoteException { 2789 String name; 2790 int userId = -1; 2791 int flags = 0; 2792 String userType = null; 2793 String opt; 2794 boolean preCreateOnly = false; 2795 while ((opt = getNextOption()) != null) { 2796 String newUserType = null; 2797 if ("--profileOf".equals(opt)) { 2798 userId = translateUserId(UserHandle.parseUserArg(getNextArgRequired()), 2799 UserHandle.USER_ALL, "runCreateUser"); 2800 } else if ("--managed".equals(opt)) { 2801 newUserType = UserManager.USER_TYPE_PROFILE_MANAGED; 2802 } else if ("--restricted".equals(opt)) { 2803 newUserType = UserManager.USER_TYPE_FULL_RESTRICTED; 2804 } else if ("--guest".equals(opt)) { 2805 newUserType = UserManager.USER_TYPE_FULL_GUEST; 2806 } else if ("--demo".equals(opt)) { 2807 newUserType = UserManager.USER_TYPE_FULL_DEMO; 2808 } else if ("--ephemeral".equals(opt)) { 2809 flags |= UserInfo.FLAG_EPHEMERAL; 2810 } else if ("--pre-create-only".equals(opt)) { 2811 preCreateOnly = true; 2812 } else if ("--user-type".equals(opt)) { 2813 newUserType = getNextArgRequired(); 2814 } else { 2815 getErrPrintWriter().println("Error: unknown option " + opt); 2816 return 1; 2817 } 2818 // Ensure only one user-type was specified. 2819 if (newUserType != null) { 2820 if (userType != null && !userType.equals(newUserType)) { 2821 getErrPrintWriter().println("Error: more than one user type was specified (" 2822 + userType + " and " + newUserType + ")"); 2823 return 1; 2824 } 2825 userType = newUserType; 2826 } 2827 } 2828 String arg = getNextArg(); 2829 if (arg == null && !preCreateOnly) { 2830 getErrPrintWriter().println("Error: no user name specified."); 2831 return 1; 2832 } 2833 if (arg != null && preCreateOnly) { 2834 getErrPrintWriter().println("Warning: name is ignored for pre-created users"); 2835 } 2836 2837 name = arg; 2838 UserInfo info = null; 2839 IUserManager um = IUserManager.Stub.asInterface( 2840 ServiceManager.getService(Context.USER_SERVICE)); 2841 IAccountManager accm = IAccountManager.Stub.asInterface( 2842 ServiceManager.getService(Context.ACCOUNT_SERVICE)); 2843 if (userType == null) { 2844 userType = UserInfo.getDefaultUserType(flags); 2845 } 2846 Trace.traceBegin(Trace.TRACE_TAG_PACKAGE_MANAGER, "shell_runCreateUser"); 2847 try { 2848 if (UserManager.isUserTypeRestricted(userType)) { 2849 // In non-split user mode, userId can only be SYSTEM 2850 int parentUserId = userId >= 0 ? userId : UserHandle.USER_SYSTEM; 2851 info = um.createRestrictedProfileWithThrow(name, parentUserId); 2852 accm.addSharedAccountsFromParentUser(parentUserId, userId, 2853 (Process.myUid() == Process.ROOT_UID) ? "root" : "com.android.shell"); 2854 } else if (userId < 0) { 2855 info = preCreateOnly ? 2856 um.preCreateUserWithThrow(userType) : 2857 um.createUserWithThrow(name, userType, flags); 2858 } else { 2859 info = um.createProfileForUserWithThrow(name, userType, flags, userId, null); 2860 } 2861 } catch (ServiceSpecificException e) { 2862 getErrPrintWriter().println("Error: " + e); 2863 } finally { 2864 Trace.traceEnd(Trace.TRACE_TAG_PACKAGE_MANAGER); 2865 } 2866 2867 if (info != null) { 2868 getOutPrintWriter().println("Success: created user id " + info.id); 2869 return 0; 2870 } else { 2871 getErrPrintWriter().println("Error: couldn't create User."); 2872 return 1; 2873 } 2874 } 2875 2876 // pm remove-user [--set-ephemeral-if-in-use][--wait] USER_ID runRemoveUser()2877 public int runRemoveUser() throws RemoteException { 2878 int userId; 2879 String arg; 2880 boolean setEphemeralIfInUse = false; 2881 boolean wait = false; 2882 2883 while ((arg = getNextOption()) != null) { 2884 switch (arg) { 2885 case "--set-ephemeral-if-in-use": 2886 setEphemeralIfInUse = true; 2887 break; 2888 case "--wait": // fallthrough 2889 case "-w": 2890 wait = true; 2891 break; 2892 default: 2893 getErrPrintWriter().println("Error: unknown option: " + arg); 2894 return -1; 2895 } 2896 } 2897 2898 arg = getNextArg(); 2899 if (arg == null) { 2900 getErrPrintWriter().println("Error: no user id specified."); 2901 return 1; 2902 } 2903 userId = UserHandle.parseUserArg(arg); 2904 IUserManager um = IUserManager.Stub.asInterface( 2905 ServiceManager.getService(Context.USER_SERVICE)); 2906 if (setEphemeralIfInUse) { 2907 return removeUserWhenPossible(um, userId); 2908 } else { 2909 final boolean success = wait ? removeUserAndWait(um, userId) : removeUser(um, userId); 2910 if (success) { 2911 getOutPrintWriter().println("Success: removed user"); 2912 return 0; 2913 } else { 2914 // Error message should already have been printed. 2915 return 1; 2916 } 2917 } 2918 } 2919 removeUser(IUserManager um, @UserIdInt int userId)2920 private boolean removeUser(IUserManager um, @UserIdInt int userId) throws RemoteException { 2921 Slog.i(TAG, "Removing user " + userId); 2922 if (um.removeUser(userId)) { 2923 return true; 2924 } else { 2925 getErrPrintWriter().println("Error: couldn't remove user id " + userId); 2926 return false; 2927 } 2928 } 2929 removeUserAndWait(IUserManager um, @UserIdInt int userId)2930 private boolean removeUserAndWait(IUserManager um, @UserIdInt int userId) 2931 throws RemoteException { 2932 Slog.i(TAG, "Removing (and waiting for completion) user " + userId); 2933 2934 final CountDownLatch waitLatch = new CountDownLatch(1); 2935 final UserManagerInternal.UserLifecycleListener listener = 2936 new UserManagerInternal.UserLifecycleListener() { 2937 @Override 2938 public void onUserRemoved(UserInfo user) { 2939 if (userId == user.id) { 2940 waitLatch.countDown(); 2941 } 2942 } 2943 }; 2944 2945 final UserManagerInternal umi = LocalServices.getService(UserManagerInternal.class); 2946 umi.addUserLifecycleListener(listener); 2947 2948 try { 2949 if (um.removeUser(userId)) { 2950 final boolean awaitSuccess = waitLatch.await(10, TimeUnit.MINUTES); 2951 if (!awaitSuccess) { 2952 getErrPrintWriter().printf("Error: Remove user %d timed out\n", userId); 2953 return false; 2954 } 2955 // Success! 2956 return true; 2957 } else { 2958 getErrPrintWriter().println("Error: couldn't remove user id " + userId); 2959 return false; 2960 } 2961 } catch (InterruptedException e) { 2962 getErrPrintWriter().printf("Error: Remove user %d wait interrupted: %s\n", userId, e); 2963 Thread.currentThread().interrupt(); 2964 return false; 2965 } finally { 2966 umi.removeUserLifecycleListener(listener); 2967 } 2968 } 2969 removeUserWhenPossible(IUserManager um, @UserIdInt int userId)2970 private int removeUserWhenPossible(IUserManager um, @UserIdInt int userId) 2971 throws RemoteException { 2972 Slog.i(TAG, "Removing " + userId + " or set as ephemeral if in use."); 2973 int result = um.removeUserWhenPossible(userId, /* overrideDevicePolicy= */ false); 2974 switch (result) { 2975 case UserManager.REMOVE_RESULT_REMOVED: 2976 getOutPrintWriter().printf("Success: user %d removed\n", userId); 2977 return 0; 2978 case UserManager.REMOVE_RESULT_DEFERRED: 2979 getOutPrintWriter().printf("Success: user %d set as ephemeral\n", userId); 2980 return 0; 2981 case UserManager.REMOVE_RESULT_ALREADY_BEING_REMOVED: 2982 getOutPrintWriter().printf("Success: user %d is already being removed\n", userId); 2983 return 0; 2984 default: 2985 getErrPrintWriter().printf("Error: couldn't remove or mark ephemeral user id %d\n", 2986 userId); 2987 return 1; 2988 } 2989 } 2990 runSetUserRestriction()2991 public int runSetUserRestriction() throws RemoteException { 2992 int userId = UserHandle.USER_SYSTEM; 2993 String opt = getNextOption(); 2994 if (opt != null && "--user".equals(opt)) { 2995 userId = UserHandle.parseUserArg(getNextArgRequired()); 2996 } 2997 2998 String restriction = getNextArg(); 2999 String arg = getNextArg(); 3000 boolean value; 3001 if ("1".equals(arg)) { 3002 value = true; 3003 } else if ("0".equals(arg)) { 3004 value = false; 3005 } else { 3006 getErrPrintWriter().println("Error: valid value not specified"); 3007 return 1; 3008 } 3009 final int translatedUserId = 3010 translateUserId(userId, UserHandle.USER_NULL, "runSetUserRestriction"); 3011 final IUserManager um = IUserManager.Stub.asInterface( 3012 ServiceManager.getService(Context.USER_SERVICE)); 3013 um.setUserRestriction(restriction, value, translatedUserId); 3014 return 0; 3015 } 3016 runGetMaxUsers()3017 public int runGetMaxUsers() { 3018 getOutPrintWriter().println("Maximum supported users: " 3019 + UserManager.getMaxSupportedUsers()); 3020 return 0; 3021 } 3022 runGetMaxRunningUsers()3023 public int runGetMaxRunningUsers() { 3024 ActivityManagerInternal activityManagerInternal = 3025 LocalServices.getService(ActivityManagerInternal.class); 3026 getOutPrintWriter().println("Maximum supported running users: " 3027 + activityManagerInternal.getMaxRunningUsers()); 3028 return 0; 3029 } 3030 3031 private static class InstallParams { 3032 SessionParams sessionParams; 3033 String installerPackageName; 3034 int userId = UserHandle.USER_ALL; 3035 long stagedReadyTimeoutMs = DEFAULT_STAGED_READY_TIMEOUT_MS; 3036 } 3037 makeInstallParams(Set<String> unsupportedOptions)3038 private InstallParams makeInstallParams(Set<String> unsupportedOptions) { 3039 final SessionParams sessionParams = new SessionParams(SessionParams.MODE_FULL_INSTALL); 3040 final InstallParams params = new InstallParams(); 3041 3042 params.sessionParams = sessionParams; 3043 // Allowlist all permissions by default 3044 sessionParams.installFlags |= PackageManager.INSTALL_ALL_WHITELIST_RESTRICTED_PERMISSIONS; 3045 // Set package source to other by default 3046 sessionParams.setPackageSource(PackageInstaller.PACKAGE_SOURCE_OTHER); 3047 3048 String opt; 3049 boolean replaceExisting = true; 3050 boolean forceNonStaged = false; 3051 while ((opt = getNextOption()) != null) { 3052 if (unsupportedOptions.contains(opt)) { 3053 throw new IllegalArgumentException("Unsupported option " + opt); 3054 } 3055 switch (opt) { 3056 case "-r": // ignore 3057 break; 3058 case "-R": 3059 replaceExisting = false; 3060 break; 3061 case "-i": 3062 params.installerPackageName = getNextArg(); 3063 if (params.installerPackageName == null) { 3064 throw new IllegalArgumentException("Missing installer package"); 3065 } 3066 break; 3067 case "-t": 3068 sessionParams.installFlags |= PackageManager.INSTALL_ALLOW_TEST; 3069 break; 3070 case "-f": 3071 sessionParams.installFlags |= PackageManager.INSTALL_INTERNAL; 3072 break; 3073 case "-d": 3074 sessionParams.installFlags |= PackageManager.INSTALL_REQUEST_DOWNGRADE; 3075 break; 3076 case "-g": 3077 sessionParams.installFlags |= PackageManager.INSTALL_GRANT_RUNTIME_PERMISSIONS; 3078 break; 3079 case "--restrict-permissions": 3080 sessionParams.installFlags &= 3081 ~PackageManager.INSTALL_ALL_WHITELIST_RESTRICTED_PERMISSIONS; 3082 break; 3083 case "--dont-kill": 3084 sessionParams.installFlags |= PackageManager.INSTALL_DONT_KILL_APP; 3085 break; 3086 case "--originating-uri": 3087 sessionParams.originatingUri = Uri.parse(getNextArg()); 3088 break; 3089 case "--referrer": 3090 sessionParams.referrerUri = Uri.parse(getNextArg()); 3091 break; 3092 case "-p": 3093 sessionParams.mode = SessionParams.MODE_INHERIT_EXISTING; 3094 sessionParams.appPackageName = getNextArg(); 3095 if (sessionParams.appPackageName == null) { 3096 throw new IllegalArgumentException("Missing inherit package name"); 3097 } 3098 break; 3099 case "--pkg": 3100 sessionParams.appPackageName = getNextArg(); 3101 if (sessionParams.appPackageName == null) { 3102 throw new IllegalArgumentException("Missing package name"); 3103 } 3104 break; 3105 case "-S": 3106 final long sizeBytes = Long.parseLong(getNextArg()); 3107 if (sizeBytes <= 0) { 3108 throw new IllegalArgumentException("Size must be positive"); 3109 } 3110 sessionParams.setSize(sizeBytes); 3111 break; 3112 case "--abi": 3113 sessionParams.abiOverride = checkAbiArgument(getNextArg()); 3114 break; 3115 case "--ephemeral": 3116 case "--instant": 3117 case "--instantapp": 3118 sessionParams.setInstallAsInstantApp(true /*isInstantApp*/); 3119 break; 3120 case "--full": 3121 sessionParams.setInstallAsInstantApp(false /*isInstantApp*/); 3122 break; 3123 case "--preload": 3124 sessionParams.setInstallAsVirtualPreload(); 3125 break; 3126 case "--user": 3127 params.userId = UserHandle.parseUserArg(getNextArgRequired()); 3128 break; 3129 case "--install-location": 3130 sessionParams.installLocation = Integer.parseInt(getNextArg()); 3131 break; 3132 case "--install-reason": 3133 sessionParams.installReason = Integer.parseInt(getNextArg()); 3134 break; 3135 case "--force-uuid": 3136 sessionParams.installFlags |= PackageManager.INSTALL_FORCE_VOLUME_UUID; 3137 sessionParams.volumeUuid = getNextArg(); 3138 if ("internal".equals(sessionParams.volumeUuid)) { 3139 sessionParams.volumeUuid = null; 3140 } 3141 break; 3142 case "--force-sdk": // ignore 3143 break; 3144 case "--apex": 3145 sessionParams.setInstallAsApex(); 3146 sessionParams.setStaged(); 3147 break; 3148 case "--force-non-staged": 3149 forceNonStaged = true; 3150 break; 3151 case "--multi-package": 3152 sessionParams.setMultiPackage(); 3153 break; 3154 case "--staged": 3155 sessionParams.setStaged(); 3156 break; 3157 case "--force-queryable": 3158 sessionParams.setForceQueryable(); 3159 break; 3160 case "--enable-rollback": 3161 if (params.installerPackageName == null) { 3162 // com.android.shell has the TEST_MANAGE_ROLLBACKS 3163 // permission needed to enable rollback for non-module 3164 // packages, which is likely what the user wants when 3165 // enabling rollback through the shell command. Set 3166 // the installer to com.android.shell if no installer 3167 // has been provided so that the user doesn't have to 3168 // remember to set it themselves. 3169 params.installerPackageName = "com.android.shell"; 3170 } 3171 sessionParams.installFlags |= PackageManager.INSTALL_ENABLE_ROLLBACK; 3172 break; 3173 case "--staged-ready-timeout": 3174 params.stagedReadyTimeoutMs = Long.parseLong(getNextArgRequired()); 3175 break; 3176 case "--skip-verification": 3177 sessionParams.installFlags |= PackageManager.INSTALL_DISABLE_VERIFICATION; 3178 break; 3179 default: 3180 throw new IllegalArgumentException("Unknown option " + opt); 3181 } 3182 } 3183 if (replaceExisting) { 3184 sessionParams.installFlags |= PackageManager.INSTALL_REPLACE_EXISTING; 3185 } 3186 if (forceNonStaged) { 3187 sessionParams.isStaged = false; 3188 } 3189 return params; 3190 } 3191 runSetHomeActivity()3192 private int runSetHomeActivity() { 3193 final PrintWriter pw = getOutPrintWriter(); 3194 int userId = UserHandle.USER_SYSTEM; 3195 String opt; 3196 while ((opt = getNextOption()) != null) { 3197 switch (opt) { 3198 case "--user": 3199 userId = UserHandle.parseUserArg(getNextArgRequired()); 3200 break; 3201 default: 3202 pw.println("Error: Unknown option: " + opt); 3203 return 1; 3204 } 3205 } 3206 3207 String pkgName; 3208 String component = getNextArg(); 3209 if (component.indexOf('/') < 0) { 3210 // No component specified, so assume it's just a package name. 3211 pkgName = component; 3212 } else { 3213 ComponentName componentName = 3214 component != null ? ComponentName.unflattenFromString(component) : null; 3215 if (componentName == null) { 3216 pw.println("Error: invalid component name"); 3217 return 1; 3218 } 3219 pkgName = componentName.getPackageName(); 3220 } 3221 final int translatedUserId = 3222 translateUserId(userId, UserHandle.USER_NULL, "runSetHomeActivity"); 3223 final CompletableFuture<Boolean> future = new CompletableFuture<>(); 3224 try { 3225 RoleManager roleManager = mContext.getSystemService(RoleManager.class); 3226 roleManager.addRoleHolderAsUser(RoleManager.ROLE_HOME, pkgName, 0, 3227 UserHandle.of(translatedUserId), FgThread.getExecutor(), future::complete); 3228 boolean success = future.get(); 3229 if (success) { 3230 pw.println("Success"); 3231 return 0; 3232 } else { 3233 pw.println("Error: Failed to set default home."); 3234 return 1; 3235 } 3236 } catch (Exception e) { 3237 pw.println(e.toString()); 3238 return 1; 3239 } 3240 } 3241 runSetInstaller()3242 private int runSetInstaller() throws RemoteException { 3243 final String targetPackage = getNextArg(); 3244 final String installerPackageName = getNextArg(); 3245 3246 if (targetPackage == null || installerPackageName == null) { 3247 getErrPrintWriter().println("Must provide both target and installer package names"); 3248 return 1; 3249 } 3250 3251 mInterface.setInstallerPackageName(targetPackage, installerPackageName); 3252 getOutPrintWriter().println("Success"); 3253 return 0; 3254 } 3255 runGetInstantAppResolver()3256 private int runGetInstantAppResolver() { 3257 final PrintWriter pw = getOutPrintWriter(); 3258 try { 3259 final ComponentName instantAppsResolver = mInterface.getInstantAppResolverComponent(); 3260 if (instantAppsResolver == null) { 3261 return 1; 3262 } 3263 pw.println(instantAppsResolver.flattenToString()); 3264 return 0; 3265 } catch (Exception e) { 3266 pw.println(e.toString()); 3267 return 1; 3268 } 3269 } 3270 runHasFeature()3271 private int runHasFeature() { 3272 final PrintWriter err = getErrPrintWriter(); 3273 final String featureName = getNextArg(); 3274 if (featureName == null) { 3275 err.println("Error: expected FEATURE name"); 3276 return 1; 3277 } 3278 final String versionString = getNextArg(); 3279 try { 3280 final int version = (versionString == null) ? 0 : Integer.parseInt(versionString); 3281 final boolean hasFeature = mInterface.hasSystemFeature(featureName, version); 3282 getOutPrintWriter().println(hasFeature); 3283 return hasFeature ? 0 : 1; 3284 } catch (NumberFormatException e) { 3285 err.println("Error: illegal version number " + versionString); 3286 return 1; 3287 } catch (RemoteException e) { 3288 err.println(e.toString()); 3289 return 1; 3290 } 3291 } 3292 runDump()3293 private int runDump() { 3294 String pkg = getNextArg(); 3295 if (pkg == null) { 3296 getErrPrintWriter().println("Error: no package specified"); 3297 return 1; 3298 } 3299 ActivityManager.dumpPackageStateStatic(getOutFileDescriptor(), pkg); 3300 return 0; 3301 } 3302 runSetHarmfulAppWarning()3303 private int runSetHarmfulAppWarning() throws RemoteException { 3304 int userId = UserHandle.USER_CURRENT; 3305 3306 String opt; 3307 while ((opt = getNextOption()) != null) { 3308 if (opt.equals("--user")) { 3309 userId = UserHandle.parseUserArg(getNextArgRequired()); 3310 } else { 3311 getErrPrintWriter().println("Error: Unknown option: " + opt); 3312 return -1; 3313 } 3314 } 3315 3316 final int translatedUserId = 3317 translateUserId(userId, UserHandle.USER_NULL, "runSetHarmfulAppWarning"); 3318 final String packageName = getNextArgRequired(); 3319 final String warning = getNextArg(); 3320 3321 mInterface.setHarmfulAppWarning(packageName, warning, translatedUserId); 3322 3323 return 0; 3324 } 3325 runGetHarmfulAppWarning()3326 private int runGetHarmfulAppWarning() throws RemoteException { 3327 int userId = UserHandle.USER_CURRENT; 3328 3329 String opt; 3330 while ((opt = getNextOption()) != null) { 3331 if (opt.equals("--user")) { 3332 userId = UserHandle.parseUserArg(getNextArgRequired()); 3333 } else { 3334 getErrPrintWriter().println("Error: Unknown option: " + opt); 3335 return -1; 3336 } 3337 } 3338 3339 final int translatedUserId = 3340 translateUserId(userId, UserHandle.USER_NULL, "runGetHarmfulAppWarning"); 3341 final String packageName = getNextArgRequired(); 3342 final CharSequence warning = mInterface.getHarmfulAppWarning(packageName, translatedUserId); 3343 if (!TextUtils.isEmpty(warning)) { 3344 getOutPrintWriter().println(warning); 3345 return 0; 3346 } else { 3347 return 1; 3348 } 3349 } 3350 runSetSilentUpdatesPolicy()3351 private int runSetSilentUpdatesPolicy() { 3352 final PrintWriter pw = getOutPrintWriter(); 3353 String opt; 3354 String installerPackageName = null; 3355 Long throttleTimeInSeconds = null; 3356 boolean reset = false; 3357 while ((opt = getNextOption()) != null) { 3358 switch (opt) { 3359 case "--allow-unlimited-silent-updates": 3360 installerPackageName = getNextArgRequired(); 3361 break; 3362 case "--throttle-time": 3363 throttleTimeInSeconds = Long.parseLong(getNextArgRequired()); 3364 break; 3365 case "--reset": 3366 reset = true; 3367 break; 3368 default: 3369 pw.println("Error: Unknown option: " + opt); 3370 return -1; 3371 } 3372 } 3373 if (throttleTimeInSeconds != null && throttleTimeInSeconds < 0) { 3374 pw.println("Error: Invalid value for \"--throttle-time\":" + throttleTimeInSeconds); 3375 return -1; 3376 } 3377 3378 try { 3379 final IPackageInstaller installer = mInterface.getPackageInstaller(); 3380 if (reset) { 3381 installer.setAllowUnlimitedSilentUpdates(null /* installerPackageName */); 3382 installer.setSilentUpdatesThrottleTime(-1 /* restore to the default */); 3383 } else { 3384 if (installerPackageName != null) { 3385 installer.setAllowUnlimitedSilentUpdates(installerPackageName); 3386 } 3387 if (throttleTimeInSeconds != null) { 3388 installer.setSilentUpdatesThrottleTime(throttleTimeInSeconds); 3389 } 3390 } 3391 } catch (RemoteException e) { 3392 pw.println("Failure [" 3393 + e.getClass().getName() + " - " 3394 + e.getMessage() + "]"); 3395 return -1; 3396 } 3397 return 1; 3398 } 3399 checkAbiArgument(String abi)3400 private static String checkAbiArgument(String abi) { 3401 if (TextUtils.isEmpty(abi)) { 3402 throw new IllegalArgumentException("Missing ABI argument"); 3403 } 3404 3405 if ("-".equals(abi)) { 3406 return abi; 3407 } 3408 3409 final String[] supportedAbis = Build.SUPPORTED_ABIS; 3410 for (String supportedAbi : supportedAbis) { 3411 if (supportedAbi.equals(abi)) { 3412 return abi; 3413 } 3414 } 3415 3416 throw new IllegalArgumentException("ABI " + abi + " not supported on this device"); 3417 } 3418 translateUserId(int userId, int allUserId, String logContext)3419 private int translateUserId(int userId, int allUserId, String logContext) { 3420 final boolean allowAll = (allUserId != UserHandle.USER_NULL); 3421 final int translatedUserId = ActivityManager.handleIncomingUser(Binder.getCallingPid(), 3422 Binder.getCallingUid(), userId, allowAll, true, logContext, "pm command"); 3423 return translatedUserId == UserHandle.USER_ALL ? allUserId : translatedUserId; 3424 } 3425 doCreateSession(SessionParams params, String installerPackageName, int userId)3426 private int doCreateSession(SessionParams params, String installerPackageName, int userId) 3427 throws RemoteException { 3428 if (userId == UserHandle.USER_ALL) { 3429 params.installFlags |= PackageManager.INSTALL_ALL_USERS; 3430 } 3431 final int translatedUserId = 3432 translateUserId(userId, UserHandle.USER_SYSTEM, "doCreateSession"); 3433 final int sessionId = mInterface.getPackageInstaller() 3434 .createSession(params, installerPackageName, null /*installerAttributionTag*/, 3435 translatedUserId); 3436 return sessionId; 3437 } 3438 doAddFiles(int sessionId, ArrayList<String> args, long sessionSizeBytes, boolean isApex)3439 private int doAddFiles(int sessionId, ArrayList<String> args, long sessionSizeBytes, 3440 boolean isApex) throws RemoteException { 3441 PackageInstaller.Session session = null; 3442 try { 3443 session = new PackageInstaller.Session( 3444 mInterface.getPackageInstaller().openSession(sessionId)); 3445 3446 // 1. Single file from stdin. 3447 if (args.isEmpty() || STDIN_PATH.equals(args.get(0))) { 3448 final String name = "base" + RANDOM.nextInt() + "." + (isApex ? "apex" : "apk"); 3449 final Metadata metadata = Metadata.forStdIn(name); 3450 session.addFile(LOCATION_DATA_APP, name, sessionSizeBytes, 3451 metadata.toByteArray(), null); 3452 return 0; 3453 } 3454 3455 for (String arg : args) { 3456 final int delimLocation = arg.indexOf(':'); 3457 3458 if (delimLocation != -1) { 3459 // 2. File with specified size read from stdin. 3460 if (processArgForStdin(arg, session) != 0) { 3461 return 1; 3462 } 3463 } else { 3464 // 3. Local file. 3465 processArgForLocalFile(arg, session); 3466 } 3467 } 3468 return 0; 3469 } catch (IllegalArgumentException e) { 3470 getErrPrintWriter().println("Failed to add file(s), reason: " + e); 3471 getOutPrintWriter().println("Failure [failed to add file(s)]"); 3472 return 1; 3473 } finally { 3474 IoUtils.closeQuietly(session); 3475 } 3476 } 3477 processArgForStdin(String arg, PackageInstaller.Session session)3478 private int processArgForStdin(String arg, PackageInstaller.Session session) { 3479 final String[] fileDesc = arg.split(":"); 3480 String name, fileId; 3481 long sizeBytes; 3482 byte[] signature = null; 3483 int streamingVersion = 0; 3484 3485 try { 3486 if (fileDesc.length < 2) { 3487 getErrPrintWriter().println("Must specify file name and size"); 3488 return 1; 3489 } 3490 name = fileDesc[0]; 3491 sizeBytes = Long.parseUnsignedLong(fileDesc[1]); 3492 fileId = name; 3493 3494 if (fileDesc.length > 2 && !TextUtils.isEmpty(fileDesc[2])) { 3495 fileId = fileDesc[2]; 3496 } 3497 if (fileDesc.length > 3) { 3498 signature = Base64.getDecoder().decode(fileDesc[3]); 3499 } 3500 if (fileDesc.length > 4) { 3501 streamingVersion = Integer.parseUnsignedInt(fileDesc[4]); 3502 if (streamingVersion < 0 || streamingVersion > 1) { 3503 getErrPrintWriter().println( 3504 "Unsupported streaming version: " + streamingVersion); 3505 return 1; 3506 } 3507 } 3508 } catch (IllegalArgumentException e) { 3509 getErrPrintWriter().println( 3510 "Unable to parse file parameters: " + arg + ", reason: " + e); 3511 return 1; 3512 } 3513 3514 if (TextUtils.isEmpty(name)) { 3515 getErrPrintWriter().println("Empty file name in: " + arg); 3516 return 1; 3517 } 3518 3519 final Metadata metadata; 3520 3521 if (signature != null) { 3522 // Streaming/adb mode. Versions: 3523 // 0: data only streaming, tree has to be fully available, 3524 // 1: tree and data streaming. 3525 metadata = (streamingVersion == 0) ? Metadata.forDataOnlyStreaming(fileId) 3526 : Metadata.forStreaming(fileId); 3527 try { 3528 if ((signature.length > 0) && (V4Signature.readFrom(signature) == null)) { 3529 getErrPrintWriter().println("V4 signature is invalid in: " + arg); 3530 return 1; 3531 } 3532 } catch (Exception e) { 3533 getErrPrintWriter().println( 3534 "V4 signature is invalid: " + e + " in " + arg); 3535 return 1; 3536 } 3537 } else { 3538 // Single-shot read from stdin. 3539 metadata = Metadata.forStdIn(fileId); 3540 } 3541 3542 session.addFile(LOCATION_DATA_APP, name, sizeBytes, metadata.toByteArray(), signature); 3543 return 0; 3544 } 3545 getFileStatSize(File file)3546 private long getFileStatSize(File file) { 3547 final ParcelFileDescriptor pfd = openFileForSystem(file.getPath(), "r"); 3548 if (pfd == null) { 3549 throw new IllegalArgumentException("Error: Can't open file: " + file.getPath()); 3550 } 3551 try { 3552 return pfd.getStatSize(); 3553 } finally { 3554 IoUtils.closeQuietly(pfd); 3555 } 3556 } 3557 processArgForLocalFile(String arg, PackageInstaller.Session session)3558 private void processArgForLocalFile(String arg, PackageInstaller.Session session) { 3559 final String inPath = arg; 3560 3561 final File file = new File(inPath); 3562 final String name = file.getName(); 3563 final long size = getFileStatSize(file); 3564 final Metadata metadata = Metadata.forLocalFile(inPath); 3565 3566 byte[] v4signatureBytes = null; 3567 // Try to load the v4 signature file for the APK; it might not exist. 3568 final String v4SignaturePath = inPath + V4Signature.EXT; 3569 final ParcelFileDescriptor pfd = openFileForSystem(v4SignaturePath, "r"); 3570 if (pfd != null) { 3571 try { 3572 final V4Signature v4signature = V4Signature.readFrom(pfd); 3573 v4signatureBytes = v4signature.toByteArray(); 3574 } catch (IOException ex) { 3575 Slog.e(TAG, "V4 signature file exists but failed to be parsed.", ex); 3576 } finally { 3577 IoUtils.closeQuietly(pfd); 3578 } 3579 } 3580 3581 session.addFile(LOCATION_DATA_APP, name, size, metadata.toByteArray(), v4signatureBytes); 3582 } 3583 doWriteSplits(int sessionId, ArrayList<String> splitPaths, long sessionSizeBytes, boolean isApex)3584 private int doWriteSplits(int sessionId, ArrayList<String> splitPaths, long sessionSizeBytes, 3585 boolean isApex) throws RemoteException { 3586 final boolean multipleSplits = splitPaths.size() > 1; 3587 for (String splitPath : splitPaths) { 3588 String splitName = multipleSplits ? new File(splitPath).getName() 3589 : "base." + (isApex ? "apex" : "apk"); 3590 3591 if (doWriteSplit(sessionId, splitPath, sessionSizeBytes, splitName, 3592 false /*logSuccess*/) != PackageInstaller.STATUS_SUCCESS) { 3593 return 1; 3594 } 3595 } 3596 return 0; 3597 } 3598 doWriteSplit(int sessionId, String inPath, long sizeBytes, String splitName, boolean logSuccess)3599 private int doWriteSplit(int sessionId, String inPath, long sizeBytes, String splitName, 3600 boolean logSuccess) throws RemoteException { 3601 PackageInstaller.Session session = null; 3602 try { 3603 session = new PackageInstaller.Session( 3604 mInterface.getPackageInstaller().openSession(sessionId)); 3605 3606 final PrintWriter pw = getOutPrintWriter(); 3607 3608 final ParcelFileDescriptor fd; 3609 if (STDIN_PATH.equals(inPath)) { 3610 fd = ParcelFileDescriptor.dup(getInFileDescriptor()); 3611 } else if (inPath != null) { 3612 fd = openFileForSystem(inPath, "r"); 3613 if (fd == null) { 3614 return -1; 3615 } 3616 sizeBytes = fd.getStatSize(); 3617 if (sizeBytes < 0) { 3618 getErrPrintWriter().println("Unable to get size of: " + inPath); 3619 return -1; 3620 } 3621 } else { 3622 fd = ParcelFileDescriptor.dup(getInFileDescriptor()); 3623 } 3624 if (sizeBytes <= 0) { 3625 getErrPrintWriter().println("Error: must specify a APK size"); 3626 return 1; 3627 } 3628 3629 session.write(splitName, 0, sizeBytes, fd); 3630 3631 if (logSuccess) { 3632 pw.println("Success: streamed " + sizeBytes + " bytes"); 3633 } 3634 return 0; 3635 } catch (IOException e) { 3636 getErrPrintWriter().println("Error: failed to write; " + e.getMessage()); 3637 return 1; 3638 } finally { 3639 IoUtils.closeQuietly(session); 3640 } 3641 } 3642 doInstallAddSession(int parentId, int[] sessionIds, boolean logSuccess)3643 private int doInstallAddSession(int parentId, int[] sessionIds, boolean logSuccess) 3644 throws RemoteException { 3645 final PrintWriter pw = getOutPrintWriter(); 3646 PackageInstaller.Session session = null; 3647 try { 3648 session = new PackageInstaller.Session( 3649 mInterface.getPackageInstaller().openSession(parentId)); 3650 if (!session.isMultiPackage()) { 3651 getErrPrintWriter().println( 3652 "Error: parent session ID is not a multi-package session"); 3653 return 1; 3654 } 3655 for (int i = 0; i < sessionIds.length; i++) { 3656 session.addChildSessionId(sessionIds[i]); 3657 } 3658 if (logSuccess) { 3659 pw.println("Success"); 3660 } 3661 return 0; 3662 } finally { 3663 IoUtils.closeQuietly(session); 3664 } 3665 } 3666 doRemoveSplits(int sessionId, Collection<String> splitNames, boolean logSuccess)3667 private int doRemoveSplits(int sessionId, Collection<String> splitNames, boolean logSuccess) 3668 throws RemoteException { 3669 final PrintWriter pw = getOutPrintWriter(); 3670 PackageInstaller.Session session = null; 3671 try { 3672 session = new PackageInstaller.Session( 3673 mInterface.getPackageInstaller().openSession(sessionId)); 3674 for (String splitName : splitNames) { 3675 session.removeSplit(splitName); 3676 } 3677 3678 if (logSuccess) { 3679 pw.println("Success"); 3680 } 3681 return 0; 3682 } catch (IOException e) { 3683 pw.println("Error: failed to remove split; " + e.getMessage()); 3684 return 1; 3685 } finally { 3686 IoUtils.closeQuietly(session); 3687 } 3688 } 3689 doCommitSession(int sessionId, boolean logSuccess)3690 private int doCommitSession(int sessionId, boolean logSuccess) 3691 throws RemoteException { 3692 3693 final PrintWriter pw = getOutPrintWriter(); 3694 PackageInstaller.Session session = null; 3695 try { 3696 session = new PackageInstaller.Session( 3697 mInterface.getPackageInstaller().openSession(sessionId)); 3698 if (!session.isMultiPackage() && !session.isStaged()) { 3699 // Validity check that all .dm files match an apk. 3700 // (The installer does not support standalone .dm files and will not process them.) 3701 try { 3702 DexMetadataHelper.validateDexPaths(session.getNames()); 3703 } catch (IllegalStateException | IOException e) { 3704 pw.println( 3705 "Warning [Could not validate the dex paths: " + e.getMessage() + "]"); 3706 } 3707 } 3708 final LocalIntentReceiver receiver = new LocalIntentReceiver(); 3709 session.commit(receiver.getIntentSender()); 3710 if (!session.isStaged()) { 3711 final Intent result = receiver.getResult(); 3712 final int status = result.getIntExtra(PackageInstaller.EXTRA_STATUS, 3713 PackageInstaller.STATUS_FAILURE); 3714 if (status == PackageInstaller.STATUS_SUCCESS) { 3715 if (logSuccess) { 3716 pw.println("Success"); 3717 } 3718 } else { 3719 pw.println("Failure [" 3720 + result.getStringExtra(PackageInstaller.EXTRA_STATUS_MESSAGE) + "]"); 3721 } 3722 return status; 3723 } else { 3724 // Return immediately without retrieving the result. The caller will decide 3725 // whether to wait for the session to become ready. 3726 if (logSuccess) { 3727 pw.println("Success"); 3728 } 3729 return PackageInstaller.STATUS_SUCCESS; 3730 } 3731 } finally { 3732 IoUtils.closeQuietly(session); 3733 } 3734 } 3735 doAbandonSession(int sessionId, boolean logSuccess)3736 private int doAbandonSession(int sessionId, boolean logSuccess) throws RemoteException { 3737 final PrintWriter pw = getOutPrintWriter(); 3738 PackageInstaller.Session session = null; 3739 try { 3740 session = new PackageInstaller.Session( 3741 mInterface.getPackageInstaller().openSession(sessionId)); 3742 session.abandon(); 3743 if (logSuccess) { 3744 pw.println("Success"); 3745 } 3746 return 0; 3747 } finally { 3748 IoUtils.closeQuietly(session); 3749 } 3750 } 3751 doListPermissions(ArrayList<String> groupList, boolean groups, boolean labels, boolean summary, int startProtectionLevel, int endProtectionLevel)3752 private void doListPermissions(ArrayList<String> groupList, boolean groups, boolean labels, 3753 boolean summary, int startProtectionLevel, int endProtectionLevel) 3754 throws RemoteException { 3755 final PrintWriter pw = getOutPrintWriter(); 3756 final int groupCount = groupList.size(); 3757 for (int i = 0; i < groupCount; i++) { 3758 String groupName = groupList.get(i); 3759 String prefix = ""; 3760 if (groups) { 3761 if (i > 0) { 3762 pw.println(""); 3763 } 3764 if (groupName != null) { 3765 PermissionGroupInfo pgi = 3766 mInterface.getPermissionGroupInfo(groupName, 0 /*flags*/); 3767 if (summary) { 3768 Resources res = getResources(pgi); 3769 if (res != null) { 3770 pw.print(loadText(pgi, pgi.labelRes, pgi.nonLocalizedLabel) + ": "); 3771 } else { 3772 pw.print(pgi.name + ": "); 3773 3774 } 3775 } else { 3776 pw.println((labels ? "+ " : "") + "group:" + pgi.name); 3777 if (labels) { 3778 pw.println(" package:" + pgi.packageName); 3779 Resources res = getResources(pgi); 3780 if (res != null) { 3781 pw.println(" label:" 3782 + loadText(pgi, pgi.labelRes, pgi.nonLocalizedLabel)); 3783 pw.println(" description:" 3784 + loadText(pgi, pgi.descriptionRes, 3785 pgi.nonLocalizedDescription)); 3786 } 3787 } 3788 } 3789 } else { 3790 pw.println(((labels && !summary) ? "+ " : "") + "ungrouped:"); 3791 } 3792 prefix = " "; 3793 } 3794 List<PermissionInfo> ps = mPermissionManager 3795 .queryPermissionsByGroup(groupList.get(i), 0 /*flags*/); 3796 final int count = (ps == null ? 0 : ps.size()); 3797 boolean first = true; 3798 for (int p = 0 ; p < count ; p++) { 3799 PermissionInfo pi = ps.get(p); 3800 if (groups && groupName == null && pi.group != null) { 3801 continue; 3802 } 3803 final int base = pi.protectionLevel & PermissionInfo.PROTECTION_MASK_BASE; 3804 if (base < startProtectionLevel 3805 || base > endProtectionLevel) { 3806 continue; 3807 } 3808 if (summary) { 3809 if (first) { 3810 first = false; 3811 } else { 3812 pw.print(", "); 3813 } 3814 Resources res = getResources(pi); 3815 if (res != null) { 3816 pw.print(loadText(pi, pi.labelRes, 3817 pi.nonLocalizedLabel)); 3818 } else { 3819 pw.print(pi.name); 3820 } 3821 } else { 3822 pw.println(prefix + (labels ? "+ " : "") 3823 + "permission:" + pi.name); 3824 if (labels) { 3825 pw.println(prefix + " package:" + pi.packageName); 3826 Resources res = getResources(pi); 3827 if (res != null) { 3828 pw.println(prefix + " label:" 3829 + loadText(pi, pi.labelRes, 3830 pi.nonLocalizedLabel)); 3831 pw.println(prefix + " description:" 3832 + loadText(pi, pi.descriptionRes, 3833 pi.nonLocalizedDescription)); 3834 } 3835 pw.println(prefix + " protectionLevel:" 3836 + PermissionInfo.protectionToString(pi.protectionLevel)); 3837 } 3838 } 3839 } 3840 3841 if (summary) { 3842 pw.println(""); 3843 } 3844 } 3845 } 3846 loadText(PackageItemInfo pii, int res, CharSequence nonLocalized)3847 private String loadText(PackageItemInfo pii, int res, CharSequence nonLocalized) 3848 throws RemoteException { 3849 if (nonLocalized != null) { 3850 return nonLocalized.toString(); 3851 } 3852 if (res != 0) { 3853 Resources r = getResources(pii); 3854 if (r != null) { 3855 try { 3856 return r.getString(res); 3857 } catch (Resources.NotFoundException e) { 3858 } 3859 } 3860 } 3861 return null; 3862 } 3863 getResources(PackageItemInfo pii)3864 private Resources getResources(PackageItemInfo pii) throws RemoteException { 3865 Resources res = mResourceCache.get(pii.packageName); 3866 if (res != null) return res; 3867 3868 ApplicationInfo ai = mInterface.getApplicationInfo(pii.packageName, 3869 PackageManager.MATCH_DISABLED_COMPONENTS 3870 | PackageManager.MATCH_HIDDEN_UNTIL_INSTALLED_COMPONENTS 3871 | PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS, 0); 3872 AssetManager am = new AssetManager(); 3873 am.addAssetPath(ai.publicSourceDir); 3874 res = new Resources(am, null, null); 3875 mResourceCache.put(pii.packageName, res); 3876 return res; 3877 } 3878 3879 @Override onHelp()3880 public void onHelp() { 3881 final PrintWriter pw = getOutPrintWriter(); 3882 pw.println("Package manager (package) commands:"); 3883 pw.println(" help"); 3884 pw.println(" Print this help text."); 3885 pw.println(""); 3886 pw.println(" path [--user USER_ID] PACKAGE"); 3887 pw.println(" Print the path to the .apk of the given PACKAGE."); 3888 pw.println(""); 3889 pw.println(" dump PACKAGE"); 3890 pw.println(" Print various system state associated with the given PACKAGE."); 3891 pw.println(""); 3892 pw.println(" has-feature FEATURE_NAME [version]"); 3893 pw.println(" Prints true and returns exit status 0 when system has a FEATURE_NAME,"); 3894 pw.println(" otherwise prints false and returns exit status 1"); 3895 pw.println(""); 3896 pw.println(" list features"); 3897 pw.println(" Prints all features of the system."); 3898 pw.println(""); 3899 pw.println(" list instrumentation [-f] [TARGET-PACKAGE]"); 3900 pw.println(" Prints all test packages; optionally only those targeting TARGET-PACKAGE"); 3901 pw.println(" Options:"); 3902 pw.println(" -f: dump the name of the .apk file containing the test package"); 3903 pw.println(""); 3904 pw.println(" list libraries"); 3905 pw.println(" Prints all system libraries."); 3906 pw.println(""); 3907 pw.println(" list packages [-f] [-d] [-e] [-s] [-3] [-i] [-l] [-u] [-U] "); 3908 pw.println(" [--show-versioncode] [--apex-only] [--uid UID] [--user USER_ID] [FILTER]"); 3909 pw.println(" Prints all packages; optionally only those whose name contains"); 3910 pw.println(" the text in FILTER. Options are:"); 3911 pw.println(" -f: see their associated file"); 3912 pw.println(" -a: all known packages (but excluding APEXes)"); 3913 pw.println(" -d: filter to only show disabled packages"); 3914 pw.println(" -e: filter to only show enabled packages"); 3915 pw.println(" -s: filter to only show system packages"); 3916 pw.println(" -3: filter to only show third party packages"); 3917 pw.println(" -i: see the installer for the packages"); 3918 pw.println(" -l: ignored (used for compatibility with older releases)"); 3919 pw.println(" -U: also show the package UID"); 3920 pw.println(" -u: also include uninstalled packages"); 3921 pw.println(" --show-versioncode: also show the version code"); 3922 pw.println(" --apex-only: only show APEX packages"); 3923 pw.println(" --uid UID: filter to only show packages with the given UID"); 3924 pw.println(" --user USER_ID: only list packages belonging to the given user"); 3925 pw.println(""); 3926 pw.println(" list permission-groups"); 3927 pw.println(" Prints all known permission groups."); 3928 pw.println(""); 3929 pw.println(" list permissions [-g] [-f] [-d] [-u] [GROUP]"); 3930 pw.println(" Prints all known permissions; optionally only those in GROUP. Options are:"); 3931 pw.println(" -g: organize by group"); 3932 pw.println(" -f: print all information"); 3933 pw.println(" -s: short summary"); 3934 pw.println(" -d: only list dangerous permissions"); 3935 pw.println(" -u: list only the permissions users will see"); 3936 pw.println(""); 3937 pw.println(" list staged-sessions [--only-ready] [--only-sessionid] [--only-parent]"); 3938 pw.println(" Prints all staged sessions."); 3939 pw.println(" --only-ready: show only staged sessions that are ready"); 3940 pw.println(" --only-sessionid: show only sessionId of each session"); 3941 pw.println(" --only-parent: hide all children sessions"); 3942 pw.println(""); 3943 pw.println(" list users"); 3944 pw.println(" Prints all users."); 3945 pw.println(""); 3946 pw.println(" resolve-activity [--brief] [--components] [--query-flags FLAGS]"); 3947 pw.println(" [--user USER_ID] INTENT"); 3948 pw.println(" Prints the activity that resolves to the given INTENT."); 3949 pw.println(""); 3950 pw.println(" query-activities [--brief] [--components] [--query-flags FLAGS]"); 3951 pw.println(" [--user USER_ID] INTENT"); 3952 pw.println(" Prints all activities that can handle the given INTENT."); 3953 pw.println(""); 3954 pw.println(" query-services [--brief] [--components] [--query-flags FLAGS]"); 3955 pw.println(" [--user USER_ID] INTENT"); 3956 pw.println(" Prints all services that can handle the given INTENT."); 3957 pw.println(""); 3958 pw.println(" query-receivers [--brief] [--components] [--query-flags FLAGS]"); 3959 pw.println(" [--user USER_ID] INTENT"); 3960 pw.println(" Prints all broadcast receivers that can handle the given INTENT."); 3961 pw.println(""); 3962 pw.println(" install [-rtfdg] [-i PACKAGE] [--user USER_ID|all|current]"); 3963 pw.println(" [-p INHERIT_PACKAGE] [--install-location 0/1/2]"); 3964 pw.println(" [--install-reason 0/1/2/3/4] [--originating-uri URI]"); 3965 pw.println(" [--referrer URI] [--abi ABI_NAME] [--force-sdk]"); 3966 pw.println(" [--preload] [--instant] [--full] [--dont-kill]"); 3967 pw.println(" [--enable-rollback]"); 3968 pw.println(" [--force-uuid internal|UUID] [--pkg PACKAGE] [-S BYTES]"); 3969 pw.println(" [--apex] [--staged-ready-timeout TIMEOUT]"); 3970 pw.println(" [PATH [SPLIT...]|-]"); 3971 pw.println(" Install an application. Must provide the apk data to install, either as"); 3972 pw.println(" file path(s) or '-' to read from stdin. Options are:"); 3973 pw.println(" -R: disallow replacement of existing application"); 3974 pw.println(" -t: allow test packages"); 3975 pw.println(" -i: specify package name of installer owning the app"); 3976 pw.println(" -f: install application on internal flash"); 3977 pw.println(" -d: allow version code downgrade (debuggable packages only)"); 3978 pw.println(" -p: partial application install (new split on top of existing pkg)"); 3979 pw.println(" -g: grant all runtime permissions"); 3980 pw.println(" -S: size in bytes of package, required for stdin"); 3981 pw.println(" --user: install under the given user."); 3982 pw.println(" --dont-kill: installing a new feature split, don't kill running app"); 3983 pw.println(" --restrict-permissions: don't whitelist restricted permissions at install"); 3984 pw.println(" --originating-uri: set URI where app was downloaded from"); 3985 pw.println(" --referrer: set URI that instigated the install of the app"); 3986 pw.println(" --pkg: specify expected package name of app being installed"); 3987 pw.println(" --abi: override the default ABI of the platform"); 3988 pw.println(" --instant: cause the app to be installed as an ephemeral install app"); 3989 pw.println(" --full: cause the app to be installed as a non-ephemeral full app"); 3990 pw.println(" --install-location: force the install location:"); 3991 pw.println(" 0=auto, 1=internal only, 2=prefer external"); 3992 pw.println(" --install-reason: indicates why the app is being installed:"); 3993 pw.println(" 0=unknown, 1=admin policy, 2=device restore,"); 3994 pw.println(" 3=device setup, 4=user request"); 3995 pw.println(" --force-uuid: force install on to disk volume with given UUID"); 3996 pw.println(" --apex: install an .apex file, not an .apk"); 3997 pw.println(" --staged-ready-timeout: By default, staged sessions wait " 3998 + DEFAULT_STAGED_READY_TIMEOUT_MS); 3999 pw.println(" milliseconds for pre-reboot verification to complete when"); 4000 pw.println(" performing staged install. This flag is used to alter the waiting"); 4001 pw.println(" time. You can skip the waiting time by specifying a TIMEOUT of '0'"); 4002 pw.println(""); 4003 pw.println(" install-existing [--user USER_ID|all|current]"); 4004 pw.println(" [--instant] [--full] [--wait] [--restrict-permissions] PACKAGE"); 4005 pw.println(" Installs an existing application for a new user. Options are:"); 4006 pw.println(" --user: install for the given user."); 4007 pw.println(" --instant: install as an instant app"); 4008 pw.println(" --full: install as a full app"); 4009 pw.println(" --wait: wait until the package is installed"); 4010 pw.println(" --restrict-permissions: don't whitelist restricted permissions"); 4011 pw.println(""); 4012 pw.println(" install-create [-lrtsfdg] [-i PACKAGE] [--user USER_ID|all|current]"); 4013 pw.println(" [-p INHERIT_PACKAGE] [--install-location 0/1/2]"); 4014 pw.println(" [--install-reason 0/1/2/3/4] [--originating-uri URI]"); 4015 pw.println(" [--referrer URI] [--abi ABI_NAME] [--force-sdk]"); 4016 pw.println(" [--preload] [--instant] [--full] [--dont-kill]"); 4017 pw.println(" [--force-uuid internal|UUID] [--pkg PACKAGE] [--apex] [-S BYTES]"); 4018 pw.println(" [--multi-package] [--staged]"); 4019 pw.println(" Like \"install\", but starts an install session. Use \"install-write\""); 4020 pw.println(" to push data into the session, and \"install-commit\" to finish."); 4021 pw.println(""); 4022 pw.println(" install-write [-S BYTES] SESSION_ID SPLIT_NAME [PATH|-]"); 4023 pw.println(" Write an apk into the given install session. If the path is '-', data"); 4024 pw.println(" will be read from stdin. Options are:"); 4025 pw.println(" -S: size in bytes of package, required for stdin"); 4026 pw.println(""); 4027 pw.println(" install-remove SESSION_ID SPLIT..."); 4028 pw.println(" Mark SPLIT(s) as removed in the given install session."); 4029 pw.println(""); 4030 pw.println(" install-add-session MULTI_PACKAGE_SESSION_ID CHILD_SESSION_IDs"); 4031 pw.println(" Add one or more session IDs to a multi-package session."); 4032 pw.println(""); 4033 pw.println(" install-commit SESSION_ID"); 4034 pw.println(" Commit the given active install session, installing the app."); 4035 pw.println(""); 4036 pw.println(" install-abandon SESSION_ID"); 4037 pw.println(" Delete the given active install session."); 4038 pw.println(""); 4039 pw.println(" set-install-location LOCATION"); 4040 pw.println(" Changes the default install location. NOTE this is only intended for debugging;"); 4041 pw.println(" using this can cause applications to break and other undersireable behavior."); 4042 pw.println(" LOCATION is one of:"); 4043 pw.println(" 0 [auto]: Let system decide the best location"); 4044 pw.println(" 1 [internal]: Install on internal device storage"); 4045 pw.println(" 2 [external]: Install on external media"); 4046 pw.println(""); 4047 pw.println(" get-install-location"); 4048 pw.println(" Returns the current install location: 0, 1 or 2 as per set-install-location."); 4049 pw.println(""); 4050 pw.println(" move-package PACKAGE [internal|UUID]"); 4051 pw.println(""); 4052 pw.println(" move-primary-storage [internal|UUID]"); 4053 pw.println(""); 4054 pw.println(" uninstall [-k] [--user USER_ID] [--versionCode VERSION_CODE]"); 4055 pw.println(" PACKAGE [SPLIT...]"); 4056 pw.println(" Remove the given package name from the system. May remove an entire app"); 4057 pw.println(" if no SPLIT names specified, otherwise will remove only the splits of the"); 4058 pw.println(" given app. Options are:"); 4059 pw.println(" -k: keep the data and cache directories around after package removal."); 4060 pw.println(" --user: remove the app from the given user."); 4061 pw.println(" --versionCode: only uninstall if the app has the given version code."); 4062 pw.println(""); 4063 pw.println(" clear [--user USER_ID] [--cache-only] PACKAGE"); 4064 pw.println(" Deletes data associated with a package. Options are:"); 4065 pw.println(" --user: specifies the user for which we need to clear data"); 4066 pw.println(" --cache-only: a flag which tells if we only need to clear cache data"); 4067 pw.println(""); 4068 pw.println(" enable [--user USER_ID] PACKAGE_OR_COMPONENT"); 4069 pw.println(" disable [--user USER_ID] PACKAGE_OR_COMPONENT"); 4070 pw.println(" disable-user [--user USER_ID] PACKAGE_OR_COMPONENT"); 4071 pw.println(" disable-until-used [--user USER_ID] PACKAGE_OR_COMPONENT"); 4072 pw.println(" default-state [--user USER_ID] PACKAGE_OR_COMPONENT"); 4073 pw.println(" These commands change the enabled state of a given package or"); 4074 pw.println(" component (written as \"package/class\")."); 4075 pw.println(""); 4076 pw.println(" hide [--user USER_ID] PACKAGE_OR_COMPONENT"); 4077 pw.println(" unhide [--user USER_ID] PACKAGE_OR_COMPONENT"); 4078 pw.println(""); 4079 pw.println(" suspend [--user USER_ID] PACKAGE [PACKAGE...]"); 4080 pw.println(" Suspends the specified package(s) (as user)."); 4081 pw.println(""); 4082 pw.println(" unsuspend [--user USER_ID] PACKAGE [PACKAGE...]"); 4083 pw.println(" Unsuspends the specified package(s) (as user)."); 4084 pw.println(""); 4085 pw.println(" set-distracting-restriction [--user USER_ID] [--flag FLAG ...]"); 4086 pw.println(" PACKAGE [PACKAGE...]"); 4087 pw.println(" Sets the specified restriction flags to given package(s) (for user)."); 4088 pw.println(" Flags are:"); 4089 pw.println(" hide-notifications: Hides notifications from this package"); 4090 pw.println(" hide-from-suggestions: Hides this package from suggestions"); 4091 pw.println(" (by the launcher, etc.)"); 4092 pw.println(" Any existing flags are overwritten, which also means that if no flags are"); 4093 pw.println(" specified then all existing flags will be cleared."); 4094 pw.println(""); 4095 pw.println(" grant [--user USER_ID] PACKAGE PERMISSION"); 4096 pw.println(" revoke [--user USER_ID] PACKAGE PERMISSION"); 4097 pw.println(" These commands either grant or revoke permissions to apps. The permissions"); 4098 pw.println(" must be declared as used in the app's manifest, be runtime permissions"); 4099 pw.println(" (protection level dangerous), and the app targeting SDK greater than Lollipop MR1."); 4100 pw.println(""); 4101 pw.println(" set-permission-flags [--user USER_ID] PACKAGE PERMISSION [FLAGS..]"); 4102 pw.println(" clear-permission-flags [--user USER_ID] PACKAGE PERMISSION [FLAGS..]"); 4103 pw.println(" These commands either set or clear permission flags on apps. The permissions"); 4104 pw.println(" must be declared as used in the app's manifest, be runtime permissions"); 4105 pw.println(" (protection level dangerous), and the app targeting SDK greater than Lollipop MR1."); 4106 pw.println(" The flags must be one or more of " + SUPPORTED_PERMISSION_FLAGS_LIST); 4107 pw.println(""); 4108 pw.println(" reset-permissions"); 4109 pw.println(" Revert all runtime permissions to their default state."); 4110 pw.println(""); 4111 pw.println(" set-permission-enforced PERMISSION [true|false]"); 4112 pw.println(""); 4113 pw.println(" get-privapp-permissions TARGET-PACKAGE"); 4114 pw.println(" Prints all privileged permissions for a package."); 4115 pw.println(""); 4116 pw.println(" get-privapp-deny-permissions TARGET-PACKAGE"); 4117 pw.println(" Prints all privileged permissions that are denied for a package."); 4118 pw.println(""); 4119 pw.println(" get-oem-permissions TARGET-PACKAGE"); 4120 pw.println(" Prints all OEM permissions for a package."); 4121 pw.println(""); 4122 pw.println(" trim-caches DESIRED_FREE_SPACE [internal|UUID]"); 4123 pw.println(" Trim cache files to reach the given free space."); 4124 pw.println(""); 4125 pw.println(" list users"); 4126 pw.println(" Lists the current users."); 4127 pw.println(""); 4128 pw.println(" create-user [--profileOf USER_ID] [--managed] [--restricted] [--ephemeral]"); 4129 pw.println(" [--guest] [--pre-create-only] [--user-type USER_TYPE] USER_NAME"); 4130 pw.println(" Create a new user with the given USER_NAME, printing the new user identifier"); 4131 pw.println(" of the user."); 4132 // TODO(b/142482943): Consider fetching the list of user types from UMS. 4133 pw.println(" USER_TYPE is the name of a user type, e.g. android.os.usertype.profile.MANAGED."); 4134 pw.println(" If not specified, the default user type is android.os.usertype.full.SECONDARY."); 4135 pw.println(" --managed is shorthand for '--user-type android.os.usertype.profile.MANAGED'."); 4136 pw.println(" --restricted is shorthand for '--user-type android.os.usertype.full.RESTRICTED'."); 4137 pw.println(" --guest is shorthand for '--user-type android.os.usertype.full.GUEST'."); 4138 pw.println(""); 4139 pw.println(" remove-user [--set-ephemeral-if-in-use | --wait] USER_ID"); 4140 pw.println(" Remove the user with the given USER_IDENTIFIER, deleting all data"); 4141 pw.println(" associated with that user."); 4142 pw.println(" --set-ephemeral-if-in-use: If the user is currently running and"); 4143 pw.println(" therefore cannot be removed immediately, mark the user as ephemeral"); 4144 pw.println(" so that it will be automatically removed when possible (after user"); 4145 pw.println(" switch or reboot)"); 4146 pw.println(" --wait: Wait until user is removed. Ignored if set-ephemeral-if-in-use"); 4147 pw.println(""); 4148 pw.println(" set-user-restriction [--user USER_ID] RESTRICTION VALUE"); 4149 pw.println(""); 4150 pw.println(" get-max-users"); 4151 pw.println(""); 4152 pw.println(" get-max-running-users"); 4153 pw.println(""); 4154 pw.println(" compile [-m MODE | -r REASON] [-f] [-c] [--split SPLIT_NAME]"); 4155 pw.println(" [--reset] [--check-prof (true | false)] (-a | TARGET-PACKAGE)"); 4156 pw.println(" Trigger compilation of TARGET-PACKAGE or all packages if \"-a\". Options are:"); 4157 pw.println(" -a: compile all packages"); 4158 pw.println(" -c: clear profile data before compiling"); 4159 pw.println(" -f: force compilation even if not needed"); 4160 pw.println(" -m: select compilation mode"); 4161 pw.println(" MODE is one of the dex2oat compiler filters:"); 4162 pw.println(" assume-verified"); 4163 pw.println(" extract"); 4164 pw.println(" verify"); 4165 pw.println(" quicken"); 4166 pw.println(" space-profile"); 4167 pw.println(" space"); 4168 pw.println(" speed-profile"); 4169 pw.println(" speed"); 4170 pw.println(" everything"); 4171 pw.println(" -r: select compilation reason"); 4172 pw.println(" REASON is one of:"); 4173 for (int i = 0; i < PackageManagerServiceCompilerMapping.REASON_STRINGS.length; i++) { 4174 pw.println(" " + PackageManagerServiceCompilerMapping.REASON_STRINGS[i]); 4175 } 4176 pw.println(" --reset: restore package to its post-install state"); 4177 pw.println(" --check-prof (true | false): look at profiles when doing dexopt?"); 4178 pw.println(" --secondary-dex: compile app secondary dex files"); 4179 pw.println(" --split SPLIT: compile only the given split name"); 4180 pw.println(" --compile-layouts: compile layout resources for faster inflation"); 4181 pw.println(""); 4182 pw.println(" force-dex-opt PACKAGE"); 4183 pw.println(" Force immediate execution of dex opt for the given PACKAGE."); 4184 pw.println(""); 4185 pw.println(" delete-dexopt PACKAGE"); 4186 pw.println(" Delete dex optimization results for the given PACKAGE."); 4187 pw.println(""); 4188 pw.println(" bg-dexopt-job"); 4189 pw.println(" Execute the background optimizations immediately."); 4190 pw.println(" Note that the command only runs the background optimizer logic. It may"); 4191 pw.println(" overlap with the actual job but the job scheduler will not be able to"); 4192 pw.println(" cancel it. It will also run even if the device is not in the idle"); 4193 pw.println(" maintenance mode."); 4194 pw.println(" cancel-bg-dexopt-job"); 4195 pw.println(" Cancels currently running background optimizations immediately."); 4196 pw.println(" This cancels optimizations run from bg-dexopt-job or from JobScjeduler."); 4197 pw.println(" Note that cancelling currently running bg-dexopt-job command requires"); 4198 pw.println(" running this command from separate adb shell."); 4199 pw.println(""); 4200 pw.println(" reconcile-secondary-dex-files TARGET-PACKAGE"); 4201 pw.println(" Reconciles the package secondary dex files with the generated oat files."); 4202 pw.println(""); 4203 pw.println(" dump-profiles [--dump-classes-and-methods] TARGET-PACKAGE"); 4204 pw.println(" Dumps method/class profile files to"); 4205 pw.println(" " + ART_PROFILE_SNAPSHOT_DEBUG_LOCATION 4206 + "TARGET-PACKAGE-primary.prof.txt."); 4207 pw.println(" --dump-classes-and-methods: passed along to the profman binary to"); 4208 pw.println(" switch to the format used by 'profman --create-profile-from'."); 4209 pw.println(""); 4210 pw.println(" snapshot-profile TARGET-PACKAGE [--code-path path]"); 4211 pw.println(" Take a snapshot of the package profiles to"); 4212 pw.println(" " + ART_PROFILE_SNAPSHOT_DEBUG_LOCATION 4213 + "TARGET-PACKAGE[-code-path].prof"); 4214 pw.println(" If TARGET-PACKAGE=android it will take a snapshot of the boot image"); 4215 pw.println(""); 4216 pw.println(" set-home-activity [--user USER_ID] TARGET-COMPONENT"); 4217 pw.println(" Set the default home activity (aka launcher)."); 4218 pw.println(" TARGET-COMPONENT can be a package name (com.package.my) or a full"); 4219 pw.println(" component (com.package.my/component.name). However, only the package name"); 4220 pw.println(" matters: the actual component used will be determined automatically from"); 4221 pw.println(" the package."); 4222 pw.println(""); 4223 pw.println(" set-installer PACKAGE INSTALLER"); 4224 pw.println(" Set installer package name"); 4225 pw.println(""); 4226 pw.println(" get-instantapp-resolver"); 4227 pw.println(" Return the name of the component that is the current instant app installer."); 4228 pw.println(""); 4229 pw.println(" set-harmful-app-warning [--user <USER_ID>] <PACKAGE> [<WARNING>]"); 4230 pw.println(" Mark the app as harmful with the given warning message."); 4231 pw.println(""); 4232 pw.println(" get-harmful-app-warning [--user <USER_ID>] <PACKAGE>"); 4233 pw.println(" Return the harmful app warning message for the given app, if present"); 4234 pw.println(); 4235 pw.println(" uninstall-system-updates [<PACKAGE>]"); 4236 pw.println(" Removes updates to the given system application and falls back to its"); 4237 pw.println(" /system version. Does nothing if the given package is not a system app."); 4238 pw.println(" If no package is specified, removes updates to all system applications."); 4239 pw.println(""); 4240 pw.println(" get-moduleinfo [--all | --installed] [module-name]"); 4241 pw.println(" Displays module info. If module-name is specified only that info is shown"); 4242 pw.println(" By default, without any argument only installed modules are shown."); 4243 pw.println(" --all: show all module info"); 4244 pw.println(" --installed: show only installed modules"); 4245 pw.println(""); 4246 pw.println(" log-visibility [--enable|--disable] <PACKAGE>"); 4247 pw.println(" Turns on debug logging when visibility is blocked for the given package."); 4248 pw.println(" --enable: turn on debug logging (default)"); 4249 pw.println(" --disable: turn off debug logging"); 4250 pw.println(""); 4251 pw.println(" set-silent-updates-policy [--allow-unlimited-silent-updates <INSTALLER>]"); 4252 pw.println(" [--throttle-time <SECONDS>] [--reset]"); 4253 pw.println(" Sets the policies of the silent updates."); 4254 pw.println(" --allow-unlimited-silent-updates: allows unlimited silent updated"); 4255 pw.println(" installation requests from the installer without the throttle time."); 4256 pw.println(" --throttle-time: update the silent updates throttle time in seconds."); 4257 pw.println(" --reset: restore the installer and throttle time to the default, and"); 4258 pw.println(" clear tracks of silent updates in the system."); 4259 pw.println(""); 4260 mDomainVerificationShell.printHelp(pw); 4261 pw.println(""); 4262 Intent.printIntentArgsHelp(pw , ""); 4263 } 4264 4265 private static class LocalIntentReceiver { 4266 private final LinkedBlockingQueue<Intent> mResult = new LinkedBlockingQueue<>(); 4267 4268 private IIntentSender.Stub mLocalSender = new IIntentSender.Stub() { 4269 @Override 4270 public void send(int code, Intent intent, String resolvedType, IBinder whitelistToken, 4271 IIntentReceiver finishedReceiver, String requiredPermission, Bundle options) { 4272 try { 4273 mResult.offer(intent, 5, TimeUnit.SECONDS); 4274 } catch (InterruptedException e) { 4275 throw new RuntimeException(e); 4276 } 4277 } 4278 }; 4279 getIntentSender()4280 public IntentSender getIntentSender() { 4281 return new IntentSender((IIntentSender) mLocalSender); 4282 } 4283 getResult()4284 public Intent getResult() { 4285 try { 4286 return mResult.take(); 4287 } catch (InterruptedException e) { 4288 throw new RuntimeException(e); 4289 } 4290 } 4291 } 4292 } 4293