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 the session ID of the multi-package session that this belongs to or 1436 * {@link SessionInfo#INVALID_ID} if it does not belong to a multi-package session. 1437 */ getParentSessionId()1438 public int getParentSessionId() { 1439 try { 1440 return mSession.getParentSessionId(); 1441 } catch (RemoteException e) { 1442 throw e.rethrowFromSystemServer(); 1443 } 1444 } 1445 1446 /** 1447 * @return the set of session IDs that will be committed atomically when this session is 1448 * committed if this is a multi-package session or null if none exist. 1449 */ 1450 @NonNull getChildSessionIds()1451 public int[] getChildSessionIds() { 1452 try { 1453 return mSession.getChildSessionIds(); 1454 } catch (RemoteException e) { 1455 throw e.rethrowFromSystemServer(); 1456 } 1457 } 1458 1459 /** 1460 * Adds a session ID to the set of sessions that will be committed atomically 1461 * when this session is committed. 1462 * 1463 * <p>If the parent is staged or has rollback enabled, all children must have 1464 * the same properties.</p> 1465 * <p>If the parent is abandoned, all children will also be abandoned.</p> 1466 * 1467 * @param sessionId the session ID to add to this multi-package session. 1468 */ addChildSessionId(int sessionId)1469 public void addChildSessionId(int sessionId) { 1470 try { 1471 mSession.addChildSessionId(sessionId); 1472 } catch (RemoteException e) { 1473 e.rethrowFromSystemServer(); 1474 } 1475 } 1476 1477 /** 1478 * Removes a session ID from the set of sessions that will be committed 1479 * atomically when this session is committed. 1480 * 1481 * @param sessionId the session ID to remove from this multi-package session. 1482 */ removeChildSessionId(int sessionId)1483 public void removeChildSessionId(int sessionId) { 1484 try { 1485 mSession.removeChildSessionId(sessionId); 1486 } catch (RemoteException e) { 1487 e.rethrowFromSystemServer(); 1488 } 1489 } 1490 } 1491 1492 /** 1493 * Parameters for creating a new {@link PackageInstaller.Session}. 1494 */ 1495 public static class SessionParams implements Parcelable { 1496 1497 /** {@hide} */ 1498 public static final int MODE_INVALID = -1; 1499 1500 /** 1501 * Mode for an install session whose staged APKs should fully replace any 1502 * existing APKs for the target app. 1503 */ 1504 public static final int MODE_FULL_INSTALL = 1; 1505 1506 /** 1507 * Mode for an install session that should inherit any existing APKs for the 1508 * target app, unless they have been explicitly overridden (based on split 1509 * name) by the session. For example, this can be used to add one or more 1510 * split APKs to an existing installation. 1511 * <p> 1512 * If there are no existing APKs for the target app, this behaves like 1513 * {@link #MODE_FULL_INSTALL}. 1514 */ 1515 public static final int MODE_INHERIT_EXISTING = 2; 1516 1517 /** 1518 * Special constant to refer to all restricted permissions. 1519 */ 1520 public static final @NonNull Set<String> RESTRICTED_PERMISSIONS_ALL = new ArraySet<>(); 1521 1522 /** {@hide} */ 1523 public static final int UID_UNKNOWN = -1; 1524 1525 /** 1526 * This value is derived from the maximum file name length. No package above this limit 1527 * can ever be successfully installed on the device. 1528 * @hide 1529 */ 1530 public static final int MAX_PACKAGE_NAME_LENGTH = 255; 1531 1532 /** @hide */ 1533 @IntDef(prefix = {"USER_ACTION_"}, value = { 1534 USER_ACTION_UNSPECIFIED, 1535 USER_ACTION_REQUIRED, 1536 USER_ACTION_NOT_REQUIRED 1537 }) 1538 @Retention(RetentionPolicy.SOURCE) 1539 public @interface UserActionRequirement {} 1540 1541 /** 1542 * The installer did not call {@link SessionParams#setRequireUserAction(int)} to 1543 * specify whether user action should be required for the install. 1544 */ 1545 public static final int USER_ACTION_UNSPECIFIED = 0; 1546 1547 /** 1548 * The installer called {@link SessionParams#setRequireUserAction(int)} with 1549 * {@code true} to require user action for the install to complete. 1550 */ 1551 public static final int USER_ACTION_REQUIRED = 1; 1552 1553 /** 1554 * The installer called {@link SessionParams#setRequireUserAction(int)} with 1555 * {@code false} to request that user action not be required for this install. 1556 */ 1557 public static final int USER_ACTION_NOT_REQUIRED = 2; 1558 1559 /** {@hide} */ 1560 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) 1561 public int mode = MODE_INVALID; 1562 /** {@hide} */ 1563 @UnsupportedAppUsage 1564 public int installFlags = PackageManager.INSTALL_ALL_WHITELIST_RESTRICTED_PERMISSIONS; 1565 /** {@hide} */ 1566 public int installLocation = PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY; 1567 /** {@hide} */ 1568 public @InstallReason int installReason = PackageManager.INSTALL_REASON_UNKNOWN; 1569 /** 1570 * {@hide} 1571 * 1572 * This flag indicates which installation scenario best describes this session. The system 1573 * may use this value when making decisions about how to handle the installation, such as 1574 * prioritizing system health or user experience. 1575 */ 1576 public @InstallScenario int installScenario = PackageManager.INSTALL_SCENARIO_DEFAULT; 1577 /** {@hide} */ 1578 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 1579 public long sizeBytes = -1; 1580 /** {@hide} */ 1581 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) 1582 public String appPackageName; 1583 /** {@hide} */ 1584 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 1585 public Bitmap appIcon; 1586 /** {@hide} */ 1587 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) 1588 public String appLabel; 1589 /** {@hide} */ 1590 public long appIconLastModified = -1; 1591 /** {@hide} */ 1592 public Uri originatingUri; 1593 /** {@hide} */ 1594 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 1595 public int originatingUid = UID_UNKNOWN; 1596 /** {@hide} */ 1597 public Uri referrerUri; 1598 /** {@hide} */ 1599 public String abiOverride; 1600 /** {@hide} */ 1601 public String volumeUuid; 1602 /** {@hide} */ 1603 public String[] grantedRuntimePermissions; 1604 /** {@hide} */ 1605 public List<String> whitelistedRestrictedPermissions; 1606 /** {@hide} */ 1607 public int autoRevokePermissionsMode = MODE_DEFAULT; 1608 /** {@hide} */ 1609 public String installerPackageName; 1610 /** {@hide} */ 1611 public boolean isMultiPackage; 1612 /** {@hide} */ 1613 public boolean isStaged; 1614 /** {@hide} */ 1615 public long requiredInstalledVersionCode = PackageManager.VERSION_CODE_HIGHEST; 1616 /** {@hide} */ 1617 public DataLoaderParams dataLoaderParams; 1618 /** {@hide} */ 1619 public int rollbackDataPolicy = PackageManager.RollbackDataPolicy.RESTORE; 1620 /** {@hide} */ 1621 public boolean forceQueryableOverride; 1622 /** {@hide} */ 1623 public int requireUserAction = USER_ACTION_UNSPECIFIED; 1624 1625 /** 1626 * Construct parameters for a new package install session. 1627 * 1628 * @param mode one of {@link #MODE_FULL_INSTALL} or 1629 * {@link #MODE_INHERIT_EXISTING} describing how the session 1630 * should interact with an existing app. 1631 */ SessionParams(int mode)1632 public SessionParams(int mode) { 1633 this.mode = mode; 1634 } 1635 1636 /** {@hide} */ SessionParams(Parcel source)1637 public SessionParams(Parcel source) { 1638 mode = source.readInt(); 1639 installFlags = source.readInt(); 1640 installLocation = source.readInt(); 1641 installReason = source.readInt(); 1642 installScenario = source.readInt(); 1643 sizeBytes = source.readLong(); 1644 appPackageName = source.readString(); 1645 appIcon = source.readParcelable(null); 1646 appLabel = source.readString(); 1647 originatingUri = source.readParcelable(null); 1648 originatingUid = source.readInt(); 1649 referrerUri = source.readParcelable(null); 1650 abiOverride = source.readString(); 1651 volumeUuid = source.readString(); 1652 grantedRuntimePermissions = source.readStringArray(); 1653 whitelistedRestrictedPermissions = source.createStringArrayList(); 1654 autoRevokePermissionsMode = source.readInt(); 1655 installerPackageName = source.readString(); 1656 isMultiPackage = source.readBoolean(); 1657 isStaged = source.readBoolean(); 1658 forceQueryableOverride = source.readBoolean(); 1659 requiredInstalledVersionCode = source.readLong(); 1660 DataLoaderParamsParcel dataLoaderParamsParcel = source.readParcelable( 1661 DataLoaderParamsParcel.class.getClassLoader()); 1662 if (dataLoaderParamsParcel != null) { 1663 dataLoaderParams = new DataLoaderParams(dataLoaderParamsParcel); 1664 } 1665 rollbackDataPolicy = source.readInt(); 1666 requireUserAction = source.readInt(); 1667 } 1668 1669 /** {@hide} */ copy()1670 public SessionParams copy() { 1671 SessionParams ret = new SessionParams(mode); 1672 ret.installFlags = installFlags; 1673 ret.installLocation = installLocation; 1674 ret.installReason = installReason; 1675 ret.installScenario = installScenario; 1676 ret.sizeBytes = sizeBytes; 1677 ret.appPackageName = appPackageName; 1678 ret.appIcon = appIcon; // not a copy. 1679 ret.appLabel = appLabel; 1680 ret.originatingUri = originatingUri; // not a copy, but immutable. 1681 ret.originatingUid = originatingUid; 1682 ret.referrerUri = referrerUri; // not a copy, but immutable. 1683 ret.abiOverride = abiOverride; 1684 ret.volumeUuid = volumeUuid; 1685 ret.grantedRuntimePermissions = grantedRuntimePermissions; 1686 ret.whitelistedRestrictedPermissions = whitelistedRestrictedPermissions; 1687 ret.autoRevokePermissionsMode = autoRevokePermissionsMode; 1688 ret.installerPackageName = installerPackageName; 1689 ret.isMultiPackage = isMultiPackage; 1690 ret.isStaged = isStaged; 1691 ret.forceQueryableOverride = forceQueryableOverride; 1692 ret.requiredInstalledVersionCode = requiredInstalledVersionCode; 1693 ret.dataLoaderParams = dataLoaderParams; 1694 ret.rollbackDataPolicy = rollbackDataPolicy; 1695 ret.requireUserAction = requireUserAction; 1696 return ret; 1697 } 1698 1699 /** 1700 * Check if there are hidden options set. 1701 * 1702 * <p>Hidden options are those options that cannot be verified via public or system-api 1703 * methods on {@link SessionInfo}. 1704 * 1705 * @return {@code true} if any hidden option is set. 1706 * 1707 * @hide 1708 */ areHiddenOptionsSet()1709 public boolean areHiddenOptionsSet() { 1710 return (installFlags & (PackageManager.INSTALL_REQUEST_DOWNGRADE 1711 | PackageManager.INSTALL_ALLOW_DOWNGRADE 1712 | PackageManager.INSTALL_DONT_KILL_APP 1713 | PackageManager.INSTALL_INSTANT_APP 1714 | PackageManager.INSTALL_FULL_APP 1715 | PackageManager.INSTALL_VIRTUAL_PRELOAD 1716 | PackageManager.INSTALL_ALLOCATE_AGGRESSIVE)) != installFlags 1717 || abiOverride != null || volumeUuid != null; 1718 } 1719 1720 /** 1721 * Provide value of {@link PackageInfo#installLocation}, which may be used 1722 * to determine where the app will be staged. Defaults to 1723 * {@link PackageInfo#INSTALL_LOCATION_INTERNAL_ONLY}. 1724 */ setInstallLocation(int installLocation)1725 public void setInstallLocation(int installLocation) { 1726 this.installLocation = installLocation; 1727 } 1728 1729 /** 1730 * Optionally indicate the total size (in bytes) of all APKs that will be 1731 * delivered in this session. The system may use this to ensure enough disk 1732 * space exists before proceeding, or to estimate container size for 1733 * installations living on external storage. 1734 * 1735 * @see PackageInfo#INSTALL_LOCATION_AUTO 1736 * @see PackageInfo#INSTALL_LOCATION_PREFER_EXTERNAL 1737 */ setSize(long sizeBytes)1738 public void setSize(long sizeBytes) { 1739 this.sizeBytes = sizeBytes; 1740 } 1741 1742 /** 1743 * Optionally set the package name of the app being installed. It's strongly 1744 * recommended that you provide this value when known, so that observers can 1745 * communicate installing apps to users. 1746 * <p> 1747 * If the APKs staged in the session aren't consistent with this package 1748 * name, the install will fail. Regardless of this value, all APKs in the 1749 * app must have the same package name. 1750 */ setAppPackageName(@ullable String appPackageName)1751 public void setAppPackageName(@Nullable String appPackageName) { 1752 this.appPackageName = appPackageName; 1753 } 1754 1755 /** 1756 * Optionally set an icon representing the app being installed. This should 1757 * be roughly {@link ActivityManager#getLauncherLargeIconSize()} in both 1758 * dimensions. 1759 */ setAppIcon(@ullable Bitmap appIcon)1760 public void setAppIcon(@Nullable Bitmap appIcon) { 1761 this.appIcon = appIcon; 1762 } 1763 1764 /** 1765 * Optionally set a label representing the app being installed. 1766 * 1767 * This value will be trimmed to the first 1000 characters. 1768 */ setAppLabel(@ullable CharSequence appLabel)1769 public void setAppLabel(@Nullable CharSequence appLabel) { 1770 this.appLabel = (appLabel != null) ? appLabel.toString() : null; 1771 } 1772 1773 /** 1774 * Optionally set the URI where this package was downloaded from. This is 1775 * informational and may be used as a signal for anti-malware purposes. 1776 * 1777 * @see Intent#EXTRA_ORIGINATING_URI 1778 */ setOriginatingUri(@ullable Uri originatingUri)1779 public void setOriginatingUri(@Nullable Uri originatingUri) { 1780 this.originatingUri = originatingUri; 1781 } 1782 1783 /** 1784 * Sets the UID that initiated the package installation. This is informational 1785 * and may be used as a signal for anti-malware purposes. 1786 */ setOriginatingUid(int originatingUid)1787 public void setOriginatingUid(int originatingUid) { 1788 this.originatingUid = originatingUid; 1789 } 1790 1791 /** 1792 * Optionally set the URI that referred you to install this package. This is 1793 * informational and may be used as a signal for anti-malware purposes. 1794 * 1795 * @see Intent#EXTRA_REFERRER 1796 */ setReferrerUri(@ullable Uri referrerUri)1797 public void setReferrerUri(@Nullable Uri referrerUri) { 1798 this.referrerUri = referrerUri; 1799 } 1800 1801 /** 1802 * Sets which runtime permissions to be granted to the package at installation. 1803 * 1804 * @param permissions The permissions to grant or null to grant all runtime 1805 * permissions. 1806 * 1807 * @hide 1808 */ 1809 @SystemApi 1810 @RequiresPermission(android.Manifest.permission.INSTALL_GRANT_RUNTIME_PERMISSIONS) setGrantedRuntimePermissions(String[] permissions)1811 public void setGrantedRuntimePermissions(String[] permissions) { 1812 installFlags |= PackageManager.INSTALL_GRANT_RUNTIME_PERMISSIONS; 1813 this.grantedRuntimePermissions = permissions; 1814 } 1815 1816 /** 1817 * Sets which restricted permissions to be allowlisted for the app. Allowlisting 1818 * is not granting the permissions, rather it allows the app to hold permissions 1819 * which are otherwise restricted. Allowlisting a non restricted permission has 1820 * no effect. 1821 * 1822 * <p> Permissions can be hard restricted which means that the app cannot hold 1823 * them or soft restricted where the app can hold the permission but in a weaker 1824 * form. Whether a permission is {@link PermissionInfo#FLAG_HARD_RESTRICTED hard 1825 * restricted} or {@link PermissionInfo#FLAG_SOFT_RESTRICTED soft restricted} 1826 * depends on the permission declaration. Allowlisting a hard restricted permission 1827 * allows the app to hold that permission and allowlisting a soft restricted 1828 * permission allows the app to hold the permission in its full, unrestricted form. 1829 * 1830 * <p> Permissions can also be immutably restricted which means that the allowlist 1831 * state of the permission can be determined only at install time and cannot be 1832 * changed on updated or at a later point via the package manager APIs. 1833 * 1834 * <p>Initially, all restricted permissions are allowlisted but you can change 1835 * which ones are allowlisted by calling this method or the corresponding ones 1836 * on the {@link PackageManager}. Only soft or hard restricted permissions on the current 1837 * Android version are supported and any invalid entries will be removed. 1838 * 1839 * @see PackageManager#addWhitelistedRestrictedPermission(String, String, int) 1840 * @see PackageManager#removeWhitelistedRestrictedPermission(String, String, int) 1841 */ setWhitelistedRestrictedPermissions(@ullable Set<String> permissions)1842 public void setWhitelistedRestrictedPermissions(@Nullable Set<String> permissions) { 1843 if (permissions == RESTRICTED_PERMISSIONS_ALL) { 1844 installFlags |= PackageManager.INSTALL_ALL_WHITELIST_RESTRICTED_PERMISSIONS; 1845 whitelistedRestrictedPermissions = null; 1846 } else { 1847 installFlags &= ~PackageManager.INSTALL_ALL_WHITELIST_RESTRICTED_PERMISSIONS; 1848 whitelistedRestrictedPermissions = (permissions != null) 1849 ? new ArrayList<>(permissions) : null; 1850 } 1851 } 1852 1853 /** 1854 * Sets whether permissions should be auto-revoked if this package is unused for an 1855 * extended periodd of time. 1856 * 1857 * It's disabled by default but generally the installer should enable it for most packages, 1858 * excluding only those where doing so might cause breakage that cannot be easily addressed 1859 * by simply re-requesting the permission(s). 1860 * 1861 * If user explicitly enabled or disabled it via settings, this call is ignored. 1862 * 1863 * @param shouldAutoRevoke whether permissions should be auto-revoked. 1864 * 1865 * @deprecated No longer used 1866 */ 1867 @Deprecated setAutoRevokePermissionsMode(boolean shouldAutoRevoke)1868 public void setAutoRevokePermissionsMode(boolean shouldAutoRevoke) { 1869 autoRevokePermissionsMode = shouldAutoRevoke ? MODE_ALLOWED : MODE_IGNORED; 1870 } 1871 1872 /** 1873 * Request that rollbacks be enabled or disabled for the given upgrade with rollback data 1874 * policy set to RESTORE. 1875 * 1876 * <p>If the parent session is staged or has rollback enabled, all children sessions 1877 * must have the same properties. 1878 * 1879 * @param enable set to {@code true} to enable, {@code false} to disable 1880 * @see SessionParams#setEnableRollback(boolean, int) 1881 * @hide 1882 */ 1883 @SystemApi setEnableRollback(boolean enable)1884 public void setEnableRollback(boolean enable) { 1885 if (enable) { 1886 installFlags |= PackageManager.INSTALL_ENABLE_ROLLBACK; 1887 } else { 1888 installFlags &= ~PackageManager.INSTALL_ENABLE_ROLLBACK; 1889 } 1890 rollbackDataPolicy = PackageManager.RollbackDataPolicy.RESTORE; 1891 } 1892 1893 /** 1894 * Request that rollbacks be enabled or disabled for the given upgrade. 1895 * 1896 * <p>If the parent session is staged or has rollback enabled, all children sessions 1897 * must have the same properties. 1898 * 1899 * <p> For a multi-package install, this method must be called on each child session to 1900 * specify rollback data policies explicitly. Note each child session is allowed to have 1901 * different policies. 1902 * 1903 * @param enable set to {@code true} to enable, {@code false} to disable 1904 * @param dataPolicy the rollback data policy for this session 1905 * @hide 1906 */ 1907 @SystemApi setEnableRollback(boolean enable, @PackageManager.RollbackDataPolicy int dataPolicy)1908 public void setEnableRollback(boolean enable, 1909 @PackageManager.RollbackDataPolicy int dataPolicy) { 1910 if (enable) { 1911 installFlags |= PackageManager.INSTALL_ENABLE_ROLLBACK; 1912 } else { 1913 installFlags &= ~PackageManager.INSTALL_ENABLE_ROLLBACK; 1914 } 1915 rollbackDataPolicy = dataPolicy; 1916 } 1917 1918 1919 /** 1920 * @deprecated use {@link #setRequestDowngrade(boolean)}. 1921 * {@hide} 1922 */ 1923 @SystemApi 1924 @Deprecated setAllowDowngrade(boolean allowDowngrade)1925 public void setAllowDowngrade(boolean allowDowngrade) { 1926 setRequestDowngrade(allowDowngrade); 1927 } 1928 1929 /** {@hide} */ 1930 @SystemApi setRequestDowngrade(boolean requestDowngrade)1931 public void setRequestDowngrade(boolean requestDowngrade) { 1932 if (requestDowngrade) { 1933 installFlags |= PackageManager.INSTALL_REQUEST_DOWNGRADE; 1934 } else { 1935 installFlags &= ~PackageManager.INSTALL_REQUEST_DOWNGRADE; 1936 } 1937 } 1938 1939 /** 1940 * Require the given version of the package be installed. 1941 * The install will only be allowed if the existing version code of 1942 * the package installed on the device matches the given version code. 1943 * Use {@link * PackageManager#VERSION_CODE_HIGHEST} to allow 1944 * installation regardless of the currently installed package version. 1945 * 1946 * @hide 1947 */ setRequiredInstalledVersionCode(long versionCode)1948 public void setRequiredInstalledVersionCode(long versionCode) { 1949 requiredInstalledVersionCode = versionCode; 1950 } 1951 1952 /** {@hide} */ setInstallFlagsForcePermissionPrompt()1953 public void setInstallFlagsForcePermissionPrompt() { 1954 installFlags |= PackageManager.INSTALL_FORCE_PERMISSION_PROMPT; 1955 } 1956 1957 /** {@hide} */ 1958 @SystemApi setDontKillApp(boolean dontKillApp)1959 public void setDontKillApp(boolean dontKillApp) { 1960 if (dontKillApp) { 1961 installFlags |= PackageManager.INSTALL_DONT_KILL_APP; 1962 } else { 1963 installFlags &= ~PackageManager.INSTALL_DONT_KILL_APP; 1964 } 1965 } 1966 1967 /** {@hide} */ 1968 @SystemApi setInstallAsInstantApp(boolean isInstantApp)1969 public void setInstallAsInstantApp(boolean isInstantApp) { 1970 if (isInstantApp) { 1971 installFlags |= PackageManager.INSTALL_INSTANT_APP; 1972 installFlags &= ~PackageManager.INSTALL_FULL_APP; 1973 } else { 1974 installFlags &= ~PackageManager.INSTALL_INSTANT_APP; 1975 installFlags |= PackageManager.INSTALL_FULL_APP; 1976 } 1977 } 1978 1979 /** 1980 * Sets the install as a virtual preload. Will only have effect when called 1981 * by the verifier. 1982 * {@hide} 1983 */ 1984 @SystemApi setInstallAsVirtualPreload()1985 public void setInstallAsVirtualPreload() { 1986 installFlags |= PackageManager.INSTALL_VIRTUAL_PRELOAD; 1987 } 1988 1989 /** 1990 * Set the reason for installing this package. 1991 * <p> 1992 * The install reason should be a pre-defined integer. The behavior is 1993 * undefined if other values are used. 1994 * 1995 * @see PackageManager#INSTALL_REASON_UNKNOWN 1996 * @see PackageManager#INSTALL_REASON_POLICY 1997 * @see PackageManager#INSTALL_REASON_DEVICE_RESTORE 1998 * @see PackageManager#INSTALL_REASON_DEVICE_SETUP 1999 * @see PackageManager#INSTALL_REASON_USER 2000 */ setInstallReason(@nstallReason int installReason)2001 public void setInstallReason(@InstallReason int installReason) { 2002 this.installReason = installReason; 2003 } 2004 2005 /** {@hide} */ 2006 @SystemApi 2007 @RequiresPermission(android.Manifest.permission.ALLOCATE_AGGRESSIVE) setAllocateAggressive(boolean allocateAggressive)2008 public void setAllocateAggressive(boolean allocateAggressive) { 2009 if (allocateAggressive) { 2010 installFlags |= PackageManager.INSTALL_ALLOCATE_AGGRESSIVE; 2011 } else { 2012 installFlags &= ~PackageManager.INSTALL_ALLOCATE_AGGRESSIVE; 2013 } 2014 } 2015 2016 /** 2017 * @hide 2018 */ 2019 @TestApi setInstallFlagAllowTest()2020 public void setInstallFlagAllowTest() { 2021 installFlags |= PackageManager.INSTALL_ALLOW_TEST; 2022 } 2023 2024 /** 2025 * Set the installer package for the app. 2026 * 2027 * By default this is the app that created the {@link PackageInstaller} object. 2028 * 2029 * @param installerPackageName name of the installer package 2030 * {@hide} 2031 */ 2032 @TestApi setInstallerPackageName(@ullable String installerPackageName)2033 public void setInstallerPackageName(@Nullable String installerPackageName) { 2034 this.installerPackageName = installerPackageName; 2035 } 2036 2037 /** 2038 * Set this session to be the parent of a multi-package install. 2039 * 2040 * A multi-package install session contains no APKs and only references other install 2041 * sessions via ID. When a multi-package session is committed, all of its children 2042 * are committed to the system in an atomic manner. If any children fail to install, 2043 * all of them do, including the multi-package session. 2044 */ setMultiPackage()2045 public void setMultiPackage() { 2046 this.isMultiPackage = true; 2047 } 2048 2049 /** 2050 * Set this session to be staged to be installed at reboot. 2051 * 2052 * Staged sessions are scheduled to be installed at next reboot. Staged sessions can also be 2053 * multi-package. In that case, if any of the children sessions fail to install at reboot, 2054 * all the other children sessions are aborted as well. 2055 * 2056 * <p>If the parent session is staged or has rollback enabled, all children sessions 2057 * must have the same properties. 2058 * 2059 * {@hide} 2060 */ 2061 @SystemApi 2062 @RequiresPermission(Manifest.permission.INSTALL_PACKAGES) setStaged()2063 public void setStaged() { 2064 this.isStaged = true; 2065 } 2066 2067 /** 2068 * Set this session to be installing an APEX package. 2069 * 2070 * {@hide} 2071 */ 2072 @SystemApi 2073 @RequiresPermission(Manifest.permission.INSTALL_PACKAGES) setInstallAsApex()2074 public void setInstallAsApex() { 2075 installFlags |= PackageManager.INSTALL_APEX; 2076 } 2077 2078 /** @hide */ getEnableRollback()2079 public boolean getEnableRollback() { 2080 return (installFlags & PackageManager.INSTALL_ENABLE_ROLLBACK) != 0; 2081 } 2082 2083 /** 2084 * Set the data loader params for the session. 2085 * This also switches installation into data loading mode and disallow direct writes into 2086 * staging folder. 2087 * 2088 * @see android.service.dataloader.DataLoaderService.DataLoader 2089 * 2090 * {@hide} 2091 */ 2092 @SystemApi 2093 @RequiresPermission(allOf = { 2094 Manifest.permission.INSTALL_PACKAGES, 2095 Manifest.permission.USE_INSTALLER_V2}) setDataLoaderParams(@onNull DataLoaderParams dataLoaderParams)2096 public void setDataLoaderParams(@NonNull DataLoaderParams dataLoaderParams) { 2097 this.dataLoaderParams = dataLoaderParams; 2098 } 2099 2100 /** 2101 * 2102 * {@hide} 2103 */ setForceQueryable()2104 public void setForceQueryable() { 2105 this.forceQueryableOverride = true; 2106 } 2107 2108 /** 2109 * Optionally indicate whether user action should be required when the session is 2110 * committed. 2111 * <p> 2112 * Defaults to {@link #USER_ACTION_UNSPECIFIED} unless otherwise set. When unspecified for 2113 * installers using the 2114 * {@link android.Manifest.permission#REQUEST_INSTALL_PACKAGES REQUEST_INSTALL_PACKAGES} 2115 * permission will behave as if set to {@link #USER_ACTION_REQUIRED}, and 2116 * {@link #USER_ACTION_NOT_REQUIRED} otherwise. When {@code requireUserAction} is set to 2117 * {@link #USER_ACTION_REQUIRED}, installers will receive a 2118 * {@link #STATUS_PENDING_USER_ACTION} callback once the session is committed, indicating 2119 * that user action is required for the install to proceed. 2120 * <p> 2121 * For installers that have been granted the 2122 * {@link android.Manifest.permission#REQUEST_INSTALL_PACKAGES REQUEST_INSTALL_PACKAGES} 2123 * permission, user action will not be required when all of the following conditions are 2124 * met: 2125 * 2126 * <ul> 2127 * <li>{@code requireUserAction} is set to {@link #USER_ACTION_NOT_REQUIRED}.</li> 2128 * <li>The app being installed targets {@link android.os.Build.VERSION_CODES#Q API 29} 2129 * or higher.</li> 2130 * <li>The installer is the {@link InstallSourceInfo#getInstallingPackageName() 2131 * installer of record} of an existing version of the app (in other words, this install 2132 * session is an app update) or the installer is updating itself.</li> 2133 * <li>The installer declares the 2134 * {@link android.Manifest.permission#UPDATE_PACKAGES_WITHOUT_USER_ACTION 2135 * UPDATE_PACKAGES_WITHOUT_USER_ACTION} permission.</li> 2136 * </ul> 2137 * <p> 2138 * Note: The target API level requirement will advance in future Android versions. 2139 * Session owners should always be prepared to handle {@link #STATUS_PENDING_USER_ACTION}. 2140 * 2141 * @param requireUserAction whether user action should be required. 2142 */ setRequireUserAction( @essionParams.UserActionRequirement int requireUserAction)2143 public void setRequireUserAction( 2144 @SessionParams.UserActionRequirement int requireUserAction) { 2145 if (requireUserAction != USER_ACTION_UNSPECIFIED 2146 && requireUserAction != USER_ACTION_REQUIRED 2147 && requireUserAction != USER_ACTION_NOT_REQUIRED) { 2148 throw new IllegalArgumentException("requireUserAction set as invalid value of " 2149 + requireUserAction + ", but must be one of [" 2150 + "USER_ACTION_UNSPECIFIED, USER_ACTION_REQUIRED, USER_ACTION_NOT_REQUIRED" 2151 + "]"); 2152 } 2153 this.requireUserAction = requireUserAction; 2154 } 2155 2156 /** 2157 * Sets the install scenario for this session, which describes the expected user journey. 2158 */ setInstallScenario(@nstallScenario int installScenario)2159 public void setInstallScenario(@InstallScenario int installScenario) { 2160 this.installScenario = installScenario; 2161 } 2162 2163 /** {@hide} */ dump(IndentingPrintWriter pw)2164 public void dump(IndentingPrintWriter pw) { 2165 pw.printPair("mode", mode); 2166 pw.printHexPair("installFlags", installFlags); 2167 pw.printPair("installLocation", installLocation); 2168 pw.printPair("installReason", installReason); 2169 pw.printPair("installScenario", installScenario); 2170 pw.printPair("sizeBytes", sizeBytes); 2171 pw.printPair("appPackageName", appPackageName); 2172 pw.printPair("appIcon", (appIcon != null)); 2173 pw.printPair("appLabel", appLabel); 2174 pw.printPair("originatingUri", originatingUri); 2175 pw.printPair("originatingUid", originatingUid); 2176 pw.printPair("referrerUri", referrerUri); 2177 pw.printPair("abiOverride", abiOverride); 2178 pw.printPair("volumeUuid", volumeUuid); 2179 pw.printPair("grantedRuntimePermissions", grantedRuntimePermissions); 2180 pw.printPair("whitelistedRestrictedPermissions", whitelistedRestrictedPermissions); 2181 pw.printPair("autoRevokePermissions", autoRevokePermissionsMode); 2182 pw.printPair("installerPackageName", installerPackageName); 2183 pw.printPair("isMultiPackage", isMultiPackage); 2184 pw.printPair("isStaged", isStaged); 2185 pw.printPair("forceQueryable", forceQueryableOverride); 2186 pw.printPair("requireUserAction", SessionInfo.userActionToString(requireUserAction)); 2187 pw.printPair("requiredInstalledVersionCode", requiredInstalledVersionCode); 2188 pw.printPair("dataLoaderParams", dataLoaderParams); 2189 pw.printPair("rollbackDataPolicy", rollbackDataPolicy); 2190 pw.println(); 2191 } 2192 2193 @Override describeContents()2194 public int describeContents() { 2195 return 0; 2196 } 2197 2198 @Override writeToParcel(Parcel dest, int flags)2199 public void writeToParcel(Parcel dest, int flags) { 2200 dest.writeInt(mode); 2201 dest.writeInt(installFlags); 2202 dest.writeInt(installLocation); 2203 dest.writeInt(installReason); 2204 dest.writeInt(installScenario); 2205 dest.writeLong(sizeBytes); 2206 dest.writeString(appPackageName); 2207 dest.writeParcelable(appIcon, flags); 2208 dest.writeString(appLabel); 2209 dest.writeParcelable(originatingUri, flags); 2210 dest.writeInt(originatingUid); 2211 dest.writeParcelable(referrerUri, flags); 2212 dest.writeString(abiOverride); 2213 dest.writeString(volumeUuid); 2214 dest.writeStringArray(grantedRuntimePermissions); 2215 dest.writeStringList(whitelistedRestrictedPermissions); 2216 dest.writeInt(autoRevokePermissionsMode); 2217 dest.writeString(installerPackageName); 2218 dest.writeBoolean(isMultiPackage); 2219 dest.writeBoolean(isStaged); 2220 dest.writeBoolean(forceQueryableOverride); 2221 dest.writeLong(requiredInstalledVersionCode); 2222 if (dataLoaderParams != null) { 2223 dest.writeParcelable(dataLoaderParams.getData(), flags); 2224 } else { 2225 dest.writeParcelable(null, flags); 2226 } 2227 dest.writeInt(rollbackDataPolicy); 2228 dest.writeInt(requireUserAction); 2229 } 2230 2231 public static final Parcelable.Creator<SessionParams> 2232 CREATOR = new Parcelable.Creator<SessionParams>() { 2233 @Override 2234 public SessionParams createFromParcel(Parcel p) { 2235 return new SessionParams(p); 2236 } 2237 2238 @Override 2239 public SessionParams[] newArray(int size) { 2240 return new SessionParams[size]; 2241 } 2242 }; 2243 } 2244 2245 /** 2246 * Details for an active install session. 2247 */ 2248 public static class SessionInfo implements Parcelable { 2249 2250 /** 2251 * A session ID that does not exist or is invalid. 2252 */ 2253 public static final int INVALID_ID = -1; 2254 /** {@hide} */ 2255 private static final int[] NO_SESSIONS = {}; 2256 2257 /** @hide */ 2258 @IntDef(prefix = { "STAGED_SESSION_" }, value = { 2259 STAGED_SESSION_NO_ERROR, 2260 STAGED_SESSION_VERIFICATION_FAILED, 2261 STAGED_SESSION_ACTIVATION_FAILED, 2262 STAGED_SESSION_UNKNOWN, 2263 STAGED_SESSION_CONFLICT}) 2264 @Retention(RetentionPolicy.SOURCE) 2265 public @interface StagedSessionErrorCode{} 2266 /** 2267 * Constant indicating that no error occurred during the preparation or the activation of 2268 * this staged session. 2269 */ 2270 public static final int STAGED_SESSION_NO_ERROR = 0; 2271 2272 /** 2273 * Constant indicating that an error occurred during the verification phase (pre-reboot) of 2274 * this staged session. 2275 */ 2276 public static final int STAGED_SESSION_VERIFICATION_FAILED = 1; 2277 2278 /** 2279 * Constant indicating that an error occurred during the activation phase (post-reboot) of 2280 * this staged session. 2281 */ 2282 public static final int STAGED_SESSION_ACTIVATION_FAILED = 2; 2283 2284 /** 2285 * Constant indicating that an unknown error occurred while processing this staged session. 2286 */ 2287 public static final int STAGED_SESSION_UNKNOWN = 3; 2288 2289 /** 2290 * Constant indicating that the session was in conflict with another staged session and had 2291 * to be sacrificed for resolution. 2292 */ 2293 public static final int STAGED_SESSION_CONFLICT = 4; 2294 userActionToString(int requireUserAction)2295 private static String userActionToString(int requireUserAction) { 2296 switch(requireUserAction) { 2297 case SessionParams.USER_ACTION_REQUIRED: 2298 return "REQUIRED"; 2299 case SessionParams.USER_ACTION_NOT_REQUIRED: 2300 return "NOT_REQUIRED"; 2301 default: 2302 return "UNSPECIFIED"; 2303 } 2304 } 2305 2306 /** {@hide} */ 2307 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) 2308 public int sessionId; 2309 /** {@hide} */ 2310 public int userId; 2311 /** {@hide} */ 2312 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) 2313 public String installerPackageName; 2314 /** {@hide} */ 2315 public String installerAttributionTag; 2316 /** {@hide} */ 2317 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 2318 public String resolvedBaseCodePath; 2319 /** {@hide} */ 2320 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) 2321 public float progress; 2322 /** {@hide} */ 2323 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 2324 public boolean sealed; 2325 /** {@hide} */ 2326 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) 2327 public boolean active; 2328 2329 /** {@hide} */ 2330 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) 2331 public int mode; 2332 /** {@hide} */ 2333 public @InstallReason int installReason; 2334 /** {@hide} */ 2335 public @InstallScenario int installScenario; 2336 /** {@hide} */ 2337 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) 2338 public long sizeBytes; 2339 /** {@hide} */ 2340 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) 2341 public String appPackageName; 2342 /** {@hide} */ 2343 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) 2344 public Bitmap appIcon; 2345 /** {@hide} */ 2346 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) 2347 public CharSequence appLabel; 2348 2349 /** {@hide} */ 2350 public int installLocation; 2351 /** {@hide} */ 2352 public Uri originatingUri; 2353 /** {@hide} */ 2354 public int originatingUid; 2355 /** {@hide} */ 2356 public Uri referrerUri; 2357 /** {@hide} */ 2358 public String[] grantedRuntimePermissions; 2359 /** {@hide}*/ 2360 public List<String> whitelistedRestrictedPermissions; 2361 /** {@hide}*/ 2362 public int autoRevokePermissionsMode = MODE_DEFAULT; 2363 /** {@hide} */ 2364 public int installFlags; 2365 /** {@hide} */ 2366 public boolean isMultiPackage; 2367 /** {@hide} */ 2368 public boolean isStaged; 2369 /** {@hide} */ 2370 public boolean forceQueryable; 2371 /** {@hide} */ 2372 public int parentSessionId = INVALID_ID; 2373 /** {@hide} */ 2374 public int[] childSessionIds = NO_SESSIONS; 2375 2376 /** {@hide} */ 2377 public boolean isStagedSessionApplied; 2378 /** {@hide} */ 2379 public boolean isStagedSessionReady; 2380 /** {@hide} */ 2381 public boolean isStagedSessionFailed; 2382 private int mStagedSessionErrorCode; 2383 private String mStagedSessionErrorMessage; 2384 2385 /** {@hide} */ 2386 public boolean isCommitted; 2387 2388 /** {@hide} */ 2389 public long createdMillis; 2390 2391 /** {@hide} */ 2392 public long updatedMillis; 2393 2394 /** {@hide} */ 2395 public int rollbackDataPolicy; 2396 2397 /** {@hide} */ 2398 public int requireUserAction; 2399 2400 /** {@hide} */ 2401 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) SessionInfo()2402 public SessionInfo() { 2403 } 2404 2405 /** {@hide} */ SessionInfo(Parcel source)2406 public SessionInfo(Parcel source) { 2407 sessionId = source.readInt(); 2408 userId = source.readInt(); 2409 installerPackageName = source.readString(); 2410 installerAttributionTag = source.readString(); 2411 resolvedBaseCodePath = source.readString(); 2412 progress = source.readFloat(); 2413 sealed = source.readInt() != 0; 2414 active = source.readInt() != 0; 2415 2416 mode = source.readInt(); 2417 installReason = source.readInt(); 2418 installScenario = source.readInt(); 2419 sizeBytes = source.readLong(); 2420 appPackageName = source.readString(); 2421 appIcon = source.readParcelable(null); 2422 appLabel = source.readString(); 2423 2424 installLocation = source.readInt(); 2425 originatingUri = source.readParcelable(null); 2426 originatingUid = source.readInt(); 2427 referrerUri = source.readParcelable(null); 2428 grantedRuntimePermissions = source.readStringArray(); 2429 whitelistedRestrictedPermissions = source.createStringArrayList(); 2430 autoRevokePermissionsMode = source.readInt(); 2431 2432 installFlags = source.readInt(); 2433 isMultiPackage = source.readBoolean(); 2434 isStaged = source.readBoolean(); 2435 forceQueryable = source.readBoolean(); 2436 parentSessionId = source.readInt(); 2437 childSessionIds = source.createIntArray(); 2438 if (childSessionIds == null) { 2439 childSessionIds = NO_SESSIONS; 2440 } 2441 isStagedSessionApplied = source.readBoolean(); 2442 isStagedSessionReady = source.readBoolean(); 2443 isStagedSessionFailed = source.readBoolean(); 2444 mStagedSessionErrorCode = source.readInt(); 2445 mStagedSessionErrorMessage = source.readString(); 2446 isCommitted = source.readBoolean(); 2447 rollbackDataPolicy = source.readInt(); 2448 createdMillis = source.readLong(); 2449 requireUserAction = source.readInt(); 2450 } 2451 2452 /** 2453 * Return the ID for this session. 2454 */ getSessionId()2455 public int getSessionId() { 2456 return sessionId; 2457 } 2458 2459 /** 2460 * Return the user associated with this session. 2461 */ getUser()2462 public @NonNull UserHandle getUser() { 2463 return new UserHandle(userId); 2464 } 2465 2466 /** 2467 * Return the package name of the app that owns this session. 2468 */ getInstallerPackageName()2469 public @Nullable String getInstallerPackageName() { 2470 return installerPackageName; 2471 } 2472 2473 /** 2474 * @return {@link android.content.Context#getAttributionTag attribution tag} of the context 2475 * that created this session 2476 */ getInstallerAttributionTag()2477 public @Nullable String getInstallerAttributionTag() { 2478 return installerAttributionTag; 2479 } 2480 2481 /** 2482 * Return current overall progress of this session, between 0 and 1. 2483 * <p> 2484 * Note that this progress may not directly correspond to the value 2485 * reported by 2486 * {@link PackageInstaller.Session#setStagingProgress(float)}, as the 2487 * system may carve out a portion of the overall progress to represent 2488 * its own internal installation work. 2489 */ getProgress()2490 public float getProgress() { 2491 return progress; 2492 } 2493 2494 /** 2495 * Return if this session is currently active. 2496 * <p> 2497 * A session is considered active whenever there is ongoing forward 2498 * progress being made, such as the installer holding an open 2499 * {@link Session} instance while streaming data into place, or the 2500 * system optimizing code as the result of 2501 * {@link Session#commit(IntentSender)}. 2502 * <p> 2503 * If the installer closes the {@link Session} without committing, the 2504 * session is considered inactive until the installer opens the session 2505 * again. 2506 */ isActive()2507 public boolean isActive() { 2508 return active; 2509 } 2510 2511 /** 2512 * Return if this session is sealed. 2513 * <p> 2514 * Once sealed, no further changes may be made to the session. A session 2515 * is sealed the moment {@link Session#commit(IntentSender)} is called. 2516 */ isSealed()2517 public boolean isSealed() { 2518 return sealed; 2519 } 2520 2521 /** 2522 * Return the reason for installing this package. 2523 * 2524 * @return The install reason. 2525 */ getInstallReason()2526 public @InstallReason int getInstallReason() { 2527 return installReason; 2528 } 2529 2530 /** {@hide} */ 2531 @Deprecated isOpen()2532 public boolean isOpen() { 2533 return isActive(); 2534 } 2535 2536 /** 2537 * Return the package name this session is working with. May be {@code null} 2538 * if unknown. 2539 */ getAppPackageName()2540 public @Nullable String getAppPackageName() { 2541 return appPackageName; 2542 } 2543 2544 /** 2545 * Return an icon representing the app being installed. May be {@code null} 2546 * if unavailable. 2547 */ getAppIcon()2548 public @Nullable Bitmap getAppIcon() { 2549 if (appIcon == null) { 2550 // Icon may have been omitted for calls that return bulk session 2551 // lists, so try fetching the specific icon. 2552 try { 2553 final SessionInfo info = AppGlobals.getPackageManager().getPackageInstaller() 2554 .getSessionInfo(sessionId); 2555 appIcon = (info != null) ? info.appIcon : null; 2556 } catch (RemoteException e) { 2557 throw e.rethrowFromSystemServer(); 2558 } 2559 } 2560 return appIcon; 2561 } 2562 2563 /** 2564 * Return a label representing the app being installed. May be {@code null} 2565 * if unavailable. 2566 */ getAppLabel()2567 public @Nullable CharSequence getAppLabel() { 2568 return appLabel; 2569 } 2570 2571 /** 2572 * Return an Intent that can be started to view details about this install 2573 * session. This may surface actions such as pause, resume, or cancel. 2574 * <p> 2575 * In some cases, a matching Activity may not exist, so ensure you safeguard 2576 * against this. 2577 * 2578 * @see PackageInstaller#ACTION_SESSION_DETAILS 2579 */ createDetailsIntent()2580 public @Nullable Intent createDetailsIntent() { 2581 final Intent intent = new Intent(PackageInstaller.ACTION_SESSION_DETAILS); 2582 intent.putExtra(PackageInstaller.EXTRA_SESSION_ID, sessionId); 2583 intent.setPackage(installerPackageName); 2584 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 2585 return intent; 2586 } 2587 2588 /** 2589 * Get the mode of the session as set in the constructor of the {@link SessionParams}. 2590 * 2591 * @return One of {@link SessionParams#MODE_FULL_INSTALL} 2592 * or {@link SessionParams#MODE_INHERIT_EXISTING} 2593 */ getMode()2594 public int getMode() { 2595 return mode; 2596 } 2597 2598 /** 2599 * Get the value set in {@link SessionParams#setInstallLocation(int)}. 2600 */ getInstallLocation()2601 public int getInstallLocation() { 2602 return installLocation; 2603 } 2604 2605 /** 2606 * Get the value as set in {@link SessionParams#setSize(long)}. 2607 * 2608 * <p>The value is a hint and does not have to match the actual size. 2609 */ getSize()2610 public long getSize() { 2611 return sizeBytes; 2612 } 2613 2614 /** 2615 * Get the value set in {@link SessionParams#setOriginatingUri(Uri)}. 2616 * Note: This value will only be non-null for the owner of the session. 2617 */ getOriginatingUri()2618 public @Nullable Uri getOriginatingUri() { 2619 return originatingUri; 2620 } 2621 2622 /** 2623 * Get the value set in {@link SessionParams#setOriginatingUid(int)}. 2624 */ getOriginatingUid()2625 public int getOriginatingUid() { 2626 return originatingUid; 2627 } 2628 2629 /** 2630 * Get the value set in {@link SessionParams#setReferrerUri(Uri)} 2631 * Note: This value will only be non-null for the owner of the session. 2632 */ getReferrerUri()2633 public @Nullable Uri getReferrerUri() { 2634 return referrerUri; 2635 } 2636 2637 /** 2638 * Get the value set in {@link SessionParams#setGrantedRuntimePermissions(String[])}. 2639 * 2640 * @hide 2641 */ 2642 @SystemApi getGrantedRuntimePermissions()2643 public @Nullable String[] getGrantedRuntimePermissions() { 2644 return grantedRuntimePermissions; 2645 } 2646 2647 /** 2648 * Get the value set in {@link SessionParams#setWhitelistedRestrictedPermissions(Set)}. 2649 * Note that if all permissions are allowlisted this method returns {@link 2650 * SessionParams#RESTRICTED_PERMISSIONS_ALL}. 2651 * 2652 * @hide 2653 */ 2654 @SystemApi getWhitelistedRestrictedPermissions()2655 public @NonNull Set<String> getWhitelistedRestrictedPermissions() { 2656 if ((installFlags & PackageManager.INSTALL_ALL_WHITELIST_RESTRICTED_PERMISSIONS) != 0) { 2657 return SessionParams.RESTRICTED_PERMISSIONS_ALL; 2658 } 2659 if (whitelistedRestrictedPermissions != null) { 2660 return new ArraySet<>(whitelistedRestrictedPermissions); 2661 } 2662 return Collections.emptySet(); 2663 } 2664 2665 /** 2666 * Get the status of whether permission auto-revocation should be allowed, ignored, or 2667 * deferred to manifest data. 2668 * 2669 * @see android.app.AppOpsManager#MODE_ALLOWED 2670 * @see android.app.AppOpsManager#MODE_IGNORED 2671 * @see android.app.AppOpsManager#MODE_DEFAULT 2672 * 2673 * @return the status of auto-revoke for this package 2674 * 2675 * @hide 2676 */ 2677 @SystemApi getAutoRevokePermissionsMode()2678 public int getAutoRevokePermissionsMode() { 2679 return autoRevokePermissionsMode; 2680 } 2681 2682 /** 2683 * Get the value set in {@link SessionParams#setAllowDowngrade(boolean)}. 2684 * 2685 * @deprecated use {@link #getRequestDowngrade()}. 2686 * @hide 2687 */ 2688 @SystemApi 2689 @Deprecated getAllowDowngrade()2690 public boolean getAllowDowngrade() { 2691 return getRequestDowngrade(); 2692 } 2693 2694 /** 2695 * Get the value set in {@link SessionParams#setRequestDowngrade(boolean)}. 2696 * 2697 * @hide 2698 */ 2699 @SystemApi getRequestDowngrade()2700 public boolean getRequestDowngrade() { 2701 return (installFlags & PackageManager.INSTALL_REQUEST_DOWNGRADE) != 0; 2702 } 2703 2704 /** 2705 * Get the value set in {@link SessionParams#setDontKillApp(boolean)}. 2706 * 2707 * @hide 2708 */ 2709 @SystemApi getDontKillApp()2710 public boolean getDontKillApp() { 2711 return (installFlags & PackageManager.INSTALL_DONT_KILL_APP) != 0; 2712 } 2713 2714 /** 2715 * Get if this session is to be installed as Instant Apps. 2716 * 2717 * @param isInstantApp an unused parameter and is ignored. 2718 * @return {@code true} if {@link SessionParams#setInstallAsInstantApp(boolean)} was called 2719 * with {@code true}; {@code false} if it was called with {@code false} or if it was not 2720 * called. 2721 * 2722 * @see #getInstallAsFullApp 2723 * 2724 * @hide 2725 */ 2726 @SystemApi getInstallAsInstantApp(boolean isInstantApp)2727 public boolean getInstallAsInstantApp(boolean isInstantApp) { 2728 return (installFlags & PackageManager.INSTALL_INSTANT_APP) != 0; 2729 } 2730 2731 /** 2732 * Get if this session is to be installed as full apps. 2733 * 2734 * @param isInstantApp an unused parameter and is ignored. 2735 * @return {@code true} if {@link SessionParams#setInstallAsInstantApp(boolean)} was called 2736 * with {@code false}; {code false} if it was called with {@code true} or if it was not 2737 * called. 2738 * 2739 * @see #getInstallAsInstantApp 2740 * 2741 * @hide 2742 */ 2743 @SystemApi getInstallAsFullApp(boolean isInstantApp)2744 public boolean getInstallAsFullApp(boolean isInstantApp) { 2745 return (installFlags & PackageManager.INSTALL_FULL_APP) != 0; 2746 } 2747 2748 /** 2749 * Get if {@link SessionParams#setInstallAsVirtualPreload()} was called. 2750 * 2751 * @hide 2752 */ 2753 @SystemApi getInstallAsVirtualPreload()2754 public boolean getInstallAsVirtualPreload() { 2755 return (installFlags & PackageManager.INSTALL_VIRTUAL_PRELOAD) != 0; 2756 } 2757 2758 /** 2759 * Return whether rollback is enabled or disabled for the given upgrade. 2760 * 2761 * @hide 2762 */ 2763 @SystemApi getEnableRollback()2764 public boolean getEnableRollback() { 2765 return (installFlags & PackageManager.INSTALL_ENABLE_ROLLBACK) != 0; 2766 } 2767 2768 /** 2769 * Get the value set in {@link SessionParams#setAllocateAggressive(boolean)}. 2770 * 2771 * @hide 2772 */ 2773 @SystemApi getAllocateAggressive()2774 public boolean getAllocateAggressive() { 2775 return (installFlags & PackageManager.INSTALL_ALLOCATE_AGGRESSIVE) != 0; 2776 } 2777 2778 2779 /** {@hide} */ 2780 @Deprecated getDetailsIntent()2781 public @Nullable Intent getDetailsIntent() { 2782 return createDetailsIntent(); 2783 } 2784 2785 /** 2786 * Returns true if this session is a multi-package session containing references to other 2787 * sessions. 2788 */ isMultiPackage()2789 public boolean isMultiPackage() { 2790 return isMultiPackage; 2791 } 2792 2793 /** 2794 * Returns true if this session is a staged session. 2795 */ isStaged()2796 public boolean isStaged() { 2797 return isStaged; 2798 } 2799 2800 /** 2801 * Return the data policy associated with the rollback for the given upgrade. 2802 * 2803 * @hide 2804 */ 2805 @SystemApi 2806 @PackageManager.RollbackDataPolicy getRollbackDataPolicy()2807 public int getRollbackDataPolicy() { 2808 return rollbackDataPolicy; 2809 } 2810 2811 /** 2812 * Returns true if this session is marked as forceQueryable 2813 * {@hide} 2814 */ isForceQueryable()2815 public boolean isForceQueryable() { 2816 return forceQueryable; 2817 } 2818 2819 /** 2820 * Returns {@code true} if this session is an active staged session. 2821 * 2822 * We consider a session active if it has been committed and it is either pending 2823 * verification, or will be applied at next reboot. 2824 * 2825 * <p>Staged session is active iff: 2826 * <ul> 2827 * <li>It is committed, i.e. {@link SessionInfo#isCommitted()} is {@code true}, and 2828 * <li>it is not applied, i.e. {@link SessionInfo#isStagedSessionApplied()} is {@code 2829 * false}, and 2830 * <li>it is not failed, i.e. {@link SessionInfo#isStagedSessionFailed()} is 2831 * {@code false}. 2832 * </ul> 2833 * 2834 * <p>In case of a multi-package session, reasoning above is applied to the parent session, 2835 * since that is the one that should have been {@link Session#commit committed}. 2836 */ isStagedSessionActive()2837 public boolean isStagedSessionActive() { 2838 return isStaged && isCommitted && !isStagedSessionApplied && !isStagedSessionFailed 2839 && !hasParentSessionId(); 2840 } 2841 2842 /** 2843 * Returns the parent multi-package session ID if this session belongs to one, 2844 * {@link #INVALID_ID} otherwise. 2845 */ getParentSessionId()2846 public int getParentSessionId() { 2847 return parentSessionId; 2848 } 2849 2850 /** 2851 * Returns true if session has a valid parent session, otherwise false. 2852 */ hasParentSessionId()2853 public boolean hasParentSessionId() { 2854 return parentSessionId != INVALID_ID; 2855 } 2856 2857 /** 2858 * Returns the set of session IDs that will be committed when this session is commited if 2859 * this session is a multi-package session. 2860 */ 2861 @NonNull getChildSessionIds()2862 public int[] getChildSessionIds() { 2863 return childSessionIds; 2864 } 2865 checkSessionIsStaged()2866 private void checkSessionIsStaged() { 2867 if (!isStaged) { 2868 throw new IllegalStateException("Session is not marked as staged."); 2869 } 2870 } 2871 2872 /** 2873 * Whether the staged session has been applied successfully, meaning that all of its 2874 * packages have been activated and no further action is required. 2875 * Only meaningful if {@code isStaged} is true. 2876 */ isStagedSessionApplied()2877 public boolean isStagedSessionApplied() { 2878 checkSessionIsStaged(); 2879 return isStagedSessionApplied; 2880 } 2881 2882 /** 2883 * Whether the staged session is ready to be applied at next reboot. Only meaningful if 2884 * {@code isStaged} is true. 2885 */ isStagedSessionReady()2886 public boolean isStagedSessionReady() { 2887 checkSessionIsStaged(); 2888 return isStagedSessionReady; 2889 } 2890 2891 /** 2892 * Whether something went wrong and the staged session is declared as failed, meaning that 2893 * it will be ignored at next reboot. Only meaningful if {@code isStaged} is true. 2894 */ isStagedSessionFailed()2895 public boolean isStagedSessionFailed() { 2896 checkSessionIsStaged(); 2897 return isStagedSessionFailed; 2898 } 2899 2900 /** 2901 * If something went wrong with a staged session, clients can check this error code to 2902 * understand which kind of failure happened. Only meaningful if {@code isStaged} is true. 2903 */ getStagedSessionErrorCode()2904 public @StagedSessionErrorCode int getStagedSessionErrorCode() { 2905 checkSessionIsStaged(); 2906 return mStagedSessionErrorCode; 2907 } 2908 2909 /** 2910 * Text description of the error code returned by {@code getStagedSessionErrorCode}, or 2911 * empty string if no error was encountered. 2912 */ getStagedSessionErrorMessage()2913 public @NonNull String getStagedSessionErrorMessage() { 2914 checkSessionIsStaged(); 2915 return mStagedSessionErrorMessage; 2916 } 2917 2918 /** {@hide} */ setStagedSessionErrorCode(@tagedSessionErrorCode int errorCode, String errorMessage)2919 public void setStagedSessionErrorCode(@StagedSessionErrorCode int errorCode, 2920 String errorMessage) { 2921 mStagedSessionErrorCode = errorCode; 2922 mStagedSessionErrorMessage = errorMessage; 2923 } 2924 2925 /** 2926 * Returns {@code true} if {@link Session#commit(IntentSender)}} was called for this 2927 * session. 2928 */ isCommitted()2929 public boolean isCommitted() { 2930 return isCommitted; 2931 } 2932 2933 /** 2934 * The timestamp of the initial creation of the session. 2935 */ getCreatedMillis()2936 public long getCreatedMillis() { 2937 return createdMillis; 2938 } 2939 2940 /** 2941 * The timestamp of the last update that occurred to the session, including changing of 2942 * states in case of staged sessions. 2943 */ 2944 @CurrentTimeMillisLong getUpdatedMillis()2945 public long getUpdatedMillis() { 2946 return updatedMillis; 2947 } 2948 2949 /** 2950 * Whether user action was required by the installer. 2951 * 2952 * <p> 2953 * Note: a return value of {@code USER_ACTION_NOT_REQUIRED} does not guarantee that the 2954 * install will not result in user action. 2955 * 2956 * @return {@link SessionParams#USER_ACTION_NOT_REQUIRED}, 2957 * {@link SessionParams#USER_ACTION_REQUIRED} or 2958 * {@link SessionParams#USER_ACTION_UNSPECIFIED} 2959 */ 2960 @SessionParams.UserActionRequirement getRequireUserAction()2961 public int getRequireUserAction() { 2962 return requireUserAction; 2963 } 2964 2965 @Override describeContents()2966 public int describeContents() { 2967 return 0; 2968 } 2969 2970 @Override writeToParcel(Parcel dest, int flags)2971 public void writeToParcel(Parcel dest, int flags) { 2972 dest.writeInt(sessionId); 2973 dest.writeInt(userId); 2974 dest.writeString(installerPackageName); 2975 dest.writeString(installerAttributionTag); 2976 dest.writeString(resolvedBaseCodePath); 2977 dest.writeFloat(progress); 2978 dest.writeInt(sealed ? 1 : 0); 2979 dest.writeInt(active ? 1 : 0); 2980 2981 dest.writeInt(mode); 2982 dest.writeInt(installReason); 2983 dest.writeInt(installScenario); 2984 dest.writeLong(sizeBytes); 2985 dest.writeString(appPackageName); 2986 dest.writeParcelable(appIcon, flags); 2987 dest.writeString(appLabel != null ? appLabel.toString() : null); 2988 2989 dest.writeInt(installLocation); 2990 dest.writeParcelable(originatingUri, flags); 2991 dest.writeInt(originatingUid); 2992 dest.writeParcelable(referrerUri, flags); 2993 dest.writeStringArray(grantedRuntimePermissions); 2994 dest.writeStringList(whitelistedRestrictedPermissions); 2995 dest.writeInt(autoRevokePermissionsMode); 2996 dest.writeInt(installFlags); 2997 dest.writeBoolean(isMultiPackage); 2998 dest.writeBoolean(isStaged); 2999 dest.writeBoolean(forceQueryable); 3000 dest.writeInt(parentSessionId); 3001 dest.writeIntArray(childSessionIds); 3002 dest.writeBoolean(isStagedSessionApplied); 3003 dest.writeBoolean(isStagedSessionReady); 3004 dest.writeBoolean(isStagedSessionFailed); 3005 dest.writeInt(mStagedSessionErrorCode); 3006 dest.writeString(mStagedSessionErrorMessage); 3007 dest.writeBoolean(isCommitted); 3008 dest.writeInt(rollbackDataPolicy); 3009 dest.writeLong(createdMillis); 3010 dest.writeInt(requireUserAction); 3011 } 3012 3013 public static final Parcelable.Creator<SessionInfo> 3014 CREATOR = new Parcelable.Creator<SessionInfo>() { 3015 @Override 3016 public SessionInfo createFromParcel(Parcel p) { 3017 return new SessionInfo(p); 3018 } 3019 3020 @Override 3021 public SessionInfo[] newArray(int size) { 3022 return new SessionInfo[size]; 3023 } 3024 }; 3025 } 3026 } 3027