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