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