1 /* 2 * Copyright (C) 2014 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 android.content.pm; 18 19 import static android.app.AppOpsManager.MODE_ALLOWED; 20 import static android.app.AppOpsManager.MODE_DEFAULT; 21 import static android.app.AppOpsManager.MODE_IGNORED; 22 23 import android.Manifest; 24 import android.annotation.CurrentTimeMillisLong; 25 import android.annotation.IntDef; 26 import android.annotation.NonNull; 27 import android.annotation.Nullable; 28 import android.annotation.RequiresPermission; 29 import android.annotation.SdkConstant; 30 import android.annotation.SdkConstant.SdkConstantType; 31 import android.annotation.SystemApi; 32 import android.annotation.TestApi; 33 import android.app.ActivityManager; 34 import android.app.AppGlobals; 35 import android.compat.annotation.UnsupportedAppUsage; 36 import android.content.Intent; 37 import android.content.IntentSender; 38 import android.content.pm.PackageManager.DeleteFlags; 39 import android.content.pm.PackageManager.InstallReason; 40 import android.content.pm.PackageManager.InstallScenario; 41 import android.graphics.Bitmap; 42 import android.net.Uri; 43 import android.os.Build; 44 import android.os.FileBridge; 45 import android.os.Handler; 46 import android.os.HandlerExecutor; 47 import android.os.Parcel; 48 import android.os.ParcelFileDescriptor; 49 import android.os.Parcelable; 50 import android.os.ParcelableException; 51 import android.os.RemoteException; 52 import android.os.SystemProperties; 53 import android.os.UserHandle; 54 import android.system.ErrnoException; 55 import android.system.Os; 56 import android.text.TextUtils; 57 import android.util.ArraySet; 58 import android.util.ExceptionUtils; 59 60 import com.android.internal.util.IndentingPrintWriter; 61 import com.android.internal.util.Preconditions; 62 import com.android.internal.util.function.pooled.PooledLambda; 63 64 import java.io.Closeable; 65 import java.io.IOException; 66 import java.io.InputStream; 67 import java.io.OutputStream; 68 import java.lang.annotation.Retention; 69 import java.lang.annotation.RetentionPolicy; 70 import java.security.MessageDigest; 71 import java.util.ArrayList; 72 import java.util.Collections; 73 import java.util.Iterator; 74 import java.util.List; 75 import java.util.Objects; 76 import java.util.Set; 77 import java.util.concurrent.Executor; 78 79 /** 80 * Offers the ability to install, upgrade, and remove applications on the 81 * device. This includes support for apps packaged either as a single 82 * "monolithic" APK, or apps packaged as multiple "split" APKs. 83 * <p> 84 * An app is delivered for installation through a 85 * {@link PackageInstaller.Session}, which any app can create. Once the session 86 * is created, the installer can stream one or more APKs into place until it 87 * decides to either commit or destroy the session. Committing may require user 88 * intervention to complete the installation, unless the caller falls into one of the 89 * following categories, in which case the installation will complete automatically. 90 * <ul> 91 * <li>the device owner 92 * <li>the affiliated profile owner 93 * </ul> 94 * <p> 95 * Sessions can install brand new apps, upgrade existing apps, or add new splits 96 * into an existing app. 97 * <p> 98 * Apps packaged as multiple split APKs always consist of a single "base" APK 99 * (with a {@code null} split name) and zero or more "split" APKs (with unique 100 * split names). Any subset of these APKs can be installed together, as long as 101 * the following constraints are met: 102 * <ul> 103 * <li>All APKs must have the exact same package name, version code, and signing 104 * certificates. 105 * <li>All APKs must have unique split names. 106 * <li>All installations must contain a single base APK. 107 * </ul> 108 * <p> 109 * The ApiDemos project contains examples of using this API: 110 * <code>ApiDemos/src/com/example/android/apis/content/InstallApk*.java</code>. 111 */ 112 public class PackageInstaller { 113 private static final String TAG = "PackageInstaller"; 114 115 /** {@hide} */ 116 public static final boolean ENABLE_REVOCABLE_FD = 117 SystemProperties.getBoolean("fw.revocable_fd", false); 118 119 /** 120 * Activity Action: Show details about a particular install session. This 121 * may surface actions such as pause, resume, or cancel. 122 * <p> 123 * This should always be scoped to the installer package that owns the 124 * session. Clients should use {@link SessionInfo#createDetailsIntent()} to 125 * build this intent correctly. 126 * <p> 127 * In some cases, a matching Activity may not exist, so ensure you safeguard 128 * against this. 129 * <p> 130 * The session to show details for is defined in {@link #EXTRA_SESSION_ID}. 131 */ 132 @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) 133 public static final String ACTION_SESSION_DETAILS = "android.content.pm.action.SESSION_DETAILS"; 134 135 /** 136 * Broadcast Action: Explicit broadcast sent to the last known default launcher when a session 137 * for a new install is committed. For managed profile, this is sent to the default launcher 138 * of the primary profile. 139 * <p> 140 * The associated session is defined in {@link #EXTRA_SESSION} and the user for which this 141 * session was created in {@link Intent#EXTRA_USER}. 142 */ 143 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 144 public static final String ACTION_SESSION_COMMITTED = 145 "android.content.pm.action.SESSION_COMMITTED"; 146 147 /** 148 * Broadcast Action: Send information about a staged install session when its state is updated. 149 * <p> 150 * The associated session information is defined in {@link #EXTRA_SESSION}. 151 */ 152 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 153 public static final String ACTION_SESSION_UPDATED = 154 "android.content.pm.action.SESSION_UPDATED"; 155 156 /** {@hide} */ 157 public static final String ACTION_CONFIRM_INSTALL = "android.content.pm.action.CONFIRM_INSTALL"; 158 159 /** 160 * An integer session ID that an operation is working with. 161 * 162 * @see Intent#getIntExtra(String, int) 163 */ 164 public static final String EXTRA_SESSION_ID = "android.content.pm.extra.SESSION_ID"; 165 166 /** 167 * {@link SessionInfo} that an operation is working with. 168 * 169 * @see Intent#getParcelableExtra(String) 170 */ 171 public static final String EXTRA_SESSION = "android.content.pm.extra.SESSION"; 172 173 /** 174 * Package name that an operation is working with. 175 * 176 * @see Intent#getStringExtra(String) 177 */ 178 public static final String EXTRA_PACKAGE_NAME = "android.content.pm.extra.PACKAGE_NAME"; 179 180 /** 181 * Current status of an operation. Will be one of 182 * {@link #STATUS_PENDING_USER_ACTION}, {@link #STATUS_SUCCESS}, 183 * {@link #STATUS_FAILURE}, {@link #STATUS_FAILURE_ABORTED}, 184 * {@link #STATUS_FAILURE_BLOCKED}, {@link #STATUS_FAILURE_CONFLICT}, 185 * {@link #STATUS_FAILURE_INCOMPATIBLE}, {@link #STATUS_FAILURE_INVALID}, or 186 * {@link #STATUS_FAILURE_STORAGE}. 187 * <p> 188 * More information about a status may be available through additional 189 * extras; see the individual status documentation for details. 190 * 191 * @see Intent#getIntExtra(String, int) 192 */ 193 public static final String EXTRA_STATUS = "android.content.pm.extra.STATUS"; 194 195 /** 196 * Detailed string representation of the status, including raw details that 197 * are useful for debugging. 198 * 199 * @see Intent#getStringExtra(String) 200 */ 201 public static final String EXTRA_STATUS_MESSAGE = "android.content.pm.extra.STATUS_MESSAGE"; 202 203 /** 204 * Another package name relevant to a status. This is typically the package 205 * responsible for causing an operation failure. 206 * 207 * @see Intent#getStringExtra(String) 208 */ 209 public static final String 210 EXTRA_OTHER_PACKAGE_NAME = "android.content.pm.extra.OTHER_PACKAGE_NAME"; 211 212 /** 213 * Storage path relevant to a status. 214 * 215 * @see Intent#getStringExtra(String) 216 */ 217 public static final String EXTRA_STORAGE_PATH = "android.content.pm.extra.STORAGE_PATH"; 218 219 /** {@hide} */ 220 @Deprecated 221 public static final String EXTRA_PACKAGE_NAMES = "android.content.pm.extra.PACKAGE_NAMES"; 222 223 /** {@hide} */ 224 public static final String EXTRA_LEGACY_STATUS = "android.content.pm.extra.LEGACY_STATUS"; 225 /** {@hide} */ 226 public static final String EXTRA_LEGACY_BUNDLE = "android.content.pm.extra.LEGACY_BUNDLE"; 227 /** {@hide} */ 228 public static final String EXTRA_CALLBACK = "android.content.pm.extra.CALLBACK"; 229 230 /** 231 * Type of DataLoader for this session. Will be one of 232 * {@link #DATA_LOADER_TYPE_NONE}, {@link #DATA_LOADER_TYPE_STREAMING}, 233 * {@link #DATA_LOADER_TYPE_INCREMENTAL}. 234 * <p> 235 * See the individual types documentation for details. 236 * 237 * @see Intent#getIntExtra(String, int) 238 * {@hide} 239 */ 240 @SystemApi 241 public static final String EXTRA_DATA_LOADER_TYPE = "android.content.pm.extra.DATA_LOADER_TYPE"; 242 243 /** 244 * Streaming installation pending. 245 * Caller should make sure DataLoader is able to prepare image and reinitiate the operation. 246 * 247 * @see #EXTRA_SESSION_ID 248 * {@hide} 249 */ 250 public static final int STATUS_PENDING_STREAMING = -2; 251 252 /** 253 * User action is currently required to proceed. You can launch the intent 254 * activity described by {@link Intent#EXTRA_INTENT} to involve the user and 255 * continue. 256 * <p> 257 * You may choose to immediately launch the intent if the user is actively 258 * using your app. Otherwise, you should use a notification to guide the 259 * user back into your app before launching. 260 * 261 * @see Intent#getParcelableExtra(String) 262 */ 263 public static final int STATUS_PENDING_USER_ACTION = -1; 264 265 /** 266 * The operation succeeded. 267 */ 268 public static final int STATUS_SUCCESS = 0; 269 270 /** 271 * The operation failed in a generic way. The system will always try to 272 * provide a more specific failure reason, but in some rare cases this may 273 * be delivered. 274 * 275 * @see #EXTRA_STATUS_MESSAGE 276 */ 277 public static final int STATUS_FAILURE = 1; 278 279 /** 280 * The operation failed because it was blocked. For example, a device policy 281 * may be blocking the operation, a package verifier may have blocked the 282 * operation, or the app may be required for core system operation. 283 * <p> 284 * The result may also contain {@link #EXTRA_OTHER_PACKAGE_NAME} with the 285 * specific package blocking the install. 286 * 287 * @see #EXTRA_STATUS_MESSAGE 288 * @see #EXTRA_OTHER_PACKAGE_NAME 289 */ 290 public static final int STATUS_FAILURE_BLOCKED = 2; 291 292 /** 293 * The operation failed because it was actively aborted. For example, the 294 * user actively declined requested permissions, or the session was 295 * abandoned. 296 * 297 * @see #EXTRA_STATUS_MESSAGE 298 */ 299 public static final int STATUS_FAILURE_ABORTED = 3; 300 301 /** 302 * The operation failed because one or more of the APKs was invalid. For 303 * example, they might be malformed, corrupt, incorrectly signed, 304 * mismatched, etc. 305 * 306 * @see #EXTRA_STATUS_MESSAGE 307 */ 308 public static final int STATUS_FAILURE_INVALID = 4; 309 310 /** 311 * The operation failed because it conflicts (or is inconsistent with) with 312 * another package already installed on the device. For example, an existing 313 * permission, incompatible certificates, etc. The user may be able to 314 * uninstall another app to fix the issue. 315 * <p> 316 * The result may also contain {@link #EXTRA_OTHER_PACKAGE_NAME} with the 317 * specific package identified as the cause of the conflict. 318 * 319 * @see #EXTRA_STATUS_MESSAGE 320 * @see #EXTRA_OTHER_PACKAGE_NAME 321 */ 322 public static final int STATUS_FAILURE_CONFLICT = 5; 323 324 /** 325 * The operation failed because of storage issues. For example, the device 326 * may be running low on space, or external media may be unavailable. The 327 * user may be able to help free space or insert different external media. 328 * <p> 329 * The result may also contain {@link #EXTRA_STORAGE_PATH} with the path to 330 * the storage device that caused the failure. 331 * 332 * @see #EXTRA_STATUS_MESSAGE 333 * @see #EXTRA_STORAGE_PATH 334 */ 335 public static final int STATUS_FAILURE_STORAGE = 6; 336 337 /** 338 * The operation failed because it is fundamentally incompatible with this 339 * device. For example, the app may require a hardware feature that doesn't 340 * exist, it may be missing native code for the ABIs supported by the 341 * device, or it requires a newer SDK version, etc. 342 * 343 * @see #EXTRA_STATUS_MESSAGE 344 */ 345 public static final int STATUS_FAILURE_INCOMPATIBLE = 7; 346 347 /** 348 * Default value, non-streaming installation session. 349 * 350 * @see #EXTRA_DATA_LOADER_TYPE 351 * {@hide} 352 */ 353 @SystemApi 354 public static final int DATA_LOADER_TYPE_NONE = DataLoaderType.NONE; 355 356 /** 357 * Streaming installation using data loader. 358 * 359 * @see #EXTRA_DATA_LOADER_TYPE 360 * {@hide} 361 */ 362 @SystemApi 363 public static final int DATA_LOADER_TYPE_STREAMING = DataLoaderType.STREAMING; 364 365 /** 366 * Streaming installation using Incremental FileSystem. 367 * 368 * @see #EXTRA_DATA_LOADER_TYPE 369 * {@hide} 370 */ 371 @SystemApi 372 public static final int DATA_LOADER_TYPE_INCREMENTAL = DataLoaderType.INCREMENTAL; 373 374 /** 375 * Target location for the file in installation session is /data/app/<packageName>-<id>. 376 * This is the intended location for APKs. 377 * Requires permission to install packages. 378 * {@hide} 379 */ 380 @SystemApi 381 public static final int LOCATION_DATA_APP = InstallationFileLocation.DATA_APP; 382 383 /** 384 * Target location for the file in installation session is 385 * /data/media/<userid>/Android/obb/<packageName>. This is the intended location for OBBs. 386 * {@hide} 387 */ 388 @SystemApi 389 public static final int LOCATION_MEDIA_OBB = InstallationFileLocation.MEDIA_OBB; 390 391 /** 392 * Target location for the file in installation session is 393 * /data/media/<userid>/Android/data/<packageName>. 394 * This is the intended location for application data. 395 * Can only be used by an app itself running under specific user. 396 * {@hide} 397 */ 398 @SystemApi 399 public static final int LOCATION_MEDIA_DATA = InstallationFileLocation.MEDIA_DATA; 400 401 /** @hide */ 402 @IntDef(prefix = { "LOCATION_" }, value = { 403 LOCATION_DATA_APP, 404 LOCATION_MEDIA_OBB, 405 LOCATION_MEDIA_DATA}) 406 @Retention(RetentionPolicy.SOURCE) 407 public @interface FileLocation{} 408 409 private final IPackageInstaller mInstaller; 410 private final int mUserId; 411 private final String mInstallerPackageName; 412 private final String mAttributionTag; 413 414 private final ArrayList<SessionCallbackDelegate> mDelegates = new ArrayList<>(); 415 416 /** {@hide} */ PackageInstaller(IPackageInstaller installer, String installerPackageName, String installerAttributionTag, int userId)417 public PackageInstaller(IPackageInstaller installer, 418 String installerPackageName, String installerAttributionTag, int userId) { 419 mInstaller = installer; 420 mInstallerPackageName = installerPackageName; 421 mAttributionTag = installerAttributionTag; 422 mUserId = userId; 423 } 424 425 /** 426 * Create a new session using the given parameters, returning a unique ID 427 * that represents the session. Once created, the session can be opened 428 * multiple times across multiple device boots. 429 * <p> 430 * The system may automatically destroy sessions that have not been 431 * finalized (either committed or abandoned) within a reasonable period of 432 * time, typically on the order of a day. 433 * 434 * @throws IOException if parameters were unsatisfiable, such as lack of 435 * disk space or unavailable media. 436 * @throws SecurityException when installation services are unavailable, 437 * such as when called from a restricted user. 438 * @throws IllegalArgumentException when {@link SessionParams} is invalid. 439 * @return positive, non-zero unique ID that represents the created session. 440 * This ID remains consistent across device reboots until the 441 * session is finalized. IDs are not reused during a given boot. 442 */ createSession(@onNull SessionParams params)443 public int createSession(@NonNull SessionParams params) throws IOException { 444 try { 445 return mInstaller.createSession(params, mInstallerPackageName, mAttributionTag, 446 mUserId); 447 } catch (RuntimeException e) { 448 ExceptionUtils.maybeUnwrapIOException(e); 449 throw e; 450 } catch (RemoteException e) { 451 throw e.rethrowFromSystemServer(); 452 } 453 } 454 455 /** 456 * Open an existing session to actively perform work. To succeed, the caller 457 * must be the owner of the install session. 458 * 459 * @throws IOException if parameters were unsatisfiable, such as lack of 460 * disk space or unavailable media. 461 * @throws SecurityException when the caller does not own the session, or 462 * the session is invalid. 463 */ openSession(int sessionId)464 public @NonNull Session openSession(int sessionId) throws IOException { 465 try { 466 try { 467 return new Session(mInstaller.openSession(sessionId)); 468 } catch (RemoteException e) { 469 throw e.rethrowFromSystemServer(); 470 } 471 } catch (RuntimeException e) { 472 ExceptionUtils.maybeUnwrapIOException(e); 473 throw e; 474 } 475 } 476 477 /** 478 * Update the icon representing the app being installed in a specific 479 * session. This should be roughly 480 * {@link ActivityManager#getLauncherLargeIconSize()} in both dimensions. 481 * 482 * @throws SecurityException when the caller does not own the session, or 483 * the session is invalid. 484 */ updateSessionAppIcon(int sessionId, @Nullable Bitmap appIcon)485 public void updateSessionAppIcon(int sessionId, @Nullable Bitmap appIcon) { 486 try { 487 mInstaller.updateSessionAppIcon(sessionId, appIcon); 488 } catch (RemoteException e) { 489 throw e.rethrowFromSystemServer(); 490 } 491 } 492 493 /** 494 * Update the label representing the app being installed in a specific 495 * session. 496 * 497 * @throws SecurityException when the caller does not own the session, or 498 * the session is invalid. 499 */ updateSessionAppLabel(int sessionId, @Nullable CharSequence appLabel)500 public void updateSessionAppLabel(int sessionId, @Nullable CharSequence appLabel) { 501 try { 502 final String val = (appLabel != null) ? appLabel.toString() : null; 503 mInstaller.updateSessionAppLabel(sessionId, val); 504 } catch (RemoteException e) { 505 throw e.rethrowFromSystemServer(); 506 } 507 } 508 509 /** 510 * Completely abandon the given session, destroying all staged data and 511 * rendering it invalid. Abandoned sessions will be reported to 512 * {@link SessionCallback} listeners as failures. This is equivalent to 513 * opening the session and calling {@link Session#abandon()}. 514 * 515 * @throws SecurityException when the caller does not own the session, or 516 * the session is invalid. 517 */ abandonSession(int sessionId)518 public void abandonSession(int sessionId) { 519 try { 520 mInstaller.abandonSession(sessionId); 521 } catch (RemoteException e) { 522 throw e.rethrowFromSystemServer(); 523 } 524 } 525 526 /** 527 * Return details for a specific session. No special permissions are 528 * required to retrieve these details. 529 * 530 * @return details for the requested session, or {@code null} if the session 531 * does not exist. 532 */ getSessionInfo(int sessionId)533 public @Nullable SessionInfo getSessionInfo(int sessionId) { 534 try { 535 return mInstaller.getSessionInfo(sessionId); 536 } catch (RemoteException e) { 537 throw e.rethrowFromSystemServer(); 538 } 539 } 540 541 /** 542 * Return list of all known install sessions, regardless of the installer. 543 */ getAllSessions()544 public @NonNull List<SessionInfo> getAllSessions() { 545 try { 546 return mInstaller.getAllSessions(mUserId).getList(); 547 } catch (RemoteException e) { 548 throw e.rethrowFromSystemServer(); 549 } 550 } 551 552 /** 553 * Return list of all known install sessions owned by the calling app. 554 */ getMySessions()555 public @NonNull List<SessionInfo> getMySessions() { 556 try { 557 return mInstaller.getMySessions(mInstallerPackageName, mUserId).getList(); 558 } catch (RemoteException e) { 559 throw e.rethrowFromSystemServer(); 560 } 561 } 562 563 /** 564 * Return list of all staged install sessions. 565 */ getStagedSessions()566 public @NonNull List<SessionInfo> getStagedSessions() { 567 try { 568 // TODO: limit this to the mUserId? 569 return mInstaller.getStagedSessions().getList(); 570 } catch (RemoteException e) { 571 throw e.rethrowFromSystemServer(); 572 } 573 } 574 575 /** 576 * Returns first active staged session, or {@code null} if there is none. 577 * 578 * <p>For more information on what sessions are considered active see 579 * {@link SessionInfo#isStagedSessionActive()}. 580 * 581 * @deprecated Use {@link #getActiveStagedSessions} as there can be more than one active staged 582 * session 583 */ 584 @Deprecated getActiveStagedSession()585 public @Nullable SessionInfo getActiveStagedSession() { 586 List<SessionInfo> activeSessions = getActiveStagedSessions(); 587 return activeSessions.isEmpty() ? null : activeSessions.get(0); 588 } 589 590 /** 591 * Returns list of active staged sessions. Returns empty list if there is none. 592 * 593 * <p>For more information on what sessions are considered active see 594 * * {@link SessionInfo#isStagedSessionActive()}. 595 */ getActiveStagedSessions()596 public @NonNull List<SessionInfo> getActiveStagedSessions() { 597 final List<SessionInfo> activeStagedSessions = new ArrayList<>(); 598 final List<SessionInfo> stagedSessions = getStagedSessions(); 599 for (int i = 0; i < stagedSessions.size(); i++) { 600 final SessionInfo sessionInfo = stagedSessions.get(i); 601 if (sessionInfo.isStagedSessionActive()) { 602 activeStagedSessions.add(sessionInfo); 603 } 604 } 605 return activeStagedSessions; 606 } 607 608 /** 609 * Uninstall the given package, removing it completely from the device. This 610 * method is available to: 611 * <ul> 612 * <li>the current "installer of record" for the package 613 * <li>the device owner 614 * <li>the affiliated profile owner 615 * </ul> 616 * 617 * @param packageName The package to uninstall. 618 * @param statusReceiver Where to deliver the result. 619 * 620 * @see android.app.admin.DevicePolicyManager 621 */ 622 @RequiresPermission(anyOf = { 623 Manifest.permission.DELETE_PACKAGES, 624 Manifest.permission.REQUEST_DELETE_PACKAGES}) uninstall(@onNull String packageName, @NonNull IntentSender statusReceiver)625 public void uninstall(@NonNull String packageName, @NonNull IntentSender statusReceiver) { 626 uninstall(packageName, 0 /*flags*/, statusReceiver); 627 } 628 629 /** 630 * Uninstall the given package, removing it completely from the device. This 631 * method is only available to the current "installer of record" for the 632 * package. 633 * 634 * @param packageName The package to uninstall. 635 * @param flags Flags for uninstall. 636 * @param statusReceiver Where to deliver the result. 637 * 638 * @hide 639 */ uninstall(@onNull String packageName, @DeleteFlags int flags, @NonNull IntentSender statusReceiver)640 public void uninstall(@NonNull String packageName, @DeleteFlags int flags, 641 @NonNull IntentSender statusReceiver) { 642 uninstall(new VersionedPackage(packageName, PackageManager.VERSION_CODE_HIGHEST), 643 flags, statusReceiver); 644 } 645 646 /** 647 * Uninstall the given package with a specific version code, removing it 648 * completely from the device. If the version code of the package 649 * does not match the one passed in the versioned package argument this 650 * method is a no-op. Use {@link PackageManager#VERSION_CODE_HIGHEST} to 651 * uninstall the latest version of the package. 652 * <p> 653 * This method is available to: 654 * <ul> 655 * <li>the current "installer of record" for the package 656 * <li>the device owner 657 * <li>the affiliated profile owner 658 * </ul> 659 * 660 * @param versionedPackage The versioned package to uninstall. 661 * @param statusReceiver Where to deliver the result. 662 * 663 * @see android.app.admin.DevicePolicyManager 664 */ 665 @RequiresPermission(anyOf = { 666 Manifest.permission.DELETE_PACKAGES, 667 Manifest.permission.REQUEST_DELETE_PACKAGES}) uninstall(@onNull VersionedPackage versionedPackage, @NonNull IntentSender statusReceiver)668 public void uninstall(@NonNull VersionedPackage versionedPackage, 669 @NonNull IntentSender statusReceiver) { 670 uninstall(versionedPackage, 0 /*flags*/, statusReceiver); 671 } 672 673 /** 674 * Uninstall the given package with a specific version code, removing it 675 * completely from the device. This method is only available to the current 676 * "installer of record" for the package. If the version code of the package 677 * does not match the one passed in the versioned package argument this 678 * method is a no-op. Use {@link PackageManager#VERSION_CODE_HIGHEST} to 679 * uninstall the latest version of the package. 680 * 681 * @param versionedPackage The versioned package to uninstall. 682 * @param flags Flags for uninstall. 683 * @param statusReceiver Where to deliver the result. 684 * 685 * @hide 686 */ 687 @RequiresPermission(anyOf = { 688 Manifest.permission.DELETE_PACKAGES, 689 Manifest.permission.REQUEST_DELETE_PACKAGES}) uninstall(@onNull VersionedPackage versionedPackage, @DeleteFlags int flags, @NonNull IntentSender statusReceiver)690 public void uninstall(@NonNull VersionedPackage versionedPackage, @DeleteFlags int flags, 691 @NonNull IntentSender statusReceiver) { 692 Objects.requireNonNull(versionedPackage, "versionedPackage cannot be null"); 693 try { 694 mInstaller.uninstall(versionedPackage, mInstallerPackageName, 695 flags, statusReceiver, mUserId); 696 } catch (RemoteException e) { 697 throw e.rethrowFromSystemServer(); 698 } 699 } 700 701 /** 702 * Install the given package, which already exists on the device, for the user for which this 703 * installer was created. 704 * 705 * <p>This will 706 * {@link PackageInstaller.SessionParams#setWhitelistedRestrictedPermissions(Set) allowlist 707 * all restricted permissions}. 708 * 709 * @param packageName The package to install. 710 * @param installReason Reason for install. 711 * @param statusReceiver Where to deliver the result. 712 */ 713 @RequiresPermission(allOf = { 714 Manifest.permission.INSTALL_PACKAGES, 715 Manifest.permission.INSTALL_EXISTING_PACKAGES}) installExistingPackage(@onNull String packageName, @InstallReason int installReason, @Nullable IntentSender statusReceiver)716 public void installExistingPackage(@NonNull String packageName, 717 @InstallReason int installReason, 718 @Nullable IntentSender statusReceiver) { 719 Objects.requireNonNull(packageName, "packageName cannot be null"); 720 try { 721 mInstaller.installExistingPackage(packageName, 722 PackageManager.INSTALL_ALL_WHITELIST_RESTRICTED_PERMISSIONS, installReason, 723 statusReceiver, mUserId, null); 724 } catch (RemoteException e) { 725 throw e.rethrowFromSystemServer(); 726 } 727 } 728 729 /** 730 * Uninstall the given package for the user for which this installer was created if the package 731 * will still exist for other users on the device. 732 * 733 * @param packageName The package to install. 734 * @param statusReceiver Where to deliver the result. 735 */ 736 @RequiresPermission(Manifest.permission.DELETE_PACKAGES) uninstallExistingPackage(@onNull String packageName, @Nullable IntentSender statusReceiver)737 public void uninstallExistingPackage(@NonNull String packageName, 738 @Nullable IntentSender statusReceiver) { 739 Objects.requireNonNull(packageName, "packageName cannot be null"); 740 try { 741 mInstaller.uninstallExistingPackage( 742 new VersionedPackage(packageName, PackageManager.VERSION_CODE_HIGHEST), 743 mInstallerPackageName, statusReceiver, mUserId); 744 } catch (RemoteException e) { 745 throw e.rethrowFromSystemServer(); 746 } 747 } 748 749 /** {@hide} */ 750 @SystemApi 751 @RequiresPermission(android.Manifest.permission.INSTALL_PACKAGES) setPermissionsResult(int sessionId, boolean accepted)752 public void setPermissionsResult(int sessionId, boolean accepted) { 753 try { 754 mInstaller.setPermissionsResult(sessionId, accepted); 755 } catch (RemoteException e) { 756 throw e.rethrowFromSystemServer(); 757 } 758 } 759 760 /** 761 * Events for observing session lifecycle. 762 * <p> 763 * A typical session lifecycle looks like this: 764 * <ul> 765 * <li>An installer creates a session to indicate pending app delivery. All 766 * install details are available at this point. 767 * <li>The installer opens the session to deliver APK data. Note that a 768 * session may be opened and closed multiple times as network connectivity 769 * changes. The installer may deliver periodic progress updates. 770 * <li>The installer commits or abandons the session, resulting in the 771 * session being finished. 772 * </ul> 773 */ 774 public static abstract class SessionCallback { 775 /** 776 * New session has been created. Details about the session can be 777 * obtained from {@link PackageInstaller#getSessionInfo(int)}. 778 */ onCreated(int sessionId)779 public abstract void onCreated(int sessionId); 780 781 /** 782 * Badging details for an existing session has changed. For example, the 783 * app icon or label has been updated. 784 */ onBadgingChanged(int sessionId)785 public abstract void onBadgingChanged(int sessionId); 786 787 /** 788 * Active state for session has been changed. 789 * <p> 790 * A session is considered active whenever there is ongoing forward 791 * progress being made, such as the installer holding an open 792 * {@link Session} instance while streaming data into place, or the 793 * system optimizing code as the result of 794 * {@link Session#commit(IntentSender)}. 795 * <p> 796 * If the installer closes the {@link Session} without committing, the 797 * session is considered inactive until the installer opens the session 798 * again. 799 */ onActiveChanged(int sessionId, boolean active)800 public abstract void onActiveChanged(int sessionId, boolean active); 801 802 /** 803 * Progress for given session has been updated. 804 * <p> 805 * Note that this progress may not directly correspond to the value 806 * reported by 807 * {@link PackageInstaller.Session#setStagingProgress(float)}, as the 808 * system may carve out a portion of the overall progress to represent 809 * its own internal installation work. 810 */ onProgressChanged(int sessionId, float progress)811 public abstract void onProgressChanged(int sessionId, float progress); 812 813 /** 814 * Session has completely finished, either with success or failure. 815 */ onFinished(int sessionId, boolean success)816 public abstract void onFinished(int sessionId, boolean success); 817 } 818 819 /** {@hide} */ 820 static class SessionCallbackDelegate extends IPackageInstallerCallback.Stub { 821 private static final int MSG_SESSION_CREATED = 1; 822 private static final int MSG_SESSION_BADGING_CHANGED = 2; 823 private static final int MSG_SESSION_ACTIVE_CHANGED = 3; 824 private static final int MSG_SESSION_PROGRESS_CHANGED = 4; 825 private static final int MSG_SESSION_FINISHED = 5; 826 827 final SessionCallback mCallback; 828 final Executor mExecutor; 829 SessionCallbackDelegate(SessionCallback callback, Executor executor)830 SessionCallbackDelegate(SessionCallback callback, Executor executor) { 831 mCallback = callback; 832 mExecutor = executor; 833 } 834 835 @Override onSessionCreated(int sessionId)836 public void onSessionCreated(int sessionId) { 837 mExecutor.execute(PooledLambda.obtainRunnable(SessionCallback::onCreated, mCallback, 838 sessionId).recycleOnUse()); 839 } 840 841 @Override onSessionBadgingChanged(int sessionId)842 public void onSessionBadgingChanged(int sessionId) { 843 mExecutor.execute(PooledLambda.obtainRunnable(SessionCallback::onBadgingChanged, 844 mCallback, sessionId).recycleOnUse()); 845 } 846 847 @Override onSessionActiveChanged(int sessionId, boolean active)848 public void onSessionActiveChanged(int sessionId, boolean active) { 849 mExecutor.execute(PooledLambda.obtainRunnable(SessionCallback::onActiveChanged, 850 mCallback, sessionId, active).recycleOnUse()); 851 } 852 853 @Override onSessionProgressChanged(int sessionId, float progress)854 public void onSessionProgressChanged(int sessionId, float progress) { 855 mExecutor.execute(PooledLambda.obtainRunnable(SessionCallback::onProgressChanged, 856 mCallback, sessionId, progress).recycleOnUse()); 857 } 858 859 @Override onSessionFinished(int sessionId, boolean success)860 public void onSessionFinished(int sessionId, boolean success) { 861 mExecutor.execute(PooledLambda.obtainRunnable(SessionCallback::onFinished, 862 mCallback, sessionId, success).recycleOnUse()); 863 } 864 } 865 866 /** {@hide} */ 867 @Deprecated addSessionCallback(@onNull SessionCallback callback)868 public void addSessionCallback(@NonNull SessionCallback callback) { 869 registerSessionCallback(callback); 870 } 871 872 /** 873 * Register to watch for session lifecycle events. No special permissions 874 * are required to watch for these events. 875 */ registerSessionCallback(@onNull SessionCallback callback)876 public void registerSessionCallback(@NonNull SessionCallback callback) { 877 registerSessionCallback(callback, new Handler()); 878 } 879 880 /** {@hide} */ 881 @Deprecated addSessionCallback(@onNull SessionCallback callback, @NonNull Handler handler)882 public void addSessionCallback(@NonNull SessionCallback callback, @NonNull Handler handler) { 883 registerSessionCallback(callback, handler); 884 } 885 886 /** 887 * Register to watch for session lifecycle events. No special permissions 888 * are required to watch for these events. 889 * 890 * @param handler to dispatch callback events through, otherwise uses 891 * calling thread. 892 */ registerSessionCallback(@onNull SessionCallback callback, @NonNull Handler handler)893 public void registerSessionCallback(@NonNull SessionCallback callback, @NonNull Handler handler) { 894 synchronized (mDelegates) { 895 final SessionCallbackDelegate delegate = new SessionCallbackDelegate(callback, 896 new HandlerExecutor(handler)); 897 try { 898 mInstaller.registerCallback(delegate, mUserId); 899 } catch (RemoteException e) { 900 throw e.rethrowFromSystemServer(); 901 } 902 mDelegates.add(delegate); 903 } 904 } 905 906 /** {@hide} */ 907 @Deprecated removeSessionCallback(@onNull SessionCallback callback)908 public void removeSessionCallback(@NonNull SessionCallback callback) { 909 unregisterSessionCallback(callback); 910 } 911 912 /** 913 * Unregister a previously registered callback. 914 */ unregisterSessionCallback(@onNull SessionCallback callback)915 public void unregisterSessionCallback(@NonNull SessionCallback callback) { 916 synchronized (mDelegates) { 917 for (Iterator<SessionCallbackDelegate> i = mDelegates.iterator(); i.hasNext();) { 918 final SessionCallbackDelegate delegate = i.next(); 919 if (delegate.mCallback == callback) { 920 try { 921 mInstaller.unregisterCallback(delegate); 922 } catch (RemoteException e) { 923 throw e.rethrowFromSystemServer(); 924 } 925 i.remove(); 926 } 927 } 928 } 929 } 930 931 /** 932 * An installation that is being actively staged. For an install to succeed, 933 * all existing and new packages must have identical package names, version 934 * codes, and signing certificates. 935 * <p> 936 * A session may contain any number of split packages. If the application 937 * does not yet exist, this session must include a base package. 938 * <p> 939 * If an APK included in this session is already defined by the existing 940 * installation (for example, the same split name), the APK in this session 941 * will replace the existing APK. 942 * <p> 943 * In such a case that multiple packages need to be committed simultaneously, 944 * multiple sessions can be referenced by a single multi-package session. 945 * This session is created with no package name and calling 946 * {@link SessionParams#setMultiPackage()}. The individual session IDs can be 947 * added with {@link #addChildSessionId(int)} and commit of the multi-package 948 * session will result in all child sessions being committed atomically. 949 */ 950 public static class Session implements Closeable { 951 /** {@hide} */ 952 protected final IPackageInstallerSession mSession; 953 954 /** {@hide} */ Session(IPackageInstallerSession session)955 public Session(IPackageInstallerSession session) { 956 mSession = session; 957 } 958 959 /** {@hide} */ 960 @Deprecated setProgress(float progress)961 public void setProgress(float progress) { 962 setStagingProgress(progress); 963 } 964 965 /** 966 * Set current progress of staging this session. Valid values are 967 * anywhere between 0 and 1. 968 * <p> 969 * Note that this progress may not directly correspond to the value 970 * reported by {@link SessionCallback#onProgressChanged(int, float)}, as 971 * the system may carve out a portion of the overall progress to 972 * represent its own internal installation work. 973 */ setStagingProgress(float progress)974 public void setStagingProgress(float progress) { 975 try { 976 mSession.setClientProgress(progress); 977 } catch (RemoteException e) { 978 throw e.rethrowFromSystemServer(); 979 } 980 } 981 982 /** {@hide} */ 983 @UnsupportedAppUsage addProgress(float progress)984 public void addProgress(float progress) { 985 try { 986 mSession.addClientProgress(progress); 987 } catch (RemoteException e) { 988 throw e.rethrowFromSystemServer(); 989 } 990 } 991 992 /** 993 * Open a stream to write an APK file into the session. 994 * <p> 995 * The returned stream will start writing data at the requested offset 996 * in the underlying file, which can be used to resume a partially 997 * written file. If a valid file length is specified, the system will 998 * preallocate the underlying disk space to optimize placement on disk. 999 * It's strongly recommended to provide a valid file length when known. 1000 * <p> 1001 * You can write data into the returned stream, optionally call 1002 * {@link #fsync(OutputStream)} as needed to ensure bytes have been 1003 * persisted to disk, and then close when finished. All streams must be 1004 * closed before calling {@link #commit(IntentSender)}. 1005 * 1006 * @param name arbitrary, unique name of your choosing to identify the 1007 * APK being written. You can open a file again for 1008 * additional writes (such as after a reboot) by using the 1009 * same name. This name is only meaningful within the context 1010 * of a single install session. 1011 * @param offsetBytes offset into the file to begin writing at, or 0 to 1012 * start at the beginning of the file. 1013 * @param lengthBytes total size of the file being written, used to 1014 * preallocate the underlying disk space, or -1 if unknown. 1015 * The system may clear various caches as needed to allocate 1016 * this space. 1017 * @throws IOException if trouble opening the file for writing, such as 1018 * lack of disk space or unavailable media. 1019 * @throws SecurityException if called after the session has been 1020 * sealed or abandoned 1021 */ openWrite(@onNull String name, long offsetBytes, long lengthBytes)1022 public @NonNull OutputStream openWrite(@NonNull String name, long offsetBytes, 1023 long lengthBytes) throws IOException { 1024 try { 1025 if (ENABLE_REVOCABLE_FD) { 1026 return new ParcelFileDescriptor.AutoCloseOutputStream( 1027 mSession.openWrite(name, offsetBytes, lengthBytes)); 1028 } else { 1029 final ParcelFileDescriptor clientSocket = mSession.openWrite(name, 1030 offsetBytes, lengthBytes); 1031 return new FileBridge.FileBridgeOutputStream(clientSocket); 1032 } 1033 } catch (RuntimeException e) { 1034 ExceptionUtils.maybeUnwrapIOException(e); 1035 throw e; 1036 } catch (RemoteException e) { 1037 throw e.rethrowFromSystemServer(); 1038 } 1039 } 1040 1041 /** {@hide} */ write(@onNull String name, long offsetBytes, long lengthBytes, @NonNull ParcelFileDescriptor fd)1042 public void write(@NonNull String name, long offsetBytes, long lengthBytes, 1043 @NonNull ParcelFileDescriptor fd) throws IOException { 1044 try { 1045 mSession.write(name, offsetBytes, lengthBytes, fd); 1046 } catch (RuntimeException e) { 1047 ExceptionUtils.maybeUnwrapIOException(e); 1048 throw e; 1049 } catch (RemoteException e) { 1050 throw e.rethrowFromSystemServer(); 1051 } 1052 } 1053 1054 /** 1055 * Populate an APK file by creating a hard link to avoid the need to copy. 1056 * <p> 1057 * Note this API is used by RollbackManager only and can only be called from system_server. 1058 * {@code target} will be relabeled if link is created successfully. RollbackManager has 1059 * to delete {@code target} when the session is committed successfully to avoid SELinux 1060 * label conflicts. 1061 * <p> 1062 * Note No more bytes should be written to the file once the link is created successfully. 1063 * 1064 * @param target the path of the link target 1065 * 1066 * @hide 1067 */ stageViaHardLink(String target)1068 public void stageViaHardLink(String target) throws IOException { 1069 try { 1070 mSession.stageViaHardLink(target); 1071 } catch (RuntimeException e) { 1072 ExceptionUtils.maybeUnwrapIOException(e); 1073 throw e; 1074 } catch (RemoteException e) { 1075 throw e.rethrowFromSystemServer(); 1076 } 1077 } 1078 1079 /** 1080 * Ensure that any outstanding data for given stream has been committed 1081 * to disk. This is only valid for streams returned from 1082 * {@link #openWrite(String, long, long)}. 1083 */ fsync(@onNull OutputStream out)1084 public void fsync(@NonNull OutputStream out) throws IOException { 1085 if (ENABLE_REVOCABLE_FD) { 1086 if (out instanceof ParcelFileDescriptor.AutoCloseOutputStream) { 1087 try { 1088 Os.fsync(((ParcelFileDescriptor.AutoCloseOutputStream) out).getFD()); 1089 } catch (ErrnoException e) { 1090 throw e.rethrowAsIOException(); 1091 } 1092 } else { 1093 throw new IllegalArgumentException("Unrecognized stream"); 1094 } 1095 } else { 1096 if (out instanceof FileBridge.FileBridgeOutputStream) { 1097 ((FileBridge.FileBridgeOutputStream) out).fsync(); 1098 } else { 1099 throw new IllegalArgumentException("Unrecognized stream"); 1100 } 1101 } 1102 } 1103 1104 /** 1105 * Return all APK names contained in this session. 1106 * <p> 1107 * This returns all names which have been previously written through 1108 * {@link #openWrite(String, long, long)} as part of this session. 1109 * 1110 * @throws SecurityException if called after the session has been 1111 * committed or abandoned. 1112 */ getNames()1113 public @NonNull String[] getNames() throws IOException { 1114 try { 1115 return mSession.getNames(); 1116 } catch (RuntimeException e) { 1117 ExceptionUtils.maybeUnwrapIOException(e); 1118 throw e; 1119 } catch (RemoteException e) { 1120 throw e.rethrowFromSystemServer(); 1121 } 1122 } 1123 1124 /** 1125 * Open a stream to read an APK file from the session. 1126 * <p> 1127 * This is only valid for names which have been previously written 1128 * through {@link #openWrite(String, long, long)} as part of this 1129 * session. For example, this stream may be used to calculate a 1130 * {@link MessageDigest} of a written APK before committing. 1131 * 1132 * @throws SecurityException if called after the session has been 1133 * committed or abandoned. 1134 */ openRead(@onNull String name)1135 public @NonNull InputStream openRead(@NonNull String name) throws IOException { 1136 try { 1137 final ParcelFileDescriptor pfd = mSession.openRead(name); 1138 return new ParcelFileDescriptor.AutoCloseInputStream(pfd); 1139 } catch (RuntimeException e) { 1140 ExceptionUtils.maybeUnwrapIOException(e); 1141 throw e; 1142 } catch (RemoteException e) { 1143 throw e.rethrowFromSystemServer(); 1144 } 1145 } 1146 1147 /** 1148 * Removes a split. 1149 * <p> 1150 * Split removals occur prior to adding new APKs. If upgrading a feature 1151 * split, it is not expected nor desirable to remove the split prior to 1152 * upgrading. 1153 * <p> 1154 * When split removal is bundled with new APKs, the packageName must be 1155 * identical. 1156 */ removeSplit(@onNull String splitName)1157 public void removeSplit(@NonNull String splitName) throws IOException { 1158 try { 1159 mSession.removeSplit(splitName); 1160 } catch (RuntimeException e) { 1161 ExceptionUtils.maybeUnwrapIOException(e); 1162 throw e; 1163 } catch (RemoteException e) { 1164 throw e.rethrowFromSystemServer(); 1165 } 1166 } 1167 1168 /** 1169 * @return data loader params or null if the session is not using one. 1170 * {@hide} 1171 */ 1172 @SystemApi 1173 @RequiresPermission(android.Manifest.permission.USE_INSTALLER_V2) getDataLoaderParams()1174 public @Nullable DataLoaderParams getDataLoaderParams() { 1175 try { 1176 DataLoaderParamsParcel data = mSession.getDataLoaderParams(); 1177 if (data == null) { 1178 return null; 1179 } 1180 return new DataLoaderParams(data); 1181 } catch (RemoteException e) { 1182 throw e.rethrowFromSystemServer(); 1183 } 1184 } 1185 1186 /** 1187 * Adds a file to session. On commit this file will be pulled from DataLoader {@code 1188 * android.service.dataloader.DataLoaderService.DataLoader}. 1189 * 1190 * @param location target location for the file. Possible values: 1191 * {@link #LOCATION_DATA_APP}, 1192 * {@link #LOCATION_MEDIA_OBB}, 1193 * {@link #LOCATION_MEDIA_DATA}. 1194 * @param name arbitrary, unique name of your choosing to identify the 1195 * APK being written. You can open a file again for 1196 * additional writes (such as after a reboot) by using the 1197 * same name. This name is only meaningful within the context 1198 * of a single install session. 1199 * @param lengthBytes total size of the file being written. 1200 * The system may clear various caches as needed to allocate 1201 * this space. 1202 * @param metadata additional info use by DataLoader to pull data for the file. 1203 * @param signature additional file signature, e.g. 1204 * <a href="https://source.android.com/security/apksigning/v4.html">APK Signature Scheme v4</a> 1205 * @throws SecurityException if called after the session has been 1206 * sealed or abandoned 1207 * @throws IllegalStateException if called for non-streaming session 1208 * 1209 * @see android.content.pm.InstallationFile 1210 * 1211 * {@hide} 1212 */ 1213 @SystemApi 1214 @RequiresPermission(android.Manifest.permission.USE_INSTALLER_V2) addFile(@ileLocation int location, @NonNull String name, long lengthBytes, @NonNull byte[] metadata, @Nullable byte[] signature)1215 public void addFile(@FileLocation int location, @NonNull String name, long lengthBytes, 1216 @NonNull byte[] metadata, @Nullable byte[] signature) { 1217 try { 1218 mSession.addFile(location, name, lengthBytes, metadata, signature); 1219 } catch (RemoteException e) { 1220 throw e.rethrowFromSystemServer(); 1221 } 1222 } 1223 1224 /** 1225 * Removes a file. 1226 * 1227 * @param location target location for the file. Possible values: 1228 * {@link #LOCATION_DATA_APP}, 1229 * {@link #LOCATION_MEDIA_OBB}, 1230 * {@link #LOCATION_MEDIA_DATA}. 1231 * @param name name of a file, e.g. split. 1232 * @throws SecurityException if called after the session has been 1233 * sealed or abandoned 1234 * @throws IllegalStateException if called for non-DataLoader session 1235 * {@hide} 1236 */ 1237 @SystemApi 1238 @RequiresPermission(android.Manifest.permission.USE_INSTALLER_V2) removeFile(@ileLocation int location, @NonNull String name)1239 public void removeFile(@FileLocation int location, @NonNull String name) { 1240 try { 1241 mSession.removeFile(location, name); 1242 } catch (RemoteException e) { 1243 throw e.rethrowFromSystemServer(); 1244 } 1245 } 1246 1247 /** 1248 * Sets installer-provided checksums for the APK file in session. 1249 * 1250 * @param name previously written as part of this session. 1251 * {@link #openWrite} 1252 * @param checksums installer intends to make available via 1253 * {@link PackageManager#requestChecksums}. 1254 * @param signature DER PKCS#7 detached signature bytes over binary serialized checksums 1255 * to enable integrity checking for the checksums or null for no integrity 1256 * checking. {@link PackageManager#requestChecksums} will return 1257 * the certificate used to create signature. 1258 * Binary format for checksums: 1259 * <pre>{@code DataOutputStream dos; 1260 * dos.writeInt(checksum.getType()); 1261 * dos.writeInt(checksum.getValue().length); 1262 * dos.write(checksum.getValue());}</pre> 1263 * If using <b>openssl cms</b>, make sure to specify -binary -nosmimecap. 1264 * @see <a href="https://www.openssl.org/docs/man1.0.2/man1/cms.html">openssl cms</a> 1265 * @throws SecurityException if called after the session has been 1266 * committed or abandoned. 1267 * @throws IllegalStateException if checksums for this file have already been added. 1268 * @deprecated do not use installer-provided checksums, 1269 * use platform-enforced checksums 1270 * e.g. {@link Checksum#TYPE_WHOLE_MERKLE_ROOT_4K_SHA256} 1271 * in {@link PackageManager#requestChecksums}. 1272 */ 1273 @Deprecated setChecksums(@onNull String name, @NonNull List<Checksum> checksums, @Nullable byte[] signature)1274 public void setChecksums(@NonNull String name, @NonNull List<Checksum> checksums, 1275 @Nullable byte[] signature) throws IOException { 1276 Objects.requireNonNull(name); 1277 Objects.requireNonNull(checksums); 1278 1279 try { 1280 mSession.setChecksums(name, checksums.toArray(new Checksum[checksums.size()]), 1281 signature); 1282 } catch (RuntimeException e) { 1283 ExceptionUtils.maybeUnwrapIOException(e); 1284 throw e; 1285 } catch (RemoteException e) { 1286 throw e.rethrowFromSystemServer(); 1287 } 1288 } 1289 1290 /** 1291 * Attempt to commit everything staged in this session. This may require 1292 * user intervention, and so it may not happen immediately. The final 1293 * result of the commit will be reported through the given callback. 1294 * <p> 1295 * Once this method is called, the session is sealed and no additional mutations may be 1296 * performed on the session. In case of device reboot or data loader transient failure 1297 * before the session has been finalized, you may commit the session again. 1298 * <p> 1299 * If the installer is the device owner or the affiliated profile owner, there will be no 1300 * user intervention. 1301 * 1302 * @param statusReceiver Called when the state of the session changes. Intents 1303 * sent to this receiver contain {@link #EXTRA_STATUS}. Refer to the 1304 * individual status codes on how to handle them. 1305 * 1306 * @throws SecurityException if streams opened through 1307 * {@link #openWrite(String, long, long)} are still open. 1308 * 1309 * @see android.app.admin.DevicePolicyManager 1310 */ commit(@onNull IntentSender statusReceiver)1311 public void commit(@NonNull IntentSender statusReceiver) { 1312 try { 1313 mSession.commit(statusReceiver, false); 1314 } catch (RemoteException e) { 1315 throw e.rethrowFromSystemServer(); 1316 } 1317 } 1318 1319 /** 1320 * Attempt to commit a session that has been {@link #transfer(String) transferred}. 1321 * 1322 * <p>If the device reboots before the session has been finalized, you may commit the 1323 * session again. 1324 * 1325 * <p>The caller of this method is responsible to ensure the safety of the session. As the 1326 * session was created by another - usually less trusted - app, it is paramount that before 1327 * committing <u>all</u> public and system {@link SessionInfo properties of the session} 1328 * and <u>all</u> {@link #openRead(String) APKs} are verified by the caller. It might happen 1329 * that new properties are added to the session with a new API revision. In this case the 1330 * callers need to be updated. 1331 * 1332 * @param statusReceiver Called when the state of the session changes. Intents 1333 * sent to this receiver contain {@link #EXTRA_STATUS}. Refer to the 1334 * individual status codes on how to handle them. 1335 * 1336 * @hide 1337 */ 1338 @SystemApi 1339 @RequiresPermission(android.Manifest.permission.INSTALL_PACKAGES) commitTransferred(@onNull IntentSender statusReceiver)1340 public void commitTransferred(@NonNull IntentSender statusReceiver) { 1341 try { 1342 mSession.commit(statusReceiver, true); 1343 } catch (RemoteException e) { 1344 throw e.rethrowFromSystemServer(); 1345 } 1346 } 1347 1348 /** 1349 * Transfer the session to a new owner. 1350 * <p> 1351 * Only sessions that update the installing app can be transferred. 1352 * <p> 1353 * After the transfer to a package with a different uid all method calls on the session 1354 * will cause {@link SecurityException}s. 1355 * <p> 1356 * Once this method is called, the session is sealed and no additional mutations beside 1357 * committing it may be performed on the session. 1358 * 1359 * @param packageName The package of the new owner. Needs to hold the INSTALL_PACKAGES 1360 * permission. 1361 * 1362 * @throws PackageManager.NameNotFoundException if the new owner could not be found. 1363 * @throws SecurityException if called after the session has been committed or abandoned. 1364 * @throws IllegalStateException if streams opened through 1365 * {@link #openWrite(String, long, long) are still open. 1366 * @throws IllegalArgumentException if {@code packageName} is invalid. 1367 */ transfer(@onNull String packageName)1368 public void transfer(@NonNull String packageName) 1369 throws PackageManager.NameNotFoundException { 1370 Preconditions.checkArgument(!TextUtils.isEmpty(packageName)); 1371 1372 try { 1373 mSession.transfer(packageName); 1374 } catch (ParcelableException e) { 1375 e.maybeRethrow(PackageManager.NameNotFoundException.class); 1376 throw new RuntimeException(e); 1377 } catch (RemoteException e) { 1378 throw e.rethrowFromSystemServer(); 1379 } 1380 } 1381 1382 /** 1383 * Release this session object. You can open the session again if it 1384 * hasn't been finalized. 1385 */ 1386 @Override close()1387 public void close() { 1388 try { 1389 mSession.close(); 1390 } catch (RemoteException e) { 1391 throw e.rethrowFromSystemServer(); 1392 } 1393 } 1394 1395 /** 1396 * Completely abandon this session, destroying all staged data and 1397 * rendering it invalid. Abandoned sessions will be reported to 1398 * {@link SessionCallback} listeners as failures. This is equivalent to 1399 * {@link #abandonSession(int)}. 1400 * <p>If the parent is abandoned, all children will also be abandoned. Any written data 1401 * would be destroyed and the created {@link Session} information will be discarded.</p> 1402 */ abandon()1403 public void abandon() { 1404 try { 1405 mSession.abandon(); 1406 } catch (RemoteException e) { 1407 throw e.rethrowFromSystemServer(); 1408 } 1409 } 1410 1411 /** 1412 * @return {@code true} if this session will commit more than one package when it is 1413 * committed. 1414 */ isMultiPackage()1415 public boolean isMultiPackage() { 1416 try { 1417 return mSession.isMultiPackage(); 1418 } catch (RemoteException e) { 1419 throw e.rethrowFromSystemServer(); 1420 } 1421 } 1422 1423 /** 1424 * @return {@code true} if this session will be staged and applied at next reboot. 1425 */ isStaged()1426 public boolean isStaged() { 1427 try { 1428 return mSession.isStaged(); 1429 } catch (RemoteException e) { 1430 throw e.rethrowFromSystemServer(); 1431 } 1432 } 1433 1434 /** 1435 * @return Session's {@link SessionParams#installFlags}. 1436 * @hide 1437 */ getInstallFlags()1438 public int getInstallFlags() { 1439 try { 1440 return mSession.getInstallFlags(); 1441 } catch (RemoteException e) { 1442 throw e.rethrowFromSystemServer(); 1443 } 1444 } 1445 1446 /** 1447 * @return the session ID of the multi-package session that this belongs to or 1448 * {@link SessionInfo#INVALID_ID} if it does not belong to a multi-package session. 1449 */ getParentSessionId()1450 public int getParentSessionId() { 1451 try { 1452 return mSession.getParentSessionId(); 1453 } catch (RemoteException e) { 1454 throw e.rethrowFromSystemServer(); 1455 } 1456 } 1457 1458 /** 1459 * @return the set of session IDs that will be committed atomically when this session is 1460 * committed if this is a multi-package session or null if none exist. 1461 */ 1462 @NonNull getChildSessionIds()1463 public int[] getChildSessionIds() { 1464 try { 1465 return mSession.getChildSessionIds(); 1466 } catch (RemoteException e) { 1467 throw e.rethrowFromSystemServer(); 1468 } 1469 } 1470 1471 /** 1472 * Adds a session ID to the set of sessions that will be committed atomically 1473 * when this session is committed. 1474 * 1475 * <p>If the parent is staged or has rollback enabled, all children must have 1476 * the same properties.</p> 1477 * <p>If the parent is abandoned, all children will also be abandoned.</p> 1478 * 1479 * @param sessionId the session ID to add to this multi-package session. 1480 */ addChildSessionId(int sessionId)1481 public void addChildSessionId(int sessionId) { 1482 try { 1483 mSession.addChildSessionId(sessionId); 1484 } catch (RemoteException e) { 1485 e.rethrowFromSystemServer(); 1486 } 1487 } 1488 1489 /** 1490 * Removes a session ID from the set of sessions that will be committed 1491 * atomically when this session is committed. 1492 * 1493 * @param sessionId the session ID to remove from this multi-package session. 1494 */ removeChildSessionId(int sessionId)1495 public void removeChildSessionId(int sessionId) { 1496 try { 1497 mSession.removeChildSessionId(sessionId); 1498 } catch (RemoteException e) { 1499 e.rethrowFromSystemServer(); 1500 } 1501 } 1502 } 1503 1504 /** 1505 * Parameters for creating a new {@link PackageInstaller.Session}. 1506 */ 1507 public static class SessionParams implements Parcelable { 1508 1509 /** {@hide} */ 1510 public static final int MODE_INVALID = -1; 1511 1512 /** 1513 * Mode for an install session whose staged APKs should fully replace any 1514 * existing APKs for the target app. 1515 */ 1516 public static final int MODE_FULL_INSTALL = 1; 1517 1518 /** 1519 * Mode for an install session that should inherit any existing APKs for the 1520 * target app, unless they have been explicitly overridden (based on split 1521 * name) by the session. For example, this can be used to add one or more 1522 * split APKs to an existing installation. 1523 * <p> 1524 * If there are no existing APKs for the target app, this behaves like 1525 * {@link #MODE_FULL_INSTALL}. 1526 */ 1527 public static final int MODE_INHERIT_EXISTING = 2; 1528 1529 /** 1530 * Special constant to refer to all restricted permissions. 1531 */ 1532 public static final @NonNull Set<String> RESTRICTED_PERMISSIONS_ALL = new ArraySet<>(); 1533 1534 /** {@hide} */ 1535 public static final int UID_UNKNOWN = -1; 1536 1537 /** 1538 * This value is derived from the maximum file name length. No package above this limit 1539 * can ever be successfully installed on the device. 1540 * @hide 1541 */ 1542 public static final int MAX_PACKAGE_NAME_LENGTH = 255; 1543 1544 /** @hide */ 1545 @IntDef(prefix = {"USER_ACTION_"}, value = { 1546 USER_ACTION_UNSPECIFIED, 1547 USER_ACTION_REQUIRED, 1548 USER_ACTION_NOT_REQUIRED 1549 }) 1550 @Retention(RetentionPolicy.SOURCE) 1551 public @interface UserActionRequirement {} 1552 1553 /** 1554 * The installer did not call {@link SessionParams#setRequireUserAction(int)} to 1555 * specify whether user action should be required for the install. 1556 */ 1557 public static final int USER_ACTION_UNSPECIFIED = 0; 1558 1559 /** 1560 * The installer called {@link SessionParams#setRequireUserAction(int)} with 1561 * {@code true} to require user action for the install to complete. 1562 */ 1563 public static final int USER_ACTION_REQUIRED = 1; 1564 1565 /** 1566 * The installer called {@link SessionParams#setRequireUserAction(int)} with 1567 * {@code false} to request that user action not be required for this install. 1568 */ 1569 public static final int USER_ACTION_NOT_REQUIRED = 2; 1570 1571 /** {@hide} */ 1572 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) 1573 public int mode = MODE_INVALID; 1574 /** {@hide} */ 1575 @UnsupportedAppUsage 1576 public int installFlags = PackageManager.INSTALL_ALL_WHITELIST_RESTRICTED_PERMISSIONS; 1577 /** {@hide} */ 1578 public int installLocation = PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY; 1579 /** {@hide} */ 1580 public @InstallReason int installReason = PackageManager.INSTALL_REASON_UNKNOWN; 1581 /** 1582 * {@hide} 1583 * 1584 * This flag indicates which installation scenario best describes this session. The system 1585 * may use this value when making decisions about how to handle the installation, such as 1586 * prioritizing system health or user experience. 1587 */ 1588 public @InstallScenario int installScenario = PackageManager.INSTALL_SCENARIO_DEFAULT; 1589 /** {@hide} */ 1590 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 1591 public long sizeBytes = -1; 1592 /** {@hide} */ 1593 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) 1594 public String appPackageName; 1595 /** {@hide} */ 1596 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 1597 public Bitmap appIcon; 1598 /** {@hide} */ 1599 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) 1600 public String appLabel; 1601 /** {@hide} */ 1602 public long appIconLastModified = -1; 1603 /** {@hide} */ 1604 public Uri originatingUri; 1605 /** {@hide} */ 1606 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 1607 public int originatingUid = UID_UNKNOWN; 1608 /** {@hide} */ 1609 public Uri referrerUri; 1610 /** {@hide} */ 1611 public String abiOverride; 1612 /** {@hide} */ 1613 public String volumeUuid; 1614 /** {@hide} */ 1615 public String[] grantedRuntimePermissions; 1616 /** {@hide} */ 1617 public List<String> whitelistedRestrictedPermissions; 1618 /** {@hide} */ 1619 public int autoRevokePermissionsMode = MODE_DEFAULT; 1620 /** {@hide} */ 1621 public String installerPackageName; 1622 /** {@hide} */ 1623 public boolean isMultiPackage; 1624 /** {@hide} */ 1625 public boolean isStaged; 1626 /** {@hide} */ 1627 public long requiredInstalledVersionCode = PackageManager.VERSION_CODE_HIGHEST; 1628 /** {@hide} */ 1629 public DataLoaderParams dataLoaderParams; 1630 /** {@hide} */ 1631 public int rollbackDataPolicy = PackageManager.RollbackDataPolicy.RESTORE; 1632 /** {@hide} */ 1633 public boolean forceQueryableOverride; 1634 /** {@hide} */ 1635 public int requireUserAction = USER_ACTION_UNSPECIFIED; 1636 1637 /** 1638 * Construct parameters for a new package install session. 1639 * 1640 * @param mode one of {@link #MODE_FULL_INSTALL} or 1641 * {@link #MODE_INHERIT_EXISTING} describing how the session 1642 * should interact with an existing app. 1643 */ SessionParams(int mode)1644 public SessionParams(int mode) { 1645 this.mode = mode; 1646 } 1647 1648 /** {@hide} */ SessionParams(Parcel source)1649 public SessionParams(Parcel source) { 1650 mode = source.readInt(); 1651 installFlags = source.readInt(); 1652 installLocation = source.readInt(); 1653 installReason = source.readInt(); 1654 installScenario = source.readInt(); 1655 sizeBytes = source.readLong(); 1656 appPackageName = source.readString(); 1657 appIcon = source.readParcelable(null); 1658 appLabel = source.readString(); 1659 originatingUri = source.readParcelable(null); 1660 originatingUid = source.readInt(); 1661 referrerUri = source.readParcelable(null); 1662 abiOverride = source.readString(); 1663 volumeUuid = source.readString(); 1664 grantedRuntimePermissions = source.readStringArray(); 1665 whitelistedRestrictedPermissions = source.createStringArrayList(); 1666 autoRevokePermissionsMode = source.readInt(); 1667 installerPackageName = source.readString(); 1668 isMultiPackage = source.readBoolean(); 1669 isStaged = source.readBoolean(); 1670 forceQueryableOverride = source.readBoolean(); 1671 requiredInstalledVersionCode = source.readLong(); 1672 DataLoaderParamsParcel dataLoaderParamsParcel = source.readParcelable( 1673 DataLoaderParamsParcel.class.getClassLoader()); 1674 if (dataLoaderParamsParcel != null) { 1675 dataLoaderParams = new DataLoaderParams(dataLoaderParamsParcel); 1676 } 1677 rollbackDataPolicy = source.readInt(); 1678 requireUserAction = source.readInt(); 1679 } 1680 1681 /** {@hide} */ copy()1682 public SessionParams copy() { 1683 SessionParams ret = new SessionParams(mode); 1684 ret.installFlags = installFlags; 1685 ret.installLocation = installLocation; 1686 ret.installReason = installReason; 1687 ret.installScenario = installScenario; 1688 ret.sizeBytes = sizeBytes; 1689 ret.appPackageName = appPackageName; 1690 ret.appIcon = appIcon; // not a copy. 1691 ret.appLabel = appLabel; 1692 ret.originatingUri = originatingUri; // not a copy, but immutable. 1693 ret.originatingUid = originatingUid; 1694 ret.referrerUri = referrerUri; // not a copy, but immutable. 1695 ret.abiOverride = abiOverride; 1696 ret.volumeUuid = volumeUuid; 1697 ret.grantedRuntimePermissions = grantedRuntimePermissions; 1698 ret.whitelistedRestrictedPermissions = whitelistedRestrictedPermissions; 1699 ret.autoRevokePermissionsMode = autoRevokePermissionsMode; 1700 ret.installerPackageName = installerPackageName; 1701 ret.isMultiPackage = isMultiPackage; 1702 ret.isStaged = isStaged; 1703 ret.forceQueryableOverride = forceQueryableOverride; 1704 ret.requiredInstalledVersionCode = requiredInstalledVersionCode; 1705 ret.dataLoaderParams = dataLoaderParams; 1706 ret.rollbackDataPolicy = rollbackDataPolicy; 1707 ret.requireUserAction = requireUserAction; 1708 return ret; 1709 } 1710 1711 /** 1712 * Check if there are hidden options set. 1713 * 1714 * <p>Hidden options are those options that cannot be verified via public or system-api 1715 * methods on {@link SessionInfo}. 1716 * 1717 * @return {@code true} if any hidden option is set. 1718 * 1719 * @hide 1720 */ areHiddenOptionsSet()1721 public boolean areHiddenOptionsSet() { 1722 return (installFlags & (PackageManager.INSTALL_REQUEST_DOWNGRADE 1723 | PackageManager.INSTALL_ALLOW_DOWNGRADE 1724 | PackageManager.INSTALL_DONT_KILL_APP 1725 | PackageManager.INSTALL_INSTANT_APP 1726 | PackageManager.INSTALL_FULL_APP 1727 | PackageManager.INSTALL_VIRTUAL_PRELOAD 1728 | PackageManager.INSTALL_ALLOCATE_AGGRESSIVE)) != installFlags 1729 || abiOverride != null || volumeUuid != null; 1730 } 1731 1732 /** 1733 * Provide value of {@link PackageInfo#installLocation}, which may be used 1734 * to determine where the app will be staged. Defaults to 1735 * {@link PackageInfo#INSTALL_LOCATION_INTERNAL_ONLY}. 1736 */ setInstallLocation(int installLocation)1737 public void setInstallLocation(int installLocation) { 1738 this.installLocation = installLocation; 1739 } 1740 1741 /** 1742 * Optionally indicate the total size (in bytes) of all APKs that will be 1743 * delivered in this session. The system may use this to ensure enough disk 1744 * space exists before proceeding, or to estimate container size for 1745 * installations living on external storage. 1746 * 1747 * @see PackageInfo#INSTALL_LOCATION_AUTO 1748 * @see PackageInfo#INSTALL_LOCATION_PREFER_EXTERNAL 1749 */ setSize(long sizeBytes)1750 public void setSize(long sizeBytes) { 1751 this.sizeBytes = sizeBytes; 1752 } 1753 1754 /** 1755 * Optionally set the package name of the app being installed. It's strongly 1756 * recommended that you provide this value when known, so that observers can 1757 * communicate installing apps to users. 1758 * <p> 1759 * If the APKs staged in the session aren't consistent with this package 1760 * name, the install will fail. Regardless of this value, all APKs in the 1761 * app must have the same package name. 1762 */ setAppPackageName(@ullable String appPackageName)1763 public void setAppPackageName(@Nullable String appPackageName) { 1764 this.appPackageName = appPackageName; 1765 } 1766 1767 /** 1768 * Optionally set an icon representing the app being installed. This should 1769 * be roughly {@link ActivityManager#getLauncherLargeIconSize()} in both 1770 * dimensions. 1771 */ setAppIcon(@ullable Bitmap appIcon)1772 public void setAppIcon(@Nullable Bitmap appIcon) { 1773 this.appIcon = appIcon; 1774 } 1775 1776 /** 1777 * Optionally set a label representing the app being installed. 1778 * 1779 * This value will be trimmed to the first 1000 characters. 1780 */ setAppLabel(@ullable CharSequence appLabel)1781 public void setAppLabel(@Nullable CharSequence appLabel) { 1782 this.appLabel = (appLabel != null) ? appLabel.toString() : null; 1783 } 1784 1785 /** 1786 * Optionally set the URI where this package was downloaded from. This is 1787 * informational and may be used as a signal for anti-malware purposes. 1788 * 1789 * @see Intent#EXTRA_ORIGINATING_URI 1790 */ setOriginatingUri(@ullable Uri originatingUri)1791 public void setOriginatingUri(@Nullable Uri originatingUri) { 1792 this.originatingUri = originatingUri; 1793 } 1794 1795 /** 1796 * Sets the UID that initiated the package installation. This is informational 1797 * and may be used as a signal for anti-malware purposes. 1798 */ setOriginatingUid(int originatingUid)1799 public void setOriginatingUid(int originatingUid) { 1800 this.originatingUid = originatingUid; 1801 } 1802 1803 /** 1804 * Optionally set the URI that referred you to install this package. This is 1805 * informational and may be used as a signal for anti-malware purposes. 1806 * 1807 * @see Intent#EXTRA_REFERRER 1808 */ setReferrerUri(@ullable Uri referrerUri)1809 public void setReferrerUri(@Nullable Uri referrerUri) { 1810 this.referrerUri = referrerUri; 1811 } 1812 1813 /** 1814 * Sets which runtime permissions to be granted to the package at installation. 1815 * 1816 * @param permissions The permissions to grant or null to grant all runtime 1817 * permissions. 1818 * 1819 * @hide 1820 */ 1821 @SystemApi 1822 @RequiresPermission(android.Manifest.permission.INSTALL_GRANT_RUNTIME_PERMISSIONS) setGrantedRuntimePermissions(String[] permissions)1823 public void setGrantedRuntimePermissions(String[] permissions) { 1824 installFlags |= PackageManager.INSTALL_GRANT_RUNTIME_PERMISSIONS; 1825 this.grantedRuntimePermissions = permissions; 1826 } 1827 1828 /** 1829 * Sets which restricted permissions to be allowlisted for the app. Allowlisting 1830 * is not granting the permissions, rather it allows the app to hold permissions 1831 * which are otherwise restricted. Allowlisting a non restricted permission has 1832 * no effect. 1833 * 1834 * <p> Permissions can be hard restricted which means that the app cannot hold 1835 * them or soft restricted where the app can hold the permission but in a weaker 1836 * form. Whether a permission is {@link PermissionInfo#FLAG_HARD_RESTRICTED hard 1837 * restricted} or {@link PermissionInfo#FLAG_SOFT_RESTRICTED soft restricted} 1838 * depends on the permission declaration. Allowlisting a hard restricted permission 1839 * allows the app to hold that permission and allowlisting a soft restricted 1840 * permission allows the app to hold the permission in its full, unrestricted form. 1841 * 1842 * <p> Permissions can also be immutably restricted which means that the allowlist 1843 * state of the permission can be determined only at install time and cannot be 1844 * changed on updated or at a later point via the package manager APIs. 1845 * 1846 * <p>Initially, all restricted permissions are allowlisted but you can change 1847 * which ones are allowlisted by calling this method or the corresponding ones 1848 * on the {@link PackageManager}. Only soft or hard restricted permissions on the current 1849 * Android version are supported and any invalid entries will be removed. 1850 * 1851 * @see PackageManager#addWhitelistedRestrictedPermission(String, String, int) 1852 * @see PackageManager#removeWhitelistedRestrictedPermission(String, String, int) 1853 */ setWhitelistedRestrictedPermissions(@ullable Set<String> permissions)1854 public void setWhitelistedRestrictedPermissions(@Nullable Set<String> permissions) { 1855 if (permissions == RESTRICTED_PERMISSIONS_ALL) { 1856 installFlags |= PackageManager.INSTALL_ALL_WHITELIST_RESTRICTED_PERMISSIONS; 1857 whitelistedRestrictedPermissions = null; 1858 } else { 1859 installFlags &= ~PackageManager.INSTALL_ALL_WHITELIST_RESTRICTED_PERMISSIONS; 1860 whitelistedRestrictedPermissions = (permissions != null) 1861 ? new ArrayList<>(permissions) : null; 1862 } 1863 } 1864 1865 /** 1866 * Sets whether permissions should be auto-revoked if this package is unused for an 1867 * extended periodd of time. 1868 * 1869 * It's disabled by default but generally the installer should enable it for most packages, 1870 * excluding only those where doing so might cause breakage that cannot be easily addressed 1871 * by simply re-requesting the permission(s). 1872 * 1873 * If user explicitly enabled or disabled it via settings, this call is ignored. 1874 * 1875 * @param shouldAutoRevoke whether permissions should be auto-revoked. 1876 * 1877 * @deprecated No longer used 1878 */ 1879 @Deprecated setAutoRevokePermissionsMode(boolean shouldAutoRevoke)1880 public void setAutoRevokePermissionsMode(boolean shouldAutoRevoke) { 1881 autoRevokePermissionsMode = shouldAutoRevoke ? MODE_ALLOWED : MODE_IGNORED; 1882 } 1883 1884 /** 1885 * Request that rollbacks be enabled or disabled for the given upgrade with rollback data 1886 * policy set to RESTORE. 1887 * 1888 * <p>If the parent session is staged or has rollback enabled, all children sessions 1889 * must have the same properties. 1890 * 1891 * @param enable set to {@code true} to enable, {@code false} to disable 1892 * @see SessionParams#setEnableRollback(boolean, int) 1893 * @hide 1894 */ 1895 @SystemApi setEnableRollback(boolean enable)1896 public void setEnableRollback(boolean enable) { 1897 if (enable) { 1898 installFlags |= PackageManager.INSTALL_ENABLE_ROLLBACK; 1899 } else { 1900 installFlags &= ~PackageManager.INSTALL_ENABLE_ROLLBACK; 1901 } 1902 rollbackDataPolicy = PackageManager.RollbackDataPolicy.RESTORE; 1903 } 1904 1905 /** 1906 * Request that rollbacks be enabled or disabled for the given upgrade. 1907 * 1908 * <p>If the parent session is staged or has rollback enabled, all children sessions 1909 * must have the same properties. 1910 * 1911 * <p> For a multi-package install, this method must be called on each child session to 1912 * specify rollback data policies explicitly. Note each child session is allowed to have 1913 * different policies. 1914 * 1915 * @param enable set to {@code true} to enable, {@code false} to disable 1916 * @param dataPolicy the rollback data policy for this session 1917 * @hide 1918 */ 1919 @SystemApi setEnableRollback(boolean enable, @PackageManager.RollbackDataPolicy int dataPolicy)1920 public void setEnableRollback(boolean enable, 1921 @PackageManager.RollbackDataPolicy int dataPolicy) { 1922 if (enable) { 1923 installFlags |= PackageManager.INSTALL_ENABLE_ROLLBACK; 1924 } else { 1925 installFlags &= ~PackageManager.INSTALL_ENABLE_ROLLBACK; 1926 } 1927 rollbackDataPolicy = dataPolicy; 1928 } 1929 1930 1931 /** 1932 * @deprecated use {@link #setRequestDowngrade(boolean)}. 1933 * {@hide} 1934 */ 1935 @SystemApi 1936 @Deprecated setAllowDowngrade(boolean allowDowngrade)1937 public void setAllowDowngrade(boolean allowDowngrade) { 1938 setRequestDowngrade(allowDowngrade); 1939 } 1940 1941 /** {@hide} */ 1942 @SystemApi setRequestDowngrade(boolean requestDowngrade)1943 public void setRequestDowngrade(boolean requestDowngrade) { 1944 if (requestDowngrade) { 1945 installFlags |= PackageManager.INSTALL_REQUEST_DOWNGRADE; 1946 } else { 1947 installFlags &= ~PackageManager.INSTALL_REQUEST_DOWNGRADE; 1948 } 1949 } 1950 1951 /** 1952 * Require the given version of the package be installed. 1953 * The install will only be allowed if the existing version code of 1954 * the package installed on the device matches the given version code. 1955 * Use {@link * PackageManager#VERSION_CODE_HIGHEST} to allow 1956 * installation regardless of the currently installed package version. 1957 * 1958 * @hide 1959 */ setRequiredInstalledVersionCode(long versionCode)1960 public void setRequiredInstalledVersionCode(long versionCode) { 1961 requiredInstalledVersionCode = versionCode; 1962 } 1963 1964 /** {@hide} */ setInstallFlagsForcePermissionPrompt()1965 public void setInstallFlagsForcePermissionPrompt() { 1966 installFlags |= PackageManager.INSTALL_FORCE_PERMISSION_PROMPT; 1967 } 1968 1969 /** {@hide} */ 1970 @SystemApi setDontKillApp(boolean dontKillApp)1971 public void setDontKillApp(boolean dontKillApp) { 1972 if (dontKillApp) { 1973 installFlags |= PackageManager.INSTALL_DONT_KILL_APP; 1974 } else { 1975 installFlags &= ~PackageManager.INSTALL_DONT_KILL_APP; 1976 } 1977 } 1978 1979 /** {@hide} */ 1980 @SystemApi setInstallAsInstantApp(boolean isInstantApp)1981 public void setInstallAsInstantApp(boolean isInstantApp) { 1982 if (isInstantApp) { 1983 installFlags |= PackageManager.INSTALL_INSTANT_APP; 1984 installFlags &= ~PackageManager.INSTALL_FULL_APP; 1985 } else { 1986 installFlags &= ~PackageManager.INSTALL_INSTANT_APP; 1987 installFlags |= PackageManager.INSTALL_FULL_APP; 1988 } 1989 } 1990 1991 /** 1992 * Sets the install as a virtual preload. Will only have effect when called 1993 * by the verifier. 1994 * {@hide} 1995 */ 1996 @SystemApi setInstallAsVirtualPreload()1997 public void setInstallAsVirtualPreload() { 1998 installFlags |= PackageManager.INSTALL_VIRTUAL_PRELOAD; 1999 } 2000 2001 /** 2002 * Set the reason for installing this package. 2003 * <p> 2004 * The install reason should be a pre-defined integer. The behavior is 2005 * undefined if other values are used. 2006 * 2007 * @see PackageManager#INSTALL_REASON_UNKNOWN 2008 * @see PackageManager#INSTALL_REASON_POLICY 2009 * @see PackageManager#INSTALL_REASON_DEVICE_RESTORE 2010 * @see PackageManager#INSTALL_REASON_DEVICE_SETUP 2011 * @see PackageManager#INSTALL_REASON_USER 2012 */ setInstallReason(@nstallReason int installReason)2013 public void setInstallReason(@InstallReason int installReason) { 2014 this.installReason = installReason; 2015 } 2016 2017 /** {@hide} */ 2018 @SystemApi 2019 @RequiresPermission(android.Manifest.permission.ALLOCATE_AGGRESSIVE) setAllocateAggressive(boolean allocateAggressive)2020 public void setAllocateAggressive(boolean allocateAggressive) { 2021 if (allocateAggressive) { 2022 installFlags |= PackageManager.INSTALL_ALLOCATE_AGGRESSIVE; 2023 } else { 2024 installFlags &= ~PackageManager.INSTALL_ALLOCATE_AGGRESSIVE; 2025 } 2026 } 2027 2028 /** 2029 * @hide 2030 */ 2031 @TestApi setInstallFlagAllowTest()2032 public void setInstallFlagAllowTest() { 2033 installFlags |= PackageManager.INSTALL_ALLOW_TEST; 2034 } 2035 2036 /** 2037 * Set the installer package for the app. 2038 * 2039 * By default this is the app that created the {@link PackageInstaller} object. 2040 * 2041 * @param installerPackageName name of the installer package 2042 * {@hide} 2043 */ 2044 @TestApi setInstallerPackageName(@ullable String installerPackageName)2045 public void setInstallerPackageName(@Nullable String installerPackageName) { 2046 this.installerPackageName = installerPackageName; 2047 } 2048 2049 /** 2050 * Set this session to be the parent of a multi-package install. 2051 * 2052 * A multi-package install session contains no APKs and only references other install 2053 * sessions via ID. When a multi-package session is committed, all of its children 2054 * are committed to the system in an atomic manner. If any children fail to install, 2055 * all of them do, including the multi-package session. 2056 */ setMultiPackage()2057 public void setMultiPackage() { 2058 this.isMultiPackage = true; 2059 } 2060 2061 /** 2062 * Set this session to be staged to be installed at reboot. 2063 * 2064 * Staged sessions are scheduled to be installed at next reboot. Staged sessions can also be 2065 * multi-package. In that case, if any of the children sessions fail to install at reboot, 2066 * all the other children sessions are aborted as well. 2067 * 2068 * <p>If the parent session is staged or has rollback enabled, all children sessions 2069 * must have the same properties. 2070 * 2071 * {@hide} 2072 */ 2073 @SystemApi 2074 @RequiresPermission(Manifest.permission.INSTALL_PACKAGES) setStaged()2075 public void setStaged() { 2076 this.isStaged = true; 2077 } 2078 2079 /** 2080 * Set this session to be installing an APEX package. 2081 * 2082 * {@hide} 2083 */ 2084 @SystemApi 2085 @RequiresPermission(Manifest.permission.INSTALL_PACKAGES) setInstallAsApex()2086 public void setInstallAsApex() { 2087 installFlags |= PackageManager.INSTALL_APEX; 2088 } 2089 2090 /** @hide */ getEnableRollback()2091 public boolean getEnableRollback() { 2092 return (installFlags & PackageManager.INSTALL_ENABLE_ROLLBACK) != 0; 2093 } 2094 2095 /** 2096 * Set the data loader params for the session. 2097 * This also switches installation into data loading mode and disallow direct writes into 2098 * staging folder. 2099 * 2100 * @see android.service.dataloader.DataLoaderService.DataLoader 2101 * 2102 * {@hide} 2103 */ 2104 @SystemApi 2105 @RequiresPermission(allOf = { 2106 Manifest.permission.INSTALL_PACKAGES, 2107 Manifest.permission.USE_INSTALLER_V2}) setDataLoaderParams(@onNull DataLoaderParams dataLoaderParams)2108 public void setDataLoaderParams(@NonNull DataLoaderParams dataLoaderParams) { 2109 this.dataLoaderParams = dataLoaderParams; 2110 } 2111 2112 /** 2113 * 2114 * {@hide} 2115 */ setForceQueryable()2116 public void setForceQueryable() { 2117 this.forceQueryableOverride = true; 2118 } 2119 2120 /** 2121 * Optionally indicate whether user action should be required when the session is 2122 * committed. 2123 * <p> 2124 * Defaults to {@link #USER_ACTION_UNSPECIFIED} unless otherwise set. When unspecified for 2125 * installers using the 2126 * {@link android.Manifest.permission#REQUEST_INSTALL_PACKAGES REQUEST_INSTALL_PACKAGES} 2127 * permission will behave as if set to {@link #USER_ACTION_REQUIRED}, and 2128 * {@link #USER_ACTION_NOT_REQUIRED} otherwise. When {@code requireUserAction} is set to 2129 * {@link #USER_ACTION_REQUIRED}, installers will receive a 2130 * {@link #STATUS_PENDING_USER_ACTION} callback once the session is committed, indicating 2131 * that user action is required for the install to proceed. 2132 * <p> 2133 * For installers that have been granted the 2134 * {@link android.Manifest.permission#REQUEST_INSTALL_PACKAGES REQUEST_INSTALL_PACKAGES} 2135 * permission, user action will not be required when all of the following conditions are 2136 * met: 2137 * 2138 * <ul> 2139 * <li>{@code requireUserAction} is set to {@link #USER_ACTION_NOT_REQUIRED}.</li> 2140 * <li>The app being installed targets {@link android.os.Build.VERSION_CODES#Q API 29} 2141 * or higher.</li> 2142 * <li>The installer is the {@link InstallSourceInfo#getInstallingPackageName() 2143 * installer of record} of an existing version of the app (in other words, this install 2144 * session is an app update) or the installer is updating itself.</li> 2145 * <li>The installer declares the 2146 * {@link android.Manifest.permission#UPDATE_PACKAGES_WITHOUT_USER_ACTION 2147 * UPDATE_PACKAGES_WITHOUT_USER_ACTION} permission.</li> 2148 * </ul> 2149 * <p> 2150 * Note: The target API level requirement will advance in future Android versions. 2151 * Session owners should always be prepared to handle {@link #STATUS_PENDING_USER_ACTION}. 2152 * 2153 * @param requireUserAction whether user action should be required. 2154 */ setRequireUserAction( @essionParams.UserActionRequirement int requireUserAction)2155 public void setRequireUserAction( 2156 @SessionParams.UserActionRequirement int requireUserAction) { 2157 if (requireUserAction != USER_ACTION_UNSPECIFIED 2158 && requireUserAction != USER_ACTION_REQUIRED 2159 && requireUserAction != USER_ACTION_NOT_REQUIRED) { 2160 throw new IllegalArgumentException("requireUserAction set as invalid value of " 2161 + requireUserAction + ", but must be one of [" 2162 + "USER_ACTION_UNSPECIFIED, USER_ACTION_REQUIRED, USER_ACTION_NOT_REQUIRED" 2163 + "]"); 2164 } 2165 this.requireUserAction = requireUserAction; 2166 } 2167 2168 /** 2169 * Sets the install scenario for this session, which describes the expected user journey. 2170 */ setInstallScenario(@nstallScenario int installScenario)2171 public void setInstallScenario(@InstallScenario int installScenario) { 2172 this.installScenario = installScenario; 2173 } 2174 2175 /** {@hide} */ dump(IndentingPrintWriter pw)2176 public void dump(IndentingPrintWriter pw) { 2177 pw.printPair("mode", mode); 2178 pw.printHexPair("installFlags", installFlags); 2179 pw.printPair("installLocation", installLocation); 2180 pw.printPair("installReason", installReason); 2181 pw.printPair("installScenario", installScenario); 2182 pw.printPair("sizeBytes", sizeBytes); 2183 pw.printPair("appPackageName", appPackageName); 2184 pw.printPair("appIcon", (appIcon != null)); 2185 pw.printPair("appLabel", appLabel); 2186 pw.printPair("originatingUri", originatingUri); 2187 pw.printPair("originatingUid", originatingUid); 2188 pw.printPair("referrerUri", referrerUri); 2189 pw.printPair("abiOverride", abiOverride); 2190 pw.printPair("volumeUuid", volumeUuid); 2191 pw.printPair("grantedRuntimePermissions", grantedRuntimePermissions); 2192 pw.printPair("whitelistedRestrictedPermissions", whitelistedRestrictedPermissions); 2193 pw.printPair("autoRevokePermissions", autoRevokePermissionsMode); 2194 pw.printPair("installerPackageName", installerPackageName); 2195 pw.printPair("isMultiPackage", isMultiPackage); 2196 pw.printPair("isStaged", isStaged); 2197 pw.printPair("forceQueryable", forceQueryableOverride); 2198 pw.printPair("requireUserAction", SessionInfo.userActionToString(requireUserAction)); 2199 pw.printPair("requiredInstalledVersionCode", requiredInstalledVersionCode); 2200 pw.printPair("dataLoaderParams", dataLoaderParams); 2201 pw.printPair("rollbackDataPolicy", rollbackDataPolicy); 2202 pw.println(); 2203 } 2204 2205 @Override describeContents()2206 public int describeContents() { 2207 return 0; 2208 } 2209 2210 @Override writeToParcel(Parcel dest, int flags)2211 public void writeToParcel(Parcel dest, int flags) { 2212 dest.writeInt(mode); 2213 dest.writeInt(installFlags); 2214 dest.writeInt(installLocation); 2215 dest.writeInt(installReason); 2216 dest.writeInt(installScenario); 2217 dest.writeLong(sizeBytes); 2218 dest.writeString(appPackageName); 2219 dest.writeParcelable(appIcon, flags); 2220 dest.writeString(appLabel); 2221 dest.writeParcelable(originatingUri, flags); 2222 dest.writeInt(originatingUid); 2223 dest.writeParcelable(referrerUri, flags); 2224 dest.writeString(abiOverride); 2225 dest.writeString(volumeUuid); 2226 dest.writeStringArray(grantedRuntimePermissions); 2227 dest.writeStringList(whitelistedRestrictedPermissions); 2228 dest.writeInt(autoRevokePermissionsMode); 2229 dest.writeString(installerPackageName); 2230 dest.writeBoolean(isMultiPackage); 2231 dest.writeBoolean(isStaged); 2232 dest.writeBoolean(forceQueryableOverride); 2233 dest.writeLong(requiredInstalledVersionCode); 2234 if (dataLoaderParams != null) { 2235 dest.writeParcelable(dataLoaderParams.getData(), flags); 2236 } else { 2237 dest.writeParcelable(null, flags); 2238 } 2239 dest.writeInt(rollbackDataPolicy); 2240 dest.writeInt(requireUserAction); 2241 } 2242 2243 public static final Parcelable.Creator<SessionParams> 2244 CREATOR = new Parcelable.Creator<SessionParams>() { 2245 @Override 2246 public SessionParams createFromParcel(Parcel p) { 2247 return new SessionParams(p); 2248 } 2249 2250 @Override 2251 public SessionParams[] newArray(int size) { 2252 return new SessionParams[size]; 2253 } 2254 }; 2255 } 2256 2257 /** 2258 * Details for an active install session. 2259 */ 2260 public static class SessionInfo implements Parcelable { 2261 2262 /** 2263 * A session ID that does not exist or is invalid. 2264 */ 2265 public static final int INVALID_ID = -1; 2266 /** {@hide} */ 2267 private static final int[] NO_SESSIONS = {}; 2268 2269 /** @hide */ 2270 @IntDef(prefix = { "STAGED_SESSION_" }, value = { 2271 STAGED_SESSION_NO_ERROR, 2272 STAGED_SESSION_VERIFICATION_FAILED, 2273 STAGED_SESSION_ACTIVATION_FAILED, 2274 STAGED_SESSION_UNKNOWN, 2275 STAGED_SESSION_CONFLICT}) 2276 @Retention(RetentionPolicy.SOURCE) 2277 public @interface StagedSessionErrorCode{} 2278 /** 2279 * Constant indicating that no error occurred during the preparation or the activation of 2280 * this staged session. 2281 */ 2282 public static final int STAGED_SESSION_NO_ERROR = 0; 2283 2284 /** 2285 * Constant indicating that an error occurred during the verification phase (pre-reboot) of 2286 * this staged session. 2287 */ 2288 public static final int STAGED_SESSION_VERIFICATION_FAILED = 1; 2289 2290 /** 2291 * Constant indicating that an error occurred during the activation phase (post-reboot) of 2292 * this staged session. 2293 */ 2294 public static final int STAGED_SESSION_ACTIVATION_FAILED = 2; 2295 2296 /** 2297 * Constant indicating that an unknown error occurred while processing this staged session. 2298 */ 2299 public static final int STAGED_SESSION_UNKNOWN = 3; 2300 2301 /** 2302 * Constant indicating that the session was in conflict with another staged session and had 2303 * to be sacrificed for resolution. 2304 */ 2305 public static final int STAGED_SESSION_CONFLICT = 4; 2306 userActionToString(int requireUserAction)2307 private static String userActionToString(int requireUserAction) { 2308 switch(requireUserAction) { 2309 case SessionParams.USER_ACTION_REQUIRED: 2310 return "REQUIRED"; 2311 case SessionParams.USER_ACTION_NOT_REQUIRED: 2312 return "NOT_REQUIRED"; 2313 default: 2314 return "UNSPECIFIED"; 2315 } 2316 } 2317 2318 /** {@hide} */ 2319 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) 2320 public int sessionId; 2321 /** {@hide} */ 2322 public int userId; 2323 /** {@hide} */ 2324 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) 2325 public String installerPackageName; 2326 /** {@hide} */ 2327 public String installerAttributionTag; 2328 /** {@hide} */ 2329 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 2330 public String resolvedBaseCodePath; 2331 /** {@hide} */ 2332 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) 2333 public float progress; 2334 /** {@hide} */ 2335 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 2336 public boolean sealed; 2337 /** {@hide} */ 2338 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) 2339 public boolean active; 2340 2341 /** {@hide} */ 2342 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) 2343 public int mode; 2344 /** {@hide} */ 2345 public @InstallReason int installReason; 2346 /** {@hide} */ 2347 public @InstallScenario int installScenario; 2348 /** {@hide} */ 2349 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) 2350 public long sizeBytes; 2351 /** {@hide} */ 2352 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) 2353 public String appPackageName; 2354 /** {@hide} */ 2355 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) 2356 public Bitmap appIcon; 2357 /** {@hide} */ 2358 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) 2359 public CharSequence appLabel; 2360 2361 /** {@hide} */ 2362 public int installLocation; 2363 /** {@hide} */ 2364 public Uri originatingUri; 2365 /** {@hide} */ 2366 public int originatingUid; 2367 /** {@hide} */ 2368 public Uri referrerUri; 2369 /** {@hide} */ 2370 public String[] grantedRuntimePermissions; 2371 /** {@hide}*/ 2372 public List<String> whitelistedRestrictedPermissions; 2373 /** {@hide}*/ 2374 public int autoRevokePermissionsMode = MODE_DEFAULT; 2375 /** {@hide} */ 2376 public int installFlags; 2377 /** {@hide} */ 2378 public boolean isMultiPackage; 2379 /** {@hide} */ 2380 public boolean isStaged; 2381 /** {@hide} */ 2382 public boolean forceQueryable; 2383 /** {@hide} */ 2384 public int parentSessionId = INVALID_ID; 2385 /** {@hide} */ 2386 public int[] childSessionIds = NO_SESSIONS; 2387 2388 /** {@hide} */ 2389 public boolean isStagedSessionApplied; 2390 /** {@hide} */ 2391 public boolean isStagedSessionReady; 2392 /** {@hide} */ 2393 public boolean isStagedSessionFailed; 2394 private int mStagedSessionErrorCode; 2395 private String mStagedSessionErrorMessage; 2396 2397 /** {@hide} */ 2398 public boolean isCommitted; 2399 2400 /** {@hide} */ 2401 public long createdMillis; 2402 2403 /** {@hide} */ 2404 public long updatedMillis; 2405 2406 /** {@hide} */ 2407 public int rollbackDataPolicy; 2408 2409 /** {@hide} */ 2410 public int requireUserAction; 2411 2412 /** {@hide} */ 2413 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) SessionInfo()2414 public SessionInfo() { 2415 } 2416 2417 /** {@hide} */ SessionInfo(Parcel source)2418 public SessionInfo(Parcel source) { 2419 sessionId = source.readInt(); 2420 userId = source.readInt(); 2421 installerPackageName = source.readString(); 2422 installerAttributionTag = source.readString(); 2423 resolvedBaseCodePath = source.readString(); 2424 progress = source.readFloat(); 2425 sealed = source.readInt() != 0; 2426 active = source.readInt() != 0; 2427 2428 mode = source.readInt(); 2429 installReason = source.readInt(); 2430 installScenario = source.readInt(); 2431 sizeBytes = source.readLong(); 2432 appPackageName = source.readString(); 2433 appIcon = source.readParcelable(null); 2434 appLabel = source.readString(); 2435 2436 installLocation = source.readInt(); 2437 originatingUri = source.readParcelable(null); 2438 originatingUid = source.readInt(); 2439 referrerUri = source.readParcelable(null); 2440 grantedRuntimePermissions = source.readStringArray(); 2441 whitelistedRestrictedPermissions = source.createStringArrayList(); 2442 autoRevokePermissionsMode = source.readInt(); 2443 2444 installFlags = source.readInt(); 2445 isMultiPackage = source.readBoolean(); 2446 isStaged = source.readBoolean(); 2447 forceQueryable = source.readBoolean(); 2448 parentSessionId = source.readInt(); 2449 childSessionIds = source.createIntArray(); 2450 if (childSessionIds == null) { 2451 childSessionIds = NO_SESSIONS; 2452 } 2453 isStagedSessionApplied = source.readBoolean(); 2454 isStagedSessionReady = source.readBoolean(); 2455 isStagedSessionFailed = source.readBoolean(); 2456 mStagedSessionErrorCode = source.readInt(); 2457 mStagedSessionErrorMessage = source.readString(); 2458 isCommitted = source.readBoolean(); 2459 rollbackDataPolicy = source.readInt(); 2460 createdMillis = source.readLong(); 2461 requireUserAction = source.readInt(); 2462 } 2463 2464 /** 2465 * Return the ID for this session. 2466 */ getSessionId()2467 public int getSessionId() { 2468 return sessionId; 2469 } 2470 2471 /** 2472 * Return the user associated with this session. 2473 */ getUser()2474 public @NonNull UserHandle getUser() { 2475 return new UserHandle(userId); 2476 } 2477 2478 /** 2479 * Return the package name of the app that owns this session. 2480 */ getInstallerPackageName()2481 public @Nullable String getInstallerPackageName() { 2482 return installerPackageName; 2483 } 2484 2485 /** 2486 * @return {@link android.content.Context#getAttributionTag attribution tag} of the context 2487 * that created this session 2488 */ getInstallerAttributionTag()2489 public @Nullable String getInstallerAttributionTag() { 2490 return installerAttributionTag; 2491 } 2492 2493 /** 2494 * Return current overall progress of this session, between 0 and 1. 2495 * <p> 2496 * Note that this progress may not directly correspond to the value 2497 * reported by 2498 * {@link PackageInstaller.Session#setStagingProgress(float)}, as the 2499 * system may carve out a portion of the overall progress to represent 2500 * its own internal installation work. 2501 */ getProgress()2502 public float getProgress() { 2503 return progress; 2504 } 2505 2506 /** 2507 * Return if this session is currently active. 2508 * <p> 2509 * A session is considered active whenever there is ongoing forward 2510 * progress being made, such as the installer holding an open 2511 * {@link Session} instance while streaming data into place, or the 2512 * system optimizing code as the result of 2513 * {@link Session#commit(IntentSender)}. 2514 * <p> 2515 * If the installer closes the {@link Session} without committing, the 2516 * session is considered inactive until the installer opens the session 2517 * again. 2518 */ isActive()2519 public boolean isActive() { 2520 return active; 2521 } 2522 2523 /** 2524 * Return if this session is sealed. 2525 * <p> 2526 * Once sealed, no further changes may be made to the session. A session 2527 * is sealed the moment {@link Session#commit(IntentSender)} is called. 2528 */ isSealed()2529 public boolean isSealed() { 2530 return sealed; 2531 } 2532 2533 /** 2534 * Return the reason for installing this package. 2535 * 2536 * @return The install reason. 2537 */ getInstallReason()2538 public @InstallReason int getInstallReason() { 2539 return installReason; 2540 } 2541 2542 /** {@hide} */ 2543 @Deprecated isOpen()2544 public boolean isOpen() { 2545 return isActive(); 2546 } 2547 2548 /** 2549 * Return the package name this session is working with. May be {@code null} 2550 * if unknown. 2551 */ getAppPackageName()2552 public @Nullable String getAppPackageName() { 2553 return appPackageName; 2554 } 2555 2556 /** 2557 * Return an icon representing the app being installed. May be {@code null} 2558 * if unavailable. 2559 */ getAppIcon()2560 public @Nullable Bitmap getAppIcon() { 2561 if (appIcon == null) { 2562 // Icon may have been omitted for calls that return bulk session 2563 // lists, so try fetching the specific icon. 2564 try { 2565 final SessionInfo info = AppGlobals.getPackageManager().getPackageInstaller() 2566 .getSessionInfo(sessionId); 2567 appIcon = (info != null) ? info.appIcon : null; 2568 } catch (RemoteException e) { 2569 throw e.rethrowFromSystemServer(); 2570 } 2571 } 2572 return appIcon; 2573 } 2574 2575 /** 2576 * Return a label representing the app being installed. May be {@code null} 2577 * if unavailable. 2578 */ getAppLabel()2579 public @Nullable CharSequence getAppLabel() { 2580 return appLabel; 2581 } 2582 2583 /** 2584 * Return an Intent that can be started to view details about this install 2585 * session. This may surface actions such as pause, resume, or cancel. 2586 * <p> 2587 * In some cases, a matching Activity may not exist, so ensure you safeguard 2588 * against this. 2589 * 2590 * @see PackageInstaller#ACTION_SESSION_DETAILS 2591 */ createDetailsIntent()2592 public @Nullable Intent createDetailsIntent() { 2593 final Intent intent = new Intent(PackageInstaller.ACTION_SESSION_DETAILS); 2594 intent.putExtra(PackageInstaller.EXTRA_SESSION_ID, sessionId); 2595 intent.setPackage(installerPackageName); 2596 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 2597 return intent; 2598 } 2599 2600 /** 2601 * Get the mode of the session as set in the constructor of the {@link SessionParams}. 2602 * 2603 * @return One of {@link SessionParams#MODE_FULL_INSTALL} 2604 * or {@link SessionParams#MODE_INHERIT_EXISTING} 2605 */ getMode()2606 public int getMode() { 2607 return mode; 2608 } 2609 2610 /** 2611 * Get the value set in {@link SessionParams#setInstallLocation(int)}. 2612 */ getInstallLocation()2613 public int getInstallLocation() { 2614 return installLocation; 2615 } 2616 2617 /** 2618 * Get the value as set in {@link SessionParams#setSize(long)}. 2619 * 2620 * <p>The value is a hint and does not have to match the actual size. 2621 */ getSize()2622 public long getSize() { 2623 return sizeBytes; 2624 } 2625 2626 /** 2627 * Get the value set in {@link SessionParams#setOriginatingUri(Uri)}. 2628 * Note: This value will only be non-null for the owner of the session. 2629 */ getOriginatingUri()2630 public @Nullable Uri getOriginatingUri() { 2631 return originatingUri; 2632 } 2633 2634 /** 2635 * Get the value set in {@link SessionParams#setOriginatingUid(int)}. 2636 */ getOriginatingUid()2637 public int getOriginatingUid() { 2638 return originatingUid; 2639 } 2640 2641 /** 2642 * Get the value set in {@link SessionParams#setReferrerUri(Uri)} 2643 * Note: This value will only be non-null for the owner of the session. 2644 */ getReferrerUri()2645 public @Nullable Uri getReferrerUri() { 2646 return referrerUri; 2647 } 2648 2649 /** 2650 * Get the value set in {@link SessionParams#setGrantedRuntimePermissions(String[])}. 2651 * 2652 * @hide 2653 */ 2654 @SystemApi getGrantedRuntimePermissions()2655 public @Nullable String[] getGrantedRuntimePermissions() { 2656 return grantedRuntimePermissions; 2657 } 2658 2659 /** 2660 * Get the value set in {@link SessionParams#setWhitelistedRestrictedPermissions(Set)}. 2661 * Note that if all permissions are allowlisted this method returns {@link 2662 * SessionParams#RESTRICTED_PERMISSIONS_ALL}. 2663 * 2664 * @hide 2665 */ 2666 @SystemApi getWhitelistedRestrictedPermissions()2667 public @NonNull Set<String> getWhitelistedRestrictedPermissions() { 2668 if ((installFlags & PackageManager.INSTALL_ALL_WHITELIST_RESTRICTED_PERMISSIONS) != 0) { 2669 return SessionParams.RESTRICTED_PERMISSIONS_ALL; 2670 } 2671 if (whitelistedRestrictedPermissions != null) { 2672 return new ArraySet<>(whitelistedRestrictedPermissions); 2673 } 2674 return Collections.emptySet(); 2675 } 2676 2677 /** 2678 * Get the status of whether permission auto-revocation should be allowed, ignored, or 2679 * deferred to manifest data. 2680 * 2681 * @see android.app.AppOpsManager#MODE_ALLOWED 2682 * @see android.app.AppOpsManager#MODE_IGNORED 2683 * @see android.app.AppOpsManager#MODE_DEFAULT 2684 * 2685 * @return the status of auto-revoke for this package 2686 * 2687 * @hide 2688 */ 2689 @SystemApi getAutoRevokePermissionsMode()2690 public int getAutoRevokePermissionsMode() { 2691 return autoRevokePermissionsMode; 2692 } 2693 2694 /** 2695 * Get the value set in {@link SessionParams#setAllowDowngrade(boolean)}. 2696 * 2697 * @deprecated use {@link #getRequestDowngrade()}. 2698 * @hide 2699 */ 2700 @SystemApi 2701 @Deprecated getAllowDowngrade()2702 public boolean getAllowDowngrade() { 2703 return getRequestDowngrade(); 2704 } 2705 2706 /** 2707 * Get the value set in {@link SessionParams#setRequestDowngrade(boolean)}. 2708 * 2709 * @hide 2710 */ 2711 @SystemApi getRequestDowngrade()2712 public boolean getRequestDowngrade() { 2713 return (installFlags & PackageManager.INSTALL_REQUEST_DOWNGRADE) != 0; 2714 } 2715 2716 /** 2717 * Get the value set in {@link SessionParams#setDontKillApp(boolean)}. 2718 * 2719 * @hide 2720 */ 2721 @SystemApi getDontKillApp()2722 public boolean getDontKillApp() { 2723 return (installFlags & PackageManager.INSTALL_DONT_KILL_APP) != 0; 2724 } 2725 2726 /** 2727 * Get if this session is to be installed as Instant Apps. 2728 * 2729 * @param isInstantApp an unused parameter and is ignored. 2730 * @return {@code true} if {@link SessionParams#setInstallAsInstantApp(boolean)} was called 2731 * with {@code true}; {@code false} if it was called with {@code false} or if it was not 2732 * called. 2733 * 2734 * @see #getInstallAsFullApp 2735 * 2736 * @hide 2737 */ 2738 @SystemApi getInstallAsInstantApp(boolean isInstantApp)2739 public boolean getInstallAsInstantApp(boolean isInstantApp) { 2740 return (installFlags & PackageManager.INSTALL_INSTANT_APP) != 0; 2741 } 2742 2743 /** 2744 * Get if this session is to be installed as full apps. 2745 * 2746 * @param isInstantApp an unused parameter and is ignored. 2747 * @return {@code true} if {@link SessionParams#setInstallAsInstantApp(boolean)} was called 2748 * with {@code false}; {code false} if it was called with {@code true} or if it was not 2749 * called. 2750 * 2751 * @see #getInstallAsInstantApp 2752 * 2753 * @hide 2754 */ 2755 @SystemApi getInstallAsFullApp(boolean isInstantApp)2756 public boolean getInstallAsFullApp(boolean isInstantApp) { 2757 return (installFlags & PackageManager.INSTALL_FULL_APP) != 0; 2758 } 2759 2760 /** 2761 * Get if {@link SessionParams#setInstallAsVirtualPreload()} was called. 2762 * 2763 * @hide 2764 */ 2765 @SystemApi getInstallAsVirtualPreload()2766 public boolean getInstallAsVirtualPreload() { 2767 return (installFlags & PackageManager.INSTALL_VIRTUAL_PRELOAD) != 0; 2768 } 2769 2770 /** 2771 * Return whether rollback is enabled or disabled for the given upgrade. 2772 * 2773 * @hide 2774 */ 2775 @SystemApi getEnableRollback()2776 public boolean getEnableRollback() { 2777 return (installFlags & PackageManager.INSTALL_ENABLE_ROLLBACK) != 0; 2778 } 2779 2780 /** 2781 * Get the value set in {@link SessionParams#setAllocateAggressive(boolean)}. 2782 * 2783 * @hide 2784 */ 2785 @SystemApi getAllocateAggressive()2786 public boolean getAllocateAggressive() { 2787 return (installFlags & PackageManager.INSTALL_ALLOCATE_AGGRESSIVE) != 0; 2788 } 2789 2790 2791 /** {@hide} */ 2792 @Deprecated getDetailsIntent()2793 public @Nullable Intent getDetailsIntent() { 2794 return createDetailsIntent(); 2795 } 2796 2797 /** 2798 * Returns true if this session is a multi-package session containing references to other 2799 * sessions. 2800 */ isMultiPackage()2801 public boolean isMultiPackage() { 2802 return isMultiPackage; 2803 } 2804 2805 /** 2806 * Returns true if this session is a staged session. 2807 */ isStaged()2808 public boolean isStaged() { 2809 return isStaged; 2810 } 2811 2812 /** 2813 * Return the data policy associated with the rollback for the given upgrade. 2814 * 2815 * @hide 2816 */ 2817 @SystemApi 2818 @PackageManager.RollbackDataPolicy getRollbackDataPolicy()2819 public int getRollbackDataPolicy() { 2820 return rollbackDataPolicy; 2821 } 2822 2823 /** 2824 * Returns true if this session is marked as forceQueryable 2825 * {@hide} 2826 */ isForceQueryable()2827 public boolean isForceQueryable() { 2828 return forceQueryable; 2829 } 2830 2831 /** 2832 * Returns {@code true} if this session is an active staged session. 2833 * 2834 * We consider a session active if it has been committed and it is either pending 2835 * verification, or will be applied at next reboot. 2836 * 2837 * <p>Staged session is active iff: 2838 * <ul> 2839 * <li>It is committed, i.e. {@link SessionInfo#isCommitted()} is {@code true}, and 2840 * <li>it is not applied, i.e. {@link SessionInfo#isStagedSessionApplied()} is {@code 2841 * false}, and 2842 * <li>it is not failed, i.e. {@link SessionInfo#isStagedSessionFailed()} is 2843 * {@code false}. 2844 * </ul> 2845 * 2846 * <p>In case of a multi-package session, reasoning above is applied to the parent session, 2847 * since that is the one that should have been {@link Session#commit committed}. 2848 */ isStagedSessionActive()2849 public boolean isStagedSessionActive() { 2850 return isStaged && isCommitted && !isStagedSessionApplied && !isStagedSessionFailed 2851 && !hasParentSessionId(); 2852 } 2853 2854 /** 2855 * Returns the parent multi-package session ID if this session belongs to one, 2856 * {@link #INVALID_ID} otherwise. 2857 */ getParentSessionId()2858 public int getParentSessionId() { 2859 return parentSessionId; 2860 } 2861 2862 /** 2863 * Returns true if session has a valid parent session, otherwise false. 2864 */ hasParentSessionId()2865 public boolean hasParentSessionId() { 2866 return parentSessionId != INVALID_ID; 2867 } 2868 2869 /** 2870 * Returns the set of session IDs that will be committed when this session is commited if 2871 * this session is a multi-package session. 2872 */ 2873 @NonNull getChildSessionIds()2874 public int[] getChildSessionIds() { 2875 return childSessionIds; 2876 } 2877 checkSessionIsStaged()2878 private void checkSessionIsStaged() { 2879 if (!isStaged) { 2880 throw new IllegalStateException("Session is not marked as staged."); 2881 } 2882 } 2883 2884 /** 2885 * Whether the staged session has been applied successfully, meaning that all of its 2886 * packages have been activated and no further action is required. 2887 * Only meaningful if {@code isStaged} is true. 2888 */ isStagedSessionApplied()2889 public boolean isStagedSessionApplied() { 2890 checkSessionIsStaged(); 2891 return isStagedSessionApplied; 2892 } 2893 2894 /** 2895 * Whether the staged session is ready to be applied at next reboot. Only meaningful if 2896 * {@code isStaged} is true. 2897 */ isStagedSessionReady()2898 public boolean isStagedSessionReady() { 2899 checkSessionIsStaged(); 2900 return isStagedSessionReady; 2901 } 2902 2903 /** 2904 * Whether something went wrong and the staged session is declared as failed, meaning that 2905 * it will be ignored at next reboot. Only meaningful if {@code isStaged} is true. 2906 */ isStagedSessionFailed()2907 public boolean isStagedSessionFailed() { 2908 checkSessionIsStaged(); 2909 return isStagedSessionFailed; 2910 } 2911 2912 /** 2913 * If something went wrong with a staged session, clients can check this error code to 2914 * understand which kind of failure happened. Only meaningful if {@code isStaged} is true. 2915 */ getStagedSessionErrorCode()2916 public @StagedSessionErrorCode int getStagedSessionErrorCode() { 2917 checkSessionIsStaged(); 2918 return mStagedSessionErrorCode; 2919 } 2920 2921 /** 2922 * Text description of the error code returned by {@code getStagedSessionErrorCode}, or 2923 * empty string if no error was encountered. 2924 */ getStagedSessionErrorMessage()2925 public @NonNull String getStagedSessionErrorMessage() { 2926 checkSessionIsStaged(); 2927 return mStagedSessionErrorMessage; 2928 } 2929 2930 /** {@hide} */ setStagedSessionErrorCode(@tagedSessionErrorCode int errorCode, String errorMessage)2931 public void setStagedSessionErrorCode(@StagedSessionErrorCode int errorCode, 2932 String errorMessage) { 2933 mStagedSessionErrorCode = errorCode; 2934 mStagedSessionErrorMessage = errorMessage; 2935 } 2936 2937 /** 2938 * Returns {@code true} if {@link Session#commit(IntentSender)}} was called for this 2939 * session. 2940 */ isCommitted()2941 public boolean isCommitted() { 2942 return isCommitted; 2943 } 2944 2945 /** 2946 * The timestamp of the initial creation of the session. 2947 */ getCreatedMillis()2948 public long getCreatedMillis() { 2949 return createdMillis; 2950 } 2951 2952 /** 2953 * The timestamp of the last update that occurred to the session, including changing of 2954 * states in case of staged sessions. 2955 */ 2956 @CurrentTimeMillisLong getUpdatedMillis()2957 public long getUpdatedMillis() { 2958 return updatedMillis; 2959 } 2960 2961 /** 2962 * Whether user action was required by the installer. 2963 * 2964 * <p> 2965 * Note: a return value of {@code USER_ACTION_NOT_REQUIRED} does not guarantee that the 2966 * install will not result in user action. 2967 * 2968 * @return {@link SessionParams#USER_ACTION_NOT_REQUIRED}, 2969 * {@link SessionParams#USER_ACTION_REQUIRED} or 2970 * {@link SessionParams#USER_ACTION_UNSPECIFIED} 2971 */ 2972 @SessionParams.UserActionRequirement getRequireUserAction()2973 public int getRequireUserAction() { 2974 return requireUserAction; 2975 } 2976 2977 @Override describeContents()2978 public int describeContents() { 2979 return 0; 2980 } 2981 2982 @Override writeToParcel(Parcel dest, int flags)2983 public void writeToParcel(Parcel dest, int flags) { 2984 dest.writeInt(sessionId); 2985 dest.writeInt(userId); 2986 dest.writeString(installerPackageName); 2987 dest.writeString(installerAttributionTag); 2988 dest.writeString(resolvedBaseCodePath); 2989 dest.writeFloat(progress); 2990 dest.writeInt(sealed ? 1 : 0); 2991 dest.writeInt(active ? 1 : 0); 2992 2993 dest.writeInt(mode); 2994 dest.writeInt(installReason); 2995 dest.writeInt(installScenario); 2996 dest.writeLong(sizeBytes); 2997 dest.writeString(appPackageName); 2998 dest.writeParcelable(appIcon, flags); 2999 dest.writeString(appLabel != null ? appLabel.toString() : null); 3000 3001 dest.writeInt(installLocation); 3002 dest.writeParcelable(originatingUri, flags); 3003 dest.writeInt(originatingUid); 3004 dest.writeParcelable(referrerUri, flags); 3005 dest.writeStringArray(grantedRuntimePermissions); 3006 dest.writeStringList(whitelistedRestrictedPermissions); 3007 dest.writeInt(autoRevokePermissionsMode); 3008 dest.writeInt(installFlags); 3009 dest.writeBoolean(isMultiPackage); 3010 dest.writeBoolean(isStaged); 3011 dest.writeBoolean(forceQueryable); 3012 dest.writeInt(parentSessionId); 3013 dest.writeIntArray(childSessionIds); 3014 dest.writeBoolean(isStagedSessionApplied); 3015 dest.writeBoolean(isStagedSessionReady); 3016 dest.writeBoolean(isStagedSessionFailed); 3017 dest.writeInt(mStagedSessionErrorCode); 3018 dest.writeString(mStagedSessionErrorMessage); 3019 dest.writeBoolean(isCommitted); 3020 dest.writeInt(rollbackDataPolicy); 3021 dest.writeLong(createdMillis); 3022 dest.writeInt(requireUserAction); 3023 } 3024 3025 public static final Parcelable.Creator<SessionInfo> 3026 CREATOR = new Parcelable.Creator<SessionInfo>() { 3027 @Override 3028 public SessionInfo createFromParcel(Parcel p) { 3029 return new SessionInfo(p); 3030 } 3031 3032 @Override 3033 public SessionInfo[] newArray(int size) { 3034 return new SessionInfo[size]; 3035 } 3036 }; 3037 } 3038 } 3039