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