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 import static android.content.pm.Checksum.TYPE_PARTIAL_MERKLE_ROOT_1M_SHA256; 23 import static android.content.pm.Checksum.TYPE_PARTIAL_MERKLE_ROOT_1M_SHA512; 24 import static android.content.pm.Checksum.TYPE_WHOLE_MD5; 25 import static android.content.pm.Checksum.TYPE_WHOLE_MERKLE_ROOT_4K_SHA256; 26 import static android.content.pm.Checksum.TYPE_WHOLE_SHA1; 27 import static android.content.pm.Checksum.TYPE_WHOLE_SHA256; 28 import static android.content.pm.Checksum.TYPE_WHOLE_SHA512; 29 import static android.content.pm.PackageInfo.INSTALL_LOCATION_AUTO; 30 import static android.content.pm.PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY; 31 import static android.content.pm.PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL; 32 33 import android.Manifest; 34 import android.annotation.CallbackExecutor; 35 import android.annotation.CurrentTimeMillisLong; 36 import android.annotation.DurationMillisLong; 37 import android.annotation.FlaggedApi; 38 import android.annotation.IntDef; 39 import android.annotation.NonNull; 40 import android.annotation.Nullable; 41 import android.annotation.RequiresPermission; 42 import android.annotation.SdkConstant; 43 import android.annotation.SdkConstant.SdkConstantType; 44 import android.annotation.SuppressLint; 45 import android.annotation.SystemApi; 46 import android.annotation.TestApi; 47 import android.app.ActivityManager; 48 import android.app.ActivityThread; 49 import android.app.AppGlobals; 50 import android.app.PendingIntent; 51 import android.compat.annotation.UnsupportedAppUsage; 52 import android.content.BroadcastReceiver; 53 import android.content.Context; 54 import android.content.Intent; 55 import android.content.IntentFilter; 56 import android.content.IntentSender; 57 import android.content.pm.PackageManager.DeleteFlags; 58 import android.content.pm.PackageManager.InstallReason; 59 import android.content.pm.PackageManager.InstallScenario; 60 import android.content.pm.parsing.ApkLiteParseUtils; 61 import android.content.pm.parsing.PackageLite; 62 import android.content.pm.parsing.result.ParseResult; 63 import android.content.pm.parsing.result.ParseTypeImpl; 64 import android.content.pm.verify.domain.DomainSet; 65 import android.graphics.Bitmap; 66 import android.icu.util.ULocale; 67 import android.net.Uri; 68 import android.os.Build; 69 import android.os.FileBridge; 70 import android.os.Handler; 71 import android.os.HandlerExecutor; 72 import android.os.Parcel; 73 import android.os.ParcelFileDescriptor; 74 import android.os.Parcelable; 75 import android.os.ParcelableException; 76 import android.os.PersistableBundle; 77 import android.os.RemoteCallback; 78 import android.os.RemoteException; 79 import android.os.SystemProperties; 80 import android.os.UserHandle; 81 import android.system.ErrnoException; 82 import android.system.Os; 83 import android.text.TextUtils; 84 import android.util.ArrayMap; 85 import android.util.ArraySet; 86 import android.util.ExceptionUtils; 87 88 import com.android.internal.content.InstallLocationUtils; 89 import com.android.internal.util.ArrayUtils; 90 import com.android.internal.util.DataClass; 91 import com.android.internal.util.IndentingPrintWriter; 92 import com.android.internal.util.Preconditions; 93 import com.android.internal.util.function.pooled.PooledLambda; 94 95 import java.io.Closeable; 96 import java.io.File; 97 import java.io.FileNotFoundException; 98 import java.io.IOException; 99 import java.io.InputStream; 100 import java.io.OutputStream; 101 import java.lang.annotation.Retention; 102 import java.lang.annotation.RetentionPolicy; 103 import java.security.MessageDigest; 104 import java.security.cert.Certificate; 105 import java.security.cert.CertificateEncodingException; 106 import java.security.cert.X509Certificate; 107 import java.util.ArrayList; 108 import java.util.Collection; 109 import java.util.Collections; 110 import java.util.Iterator; 111 import java.util.List; 112 import java.util.Objects; 113 import java.util.Set; 114 import java.util.concurrent.Executor; 115 import java.util.function.Consumer; 116 117 /** 118 * Offers the ability to install, upgrade, and remove applications on the 119 * device. This includes support for apps packaged either as a single 120 * "monolithic" APK, or apps packaged as multiple "split" APKs. 121 * <p> 122 * An app is delivered for installation through a 123 * {@link PackageInstaller.Session}, which any app can create. Once the session 124 * is created, the installer can stream one or more APKs into place until it 125 * decides to either commit or destroy the session. Committing may require user 126 * intervention to complete the installation, unless the caller falls into one of the 127 * following categories, in which case the installation will complete automatically. 128 * <ul> 129 * <li>the device owner 130 * <li>the affiliated profile owner 131 * </ul> 132 * <p> 133 * Sessions can install brand new apps, upgrade existing apps, or add new splits 134 * into an existing app. 135 * <p> 136 * Apps packaged as multiple split APKs always consist of a single "base" APK 137 * (with a {@code null} split name) and zero or more "split" APKs (with unique 138 * split names). Any subset of these APKs can be installed together, as long as 139 * the following constraints are met: 140 * <ul> 141 * <li>All APKs must have the exact same package name, version code, and signing 142 * certificates. 143 * <li>All APKs must have unique split names. 144 * <li>All installations must contain a single base APK. 145 * </ul> 146 * <p> 147 * The ApiDemos project contains examples of using this API: 148 * <code>ApiDemos/src/com/example/android/apis/content/InstallApk*.java</code>. 149 */ 150 public class PackageInstaller { 151 private static final String TAG = "PackageInstaller"; 152 153 private static final String ACTION_WAIT_INSTALL_CONSTRAINTS = 154 "android.content.pm.action.WAIT_INSTALL_CONSTRAINTS"; 155 156 /** {@hide} */ 157 public static final boolean ENABLE_REVOCABLE_FD = 158 SystemProperties.getBoolean("fw.revocable_fd", false); 159 160 /** 161 * Activity Action: Show details about a particular install session. This 162 * may surface actions such as pause, resume, or cancel. 163 * <p> 164 * This should always be scoped to the installer package that owns the 165 * session. Clients should use {@link SessionInfo#createDetailsIntent()} to 166 * build this intent correctly. 167 * <p> 168 * In some cases, a matching Activity may not exist, so ensure you safeguard 169 * against this. 170 * <p> 171 * The session to show details for is defined in {@link #EXTRA_SESSION_ID}. 172 */ 173 @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) 174 public static final String ACTION_SESSION_DETAILS = "android.content.pm.action.SESSION_DETAILS"; 175 176 /** 177 * Broadcast Action: Explicit broadcast sent to the last known default launcher when a session 178 * for a new install is committed. For managed profile, this is sent to the default launcher 179 * of the primary profile. 180 * For user-profiles that have items restricted on home screen, this broadcast is sent to 181 * the default launcher of the primary profile, only if it has either 182 * {@link Manifest.permission.ACCESS_HIDDEN_PROFILES_FULL} or 183 * {@link Manifest.permission.ACCESS_HIDDEN_PROFILES} permission. 184 * <p> 185 * The associated session is defined in {@link #EXTRA_SESSION} and the user for which this 186 * session was created in {@link Intent#EXTRA_USER}. 187 */ 188 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 189 public static final String ACTION_SESSION_COMMITTED = 190 "android.content.pm.action.SESSION_COMMITTED"; 191 192 /** 193 * Broadcast Action: Send information about a staged install session when its state is updated. 194 * <p> 195 * The associated session information is defined in {@link #EXTRA_SESSION}. 196 */ 197 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 198 public static final String ACTION_SESSION_UPDATED = 199 "android.content.pm.action.SESSION_UPDATED"; 200 201 /** 202 * Intent action to indicate that user action is required for current install. This action can 203 * be used only by system apps. 204 * 205 * @hide 206 */ 207 @SystemApi 208 public static final String ACTION_CONFIRM_INSTALL = "android.content.pm.action.CONFIRM_INSTALL"; 209 210 /** 211 * Activity Action: Intent sent to the installer when a session for requesting 212 * user pre-approval, and user needs to confirm the installation. 213 * 214 * @hide 215 */ 216 @SystemApi 217 public static final String ACTION_CONFIRM_PRE_APPROVAL = 218 "android.content.pm.action.CONFIRM_PRE_APPROVAL"; 219 220 /** 221 * An integer session ID that an operation is working with. 222 * 223 * @see Intent#getIntExtra(String, int) 224 */ 225 public static final String EXTRA_SESSION_ID = "android.content.pm.extra.SESSION_ID"; 226 227 /** 228 * {@link SessionInfo} that an operation is working with. 229 * 230 * @see Intent#getParcelableExtra(String) 231 */ 232 public static final String EXTRA_SESSION = "android.content.pm.extra.SESSION"; 233 234 /** 235 * Package name that an operation is working with. 236 * 237 * @see Intent#getStringExtra(String) 238 */ 239 public static final String EXTRA_PACKAGE_NAME = "android.content.pm.extra.PACKAGE_NAME"; 240 241 /** 242 * Current status of an operation. Will be one of 243 * {@link #STATUS_PENDING_USER_ACTION}, {@link #STATUS_SUCCESS}, 244 * {@link #STATUS_FAILURE}, {@link #STATUS_FAILURE_ABORTED}, 245 * {@link #STATUS_FAILURE_BLOCKED}, {@link #STATUS_FAILURE_CONFLICT}, 246 * {@link #STATUS_FAILURE_INCOMPATIBLE}, {@link #STATUS_FAILURE_INVALID}, 247 * {@link #STATUS_FAILURE_STORAGE}, or {@link #STATUS_FAILURE_TIMEOUT}. 248 * <p> 249 * More information about a status may be available through additional 250 * extras; see the individual status documentation for details. 251 * 252 * @see Intent#getIntExtra(String, int) 253 */ 254 public static final String EXTRA_STATUS = "android.content.pm.extra.STATUS"; 255 256 /** 257 * Indicate if the status is for a pre-approval request. 258 * 259 * If callers use the same {@link IntentSender} for both 260 * {@link Session#requestUserPreapproval(PreapprovalDetails, IntentSender)} and 261 * {@link Session#commit(IntentSender)}, they can use this to differentiate between them. 262 * 263 * @see Intent#getBooleanExtra(String, boolean) 264 */ 265 public static final String EXTRA_PRE_APPROVAL = "android.content.pm.extra.PRE_APPROVAL"; 266 267 /** 268 * Detailed string representation of the status, including raw details that 269 * are useful for debugging. 270 * 271 * @see Intent#getStringExtra(String) 272 */ 273 public static final String EXTRA_STATUS_MESSAGE = "android.content.pm.extra.STATUS_MESSAGE"; 274 275 /** 276 * Another package name relevant to a status. This is typically the package 277 * responsible for causing an operation failure. 278 * 279 * @see Intent#getStringExtra(String) 280 */ 281 public static final String 282 EXTRA_OTHER_PACKAGE_NAME = "android.content.pm.extra.OTHER_PACKAGE_NAME"; 283 284 /** 285 * Storage path relevant to a status. 286 * 287 * @see Intent#getStringExtra(String) 288 */ 289 public static final String EXTRA_STORAGE_PATH = "android.content.pm.extra.STORAGE_PATH"; 290 291 /** 292 * The {@link InstallConstraints} object. 293 * 294 * @see Intent#getParcelableExtra(String, Class) 295 * @see #waitForInstallConstraints(List, InstallConstraints, IntentSender, long) 296 */ 297 public static final String EXTRA_INSTALL_CONSTRAINTS = 298 "android.content.pm.extra.INSTALL_CONSTRAINTS"; 299 300 /** 301 * The {@link InstallConstraintsResult} object. 302 * 303 * @see Intent#getParcelableExtra(String, Class) 304 * @see #waitForInstallConstraints(List, InstallConstraints, IntentSender, long) 305 */ 306 public static final String EXTRA_INSTALL_CONSTRAINTS_RESULT = 307 "android.content.pm.extra.INSTALL_CONSTRAINTS_RESULT"; 308 309 /** {@hide} */ 310 @Deprecated 311 public static final String EXTRA_PACKAGE_NAMES = "android.content.pm.extra.PACKAGE_NAMES"; 312 313 /** 314 * The status as used internally in the package manager. Refer to {@link PackageManager} for 315 * a list of all valid legacy statuses. 316 * 317 * @hide 318 */ 319 @SystemApi 320 public static final String EXTRA_LEGACY_STATUS = "android.content.pm.extra.LEGACY_STATUS"; 321 /** {@hide} */ 322 public static final String EXTRA_LEGACY_BUNDLE = "android.content.pm.extra.LEGACY_BUNDLE"; 323 /** 324 * The callback to execute once an uninstall is completed (used for both successful and 325 * unsuccessful uninstalls). 326 * 327 * @hide 328 */ 329 @SystemApi 330 public static final String EXTRA_CALLBACK = "android.content.pm.extra.CALLBACK"; 331 /** 332 * Key for passing extra delete flags during archiving. 333 * 334 * @hide 335 */ 336 @SystemApi 337 @FlaggedApi(android.content.pm.Flags.FLAG_ARCHIVING) 338 public static final String EXTRA_DELETE_FLAGS = "android.content.pm.extra.DELETE_FLAGS"; 339 340 /** 341 * Type of DataLoader for this session. Will be one of 342 * {@link #DATA_LOADER_TYPE_NONE}, {@link #DATA_LOADER_TYPE_STREAMING}, 343 * {@link #DATA_LOADER_TYPE_INCREMENTAL}. 344 * <p> 345 * See the individual types documentation for details. 346 * 347 * @see Intent#getIntExtra(String, int) 348 * {@hide} 349 */ 350 @SystemApi 351 public static final String EXTRA_DATA_LOADER_TYPE = "android.content.pm.extra.DATA_LOADER_TYPE"; 352 353 /** 354 * Path to the validated base APK for this session, which may point at an 355 * APK inside the session (when the session defines the base), or it may 356 * point at the existing base APK (when adding splits to an existing app). 357 * 358 * @hide 359 * @deprecated Resolved base path of an install session should not be available to unauthorized 360 * callers. Use {@link SessionInfo#getResolvedBaseApkPath()} instead. 361 */ 362 @Deprecated 363 @SystemApi 364 public static final String EXTRA_RESOLVED_BASE_PATH = 365 "android.content.pm.extra.RESOLVED_BASE_PATH"; 366 367 /** 368 * Extra field for the package name of a package that is requested to be unarchived. Sent as 369 * part of the {@link android.content.Intent#ACTION_UNARCHIVE_PACKAGE} intent. 370 */ 371 @FlaggedApi(Flags.FLAG_ARCHIVING) 372 public static final String EXTRA_UNARCHIVE_PACKAGE_NAME = 373 "android.content.pm.extra.UNARCHIVE_PACKAGE_NAME"; 374 375 /** 376 * Extra field for the unarchive ID. Sent as 377 * part of the {@link android.content.Intent#ACTION_UNARCHIVE_PACKAGE} intent. 378 * 379 * @see SessionParams#setUnarchiveId 380 */ 381 @FlaggedApi(Flags.FLAG_ARCHIVING) 382 public static final String EXTRA_UNARCHIVE_ID = 383 "android.content.pm.extra.UNARCHIVE_ID"; 384 385 /** 386 * If true, the requestor of the unarchival has specified that the app should be unarchived 387 * for all users. Sent as part of the {@link android.content.Intent#ACTION_UNARCHIVE_PACKAGE} 388 * intent. 389 */ 390 @FlaggedApi(Flags.FLAG_ARCHIVING) 391 public static final String EXTRA_UNARCHIVE_ALL_USERS = 392 "android.content.pm.extra.UNARCHIVE_ALL_USERS"; 393 394 /** 395 * Current status of an unarchive operation. Will be one of 396 * {@link #UNARCHIVAL_OK}, {@link #UNARCHIVAL_ERROR_USER_ACTION_NEEDED}, 397 * {@link #UNARCHIVAL_ERROR_INSUFFICIENT_STORAGE}, {@link #UNARCHIVAL_ERROR_NO_CONNECTIVITY}, 398 * {@link #UNARCHIVAL_GENERIC_ERROR}, {@link #UNARCHIVAL_ERROR_INSTALLER_DISABLED} or 399 * {@link #UNARCHIVAL_ERROR_INSTALLER_UNINSTALLED}. 400 * 401 * <p> If the status is not {@link #UNARCHIVAL_OK}, then {@link Intent#EXTRA_INTENT} will be set 402 * with an intent for a corresponding follow-up action (e.g. storage clearing dialog) or a 403 * failure dialog. 404 * 405 * <p> Used as part of {@link #requestUnarchive} to return the status of the unarchival through 406 * the {@link IntentSender}. 407 * 408 * @see #requestUnarchive 409 */ 410 @FlaggedApi(Flags.FLAG_ARCHIVING) 411 public static final String EXTRA_UNARCHIVE_STATUS = "android.content.pm.extra.UNARCHIVE_STATUS"; 412 413 /** 414 * A list of warnings that occurred during installation. 415 * 416 * @hide 417 */ 418 public static final String EXTRA_WARNINGS = "android.content.pm.extra.WARNINGS"; 419 420 /** 421 * Streaming installation pending. 422 * Caller should make sure DataLoader is able to prepare image and reinitiate the operation. 423 * 424 * @see #EXTRA_SESSION_ID 425 * {@hide} 426 */ 427 public static final int STATUS_PENDING_STREAMING = -2; 428 429 /** 430 * User action is currently required to proceed. You can launch the intent 431 * activity described by {@link Intent#EXTRA_INTENT} to involve the user and 432 * continue. 433 * <p> 434 * You may choose to immediately launch the intent if the user is actively 435 * using your app. Otherwise, you should use a notification to guide the 436 * user back into your app before launching. 437 * 438 * @see Intent#getParcelableExtra(String) 439 */ 440 public static final int STATUS_PENDING_USER_ACTION = -1; 441 442 /** 443 * The operation succeeded. 444 */ 445 public static final int STATUS_SUCCESS = 0; 446 447 /** 448 * The operation failed in a generic way. The system will always try to 449 * provide a more specific failure reason, but in some rare cases this may 450 * be delivered. 451 * 452 * @see #EXTRA_STATUS_MESSAGE 453 */ 454 public static final int STATUS_FAILURE = 1; 455 456 /** 457 * The operation failed because it was blocked. For example, a device policy 458 * may be blocking the operation, a package verifier may have blocked the 459 * operation, or the app may be required for core system operation. 460 * <p> 461 * The result may also contain {@link #EXTRA_OTHER_PACKAGE_NAME} with the 462 * specific package blocking the install. 463 * 464 * @see #EXTRA_STATUS_MESSAGE 465 * @see #EXTRA_OTHER_PACKAGE_NAME 466 */ 467 public static final int STATUS_FAILURE_BLOCKED = 2; 468 469 /** 470 * The operation failed because it was actively aborted. For example, the 471 * user actively declined requested permissions, or the session was 472 * abandoned. 473 * 474 * @see #EXTRA_STATUS_MESSAGE 475 */ 476 public static final int STATUS_FAILURE_ABORTED = 3; 477 478 /** 479 * The operation failed because one or more of the APKs was invalid. For 480 * example, they might be malformed, corrupt, incorrectly signed, 481 * mismatched, etc. 482 * 483 * @see #EXTRA_STATUS_MESSAGE 484 */ 485 public static final int STATUS_FAILURE_INVALID = 4; 486 487 /** 488 * The operation failed because it conflicts (or is inconsistent with) with 489 * another package already installed on the device. For example, an existing 490 * permission, incompatible certificates, etc. The user may be able to 491 * uninstall another app to fix the issue. 492 * <p> 493 * The result may also contain {@link #EXTRA_OTHER_PACKAGE_NAME} with the 494 * specific package identified as the cause of the conflict. 495 * 496 * @see #EXTRA_STATUS_MESSAGE 497 * @see #EXTRA_OTHER_PACKAGE_NAME 498 */ 499 public static final int STATUS_FAILURE_CONFLICT = 5; 500 501 /** 502 * The operation failed because of storage issues. For example, the device 503 * may be running low on space, or external media may be unavailable. The 504 * user may be able to help free space or insert different external media. 505 * <p> 506 * The result may also contain {@link #EXTRA_STORAGE_PATH} with the path to 507 * the storage device that caused the failure. 508 * 509 * @see #EXTRA_STATUS_MESSAGE 510 * @see #EXTRA_STORAGE_PATH 511 */ 512 public static final int STATUS_FAILURE_STORAGE = 6; 513 514 /** 515 * The operation failed because it is fundamentally incompatible with this 516 * device. For example, the app may require a hardware feature that doesn't 517 * exist, it may be missing native code for the ABIs supported by the 518 * device, or it requires a newer SDK version, etc. 519 * 520 * Starting in {@link Build.VERSION_CODES#UPSIDE_DOWN_CAKE}, an app with only 32-bit native 521 * code can still be installed on a device that supports both 64-bit and 32-bit ABIs. 522 * However, a warning dialog will be displayed when the app is launched. 523 * 524 * @see #EXTRA_STATUS_MESSAGE 525 */ 526 public static final int STATUS_FAILURE_INCOMPATIBLE = 7; 527 528 /** 529 * The operation failed because it didn't complete within the specified timeout. 530 * 531 * @see #EXTRA_STATUS_MESSAGE 532 */ 533 public static final int STATUS_FAILURE_TIMEOUT = 8; 534 535 /** 536 * Default value, non-streaming installation session. 537 * 538 * @see #EXTRA_DATA_LOADER_TYPE 539 * {@hide} 540 */ 541 @SystemApi 542 public static final int DATA_LOADER_TYPE_NONE = DataLoaderType.NONE; 543 544 /** 545 * Streaming installation using data loader. 546 * 547 * @see #EXTRA_DATA_LOADER_TYPE 548 * {@hide} 549 */ 550 @SystemApi 551 public static final int DATA_LOADER_TYPE_STREAMING = DataLoaderType.STREAMING; 552 553 /** 554 * Streaming installation using Incremental FileSystem. 555 * 556 * @see #EXTRA_DATA_LOADER_TYPE 557 * {@hide} 558 */ 559 @SystemApi 560 public static final int DATA_LOADER_TYPE_INCREMENTAL = DataLoaderType.INCREMENTAL; 561 562 /** 563 * Target location for the file in installation session is /data/app/<packageName>-<id>. 564 * This is the intended location for APKs. 565 * Requires permission to install packages. 566 * {@hide} 567 */ 568 @SystemApi 569 public static final int LOCATION_DATA_APP = InstallationFileLocation.DATA_APP; 570 571 /** 572 * Target location for the file in installation session is 573 * /data/media/<userid>/Android/obb/<packageName>. This is the intended location for OBBs. 574 * {@hide} 575 */ 576 @SystemApi 577 public static final int LOCATION_MEDIA_OBB = InstallationFileLocation.MEDIA_OBB; 578 579 /** 580 * Target location for the file in installation session is 581 * /data/media/<userid>/Android/data/<packageName>. 582 * This is the intended location for application data. 583 * Can only be used by an app itself running under specific user. 584 * {@hide} 585 */ 586 @SystemApi 587 public static final int LOCATION_MEDIA_DATA = InstallationFileLocation.MEDIA_DATA; 588 589 /** @hide */ 590 @IntDef(prefix = { "LOCATION_" }, value = { 591 LOCATION_DATA_APP, 592 LOCATION_MEDIA_OBB, 593 LOCATION_MEDIA_DATA}) 594 @Retention(RetentionPolicy.SOURCE) 595 public @interface FileLocation{} 596 597 /** 598 * The installer did not call {@link PackageInstaller.SessionParams#setPackageSource(int)} to 599 * specify the package source. 600 */ 601 public static final int PACKAGE_SOURCE_UNSPECIFIED = 0; 602 603 /** 604 * Code indicating that the package being installed is from a source not reflected by any 605 * other package source constant. 606 */ 607 public static final int PACKAGE_SOURCE_OTHER = 1; 608 609 /** 610 * Code indicating that the package being installed is from a store. An app store that 611 * installs an app for the user would use this. 612 */ 613 public static final int PACKAGE_SOURCE_STORE = 2; 614 615 /** 616 * Code indicating that the package being installed comes from a local file on the device. A 617 * file manager that is facilitating the installation of an APK file would use this. 618 */ 619 public static final int PACKAGE_SOURCE_LOCAL_FILE = 3; 620 621 /** 622 * Code indicating that the package being installed comes from a file that was downloaded to 623 * the device by the user. For use in place of {@link #PACKAGE_SOURCE_LOCAL_FILE} when the 624 * installer knows the package was downloaded. 625 */ 626 public static final int PACKAGE_SOURCE_DOWNLOADED_FILE = 4; 627 628 /** @hide */ 629 @IntDef(prefix = { "PACKAGE_SOURCE_" }, value = { 630 PACKAGE_SOURCE_UNSPECIFIED, 631 PACKAGE_SOURCE_STORE, 632 PACKAGE_SOURCE_LOCAL_FILE, 633 PACKAGE_SOURCE_DOWNLOADED_FILE, 634 PACKAGE_SOURCE_OTHER 635 }) 636 @Retention(RetentionPolicy.SOURCE) 637 @interface PackageSourceType{} 638 639 /** 640 * Indicate the user intervention is required when the installer attempts to commit the session. 641 * This is the default case. 642 * 643 * @hide 644 */ 645 @SystemApi 646 public static final int REASON_CONFIRM_PACKAGE_CHANGE = 0; 647 648 /** 649 * Indicate the user intervention is required because the update ownership enforcement is 650 * enabled, and the update owner will change. 651 * 652 * @see PackageInstaller.SessionParams#setRequestUpdateOwnership 653 * @see InstallSourceInfo#getUpdateOwnerPackageName 654 * @hide 655 */ 656 @SystemApi 657 public static final int REASON_OWNERSHIP_CHANGED = 1; 658 659 /** 660 * Indicate the user intervention is required because the update ownership enforcement is 661 * enabled, and remind the update owner is a different package. 662 * 663 * @see PackageInstaller.SessionParams#setRequestUpdateOwnership 664 * @see InstallSourceInfo#getUpdateOwnerPackageName 665 * @hide 666 */ 667 @SystemApi 668 public static final int REASON_REMIND_OWNERSHIP = 2; 669 670 /** @hide */ 671 @IntDef(prefix = { "REASON_" }, value = { 672 REASON_CONFIRM_PACKAGE_CHANGE, 673 REASON_OWNERSHIP_CHANGED, 674 REASON_REMIND_OWNERSHIP, 675 }) 676 @Retention(RetentionPolicy.SOURCE) 677 public @interface UserActionReason {} 678 679 /** 680 * The unarchival status is not set. 681 * 682 * @hide 683 */ 684 public static final int UNARCHIVAL_STATUS_UNSET = -1; 685 686 /** 687 * The unarchival is possible and will commence. 688 * 689 * <p> Note that this does not mean that the unarchival has completed. This status should be 690 * sent before any longer asynchronous action (e.g. app download) is started. 691 */ 692 @FlaggedApi(Flags.FLAG_ARCHIVING) 693 public static final int UNARCHIVAL_OK = 0; 694 695 /** 696 * The user needs to interact with the installer to enable the installation. 697 * 698 * <p> An example use case for this could be that the user needs to login to allow the 699 * download for a paid app. 700 */ 701 @FlaggedApi(Flags.FLAG_ARCHIVING) 702 public static final int UNARCHIVAL_ERROR_USER_ACTION_NEEDED = 1; 703 704 /** 705 * Not enough storage to unarchive the application. 706 * 707 * <p> The installer can optionally provide a {@code userActionIntent} for a space-clearing 708 * dialog. If no action is provided, then a generic intent 709 * {@link android.os.storage.StorageManager#ACTION_MANAGE_STORAGE} is started instead. 710 */ 711 @FlaggedApi(Flags.FLAG_ARCHIVING) 712 public static final int UNARCHIVAL_ERROR_INSUFFICIENT_STORAGE = 2; 713 714 /** 715 * The device is not connected to the internet 716 */ 717 @FlaggedApi(Flags.FLAG_ARCHIVING) 718 public static final int UNARCHIVAL_ERROR_NO_CONNECTIVITY = 3; 719 720 /** 721 * The installer responsible for the unarchival is disabled. 722 * 723 * <p> The system will return this status if appropriate. Installers do not need to verify for 724 * this error. 725 */ 726 @FlaggedApi(Flags.FLAG_ARCHIVING) 727 public static final int UNARCHIVAL_ERROR_INSTALLER_DISABLED = 4; 728 729 /** 730 * The installer responsible for the unarchival has been uninstalled 731 * 732 * <p> The system will return this status if appropriate. Installers do not need to verify for 733 * this error. 734 */ 735 @FlaggedApi(Flags.FLAG_ARCHIVING) 736 public static final int UNARCHIVAL_ERROR_INSTALLER_UNINSTALLED = 5; 737 738 /** 739 * Generic error: The app cannot be unarchived. 740 */ 741 @FlaggedApi(Flags.FLAG_ARCHIVING) 742 public static final int UNARCHIVAL_GENERIC_ERROR = 100; 743 744 /** 745 * The set of error types that can be set for 746 * {@link #reportUnarchivalState}. 747 * 748 * @hide 749 */ 750 @IntDef(value = { 751 UNARCHIVAL_STATUS_UNSET, 752 UNARCHIVAL_OK, 753 UNARCHIVAL_ERROR_USER_ACTION_NEEDED, 754 UNARCHIVAL_ERROR_INSUFFICIENT_STORAGE, 755 UNARCHIVAL_ERROR_NO_CONNECTIVITY, 756 UNARCHIVAL_ERROR_INSTALLER_DISABLED, 757 UNARCHIVAL_ERROR_INSTALLER_UNINSTALLED, 758 UNARCHIVAL_GENERIC_ERROR, 759 }) 760 @Retention(RetentionPolicy.SOURCE) 761 public @interface UnarchivalStatus {} 762 763 764 /** Default set of checksums - includes all available checksums. 765 * @see Session#requestChecksums */ 766 private static final int DEFAULT_CHECKSUMS = 767 TYPE_WHOLE_MERKLE_ROOT_4K_SHA256 | TYPE_WHOLE_MD5 | TYPE_WHOLE_SHA1 | TYPE_WHOLE_SHA256 768 | TYPE_WHOLE_SHA512 | TYPE_PARTIAL_MERKLE_ROOT_1M_SHA256 769 | TYPE_PARTIAL_MERKLE_ROOT_1M_SHA512; 770 771 private final IPackageInstaller mInstaller; 772 private final int mUserId; 773 private final String mInstallerPackageName; 774 private final String mAttributionTag; 775 776 private final ArrayList<SessionCallbackDelegate> mDelegates = new ArrayList<>(); 777 778 /** {@hide} */ PackageInstaller(IPackageInstaller installer, String installerPackageName, String installerAttributionTag, int userId)779 public PackageInstaller(IPackageInstaller installer, 780 String installerPackageName, String installerAttributionTag, int userId) { 781 Objects.requireNonNull(installer, "installer cannot be null"); 782 mInstaller = installer; 783 mInstallerPackageName = installerPackageName; 784 mAttributionTag = installerAttributionTag; 785 mUserId = userId; 786 } 787 788 /** 789 * Create a new session using the given parameters, returning a unique ID 790 * that represents the session. Once created, the session can be opened 791 * multiple times across multiple device boots. 792 * <p> 793 * The system may automatically destroy sessions that have not been 794 * finalized (either committed or abandoned) within a reasonable period of 795 * time, typically on the order of a day. 796 * 797 * @throws IOException if parameters were unsatisfiable, such as lack of 798 * disk space or unavailable media. 799 * @throws SecurityException when installation services are unavailable, 800 * such as when called from a restricted user. 801 * @throws IllegalArgumentException when {@link SessionParams} is invalid. 802 * @return positive, non-zero unique ID that represents the created session. 803 * This ID remains consistent across device reboots until the 804 * session is finalized. IDs are not reused during a given boot. 805 */ createSession(@onNull SessionParams params)806 public int createSession(@NonNull SessionParams params) throws IOException { 807 try { 808 return mInstaller.createSession(params, mInstallerPackageName, mAttributionTag, 809 mUserId); 810 } catch (RuntimeException e) { 811 ExceptionUtils.maybeUnwrapIOException(e); 812 throw e; 813 } catch (RemoteException e) { 814 throw e.rethrowFromSystemServer(); 815 } 816 } 817 818 /** 819 * Open an existing session to actively perform work. To succeed, the caller 820 * must be the owner of the install session. 821 * 822 * @throws IOException if parameters were unsatisfiable, such as lack of 823 * disk space or unavailable media. 824 * @throws SecurityException when the caller does not own the session, or 825 * the session is invalid. 826 */ openSession(int sessionId)827 public @NonNull Session openSession(int sessionId) throws IOException { 828 try { 829 try { 830 return new Session(mInstaller.openSession(sessionId)); 831 } catch (RemoteException e) { 832 throw e.rethrowFromSystemServer(); 833 } 834 } catch (RuntimeException e) { 835 ExceptionUtils.maybeUnwrapIOException(e); 836 throw e; 837 } 838 } 839 840 /** 841 * Update the icon representing the app being installed in a specific 842 * session. This should be roughly 843 * {@link ActivityManager#getLauncherLargeIconSize()} in both dimensions. 844 * 845 * @throws SecurityException when the caller does not own the session, or 846 * the session is invalid. 847 */ updateSessionAppIcon(int sessionId, @Nullable Bitmap appIcon)848 public void updateSessionAppIcon(int sessionId, @Nullable Bitmap appIcon) { 849 try { 850 mInstaller.updateSessionAppIcon(sessionId, appIcon); 851 } catch (RemoteException e) { 852 throw e.rethrowFromSystemServer(); 853 } 854 } 855 856 /** 857 * Update the label representing the app being installed in a specific 858 * session. 859 * 860 * @throws SecurityException when the caller does not own the session, or 861 * the session is invalid. 862 */ updateSessionAppLabel(int sessionId, @Nullable CharSequence appLabel)863 public void updateSessionAppLabel(int sessionId, @Nullable CharSequence appLabel) { 864 try { 865 final String val = (appLabel != null) ? appLabel.toString() : null; 866 mInstaller.updateSessionAppLabel(sessionId, val); 867 } catch (RemoteException e) { 868 throw e.rethrowFromSystemServer(); 869 } 870 } 871 872 /** 873 * Completely abandon the given session, destroying all staged data and 874 * rendering it invalid. Abandoned sessions will be reported to 875 * {@link SessionCallback} listeners as failures. This is equivalent to 876 * opening the session and calling {@link Session#abandon()}. 877 * 878 * @throws SecurityException when the caller does not own the session, or 879 * the session is invalid. 880 */ abandonSession(int sessionId)881 public void abandonSession(int sessionId) { 882 try { 883 mInstaller.abandonSession(sessionId); 884 } catch (RemoteException e) { 885 throw e.rethrowFromSystemServer(); 886 } 887 } 888 889 /** 890 * Return details for a specific session. Callers need to either declare <queries> 891 * element with the specific package name in the app's manifest, have the 892 * android.permission.QUERY_ALL_PACKAGES, or be the session owner to retrieve these details. 893 * 894 * @return details for the requested session, or {@code null} if the session 895 * does not exist. 896 */ getSessionInfo(int sessionId)897 public @Nullable SessionInfo getSessionInfo(int sessionId) { 898 try { 899 return mInstaller.getSessionInfo(sessionId); 900 } catch (RemoteException e) { 901 throw e.rethrowFromSystemServer(); 902 } 903 } 904 905 /** 906 * Return list of all known install sessions, regardless of the installer. Callers need to 907 * either declare <queries> element with the specific package name in the app's manifest, 908 * have the android.permission.QUERY_ALL_PACKAGES, or be the session owner to retrieve these 909 * details. 910 */ getAllSessions()911 public @NonNull List<SessionInfo> getAllSessions() { 912 try { 913 return mInstaller.getAllSessions(mUserId).getList(); 914 } catch (RemoteException e) { 915 throw e.rethrowFromSystemServer(); 916 } 917 } 918 919 /** 920 * Return list of all known install sessions owned by the calling app. 921 */ getMySessions()922 public @NonNull List<SessionInfo> getMySessions() { 923 try { 924 return mInstaller.getMySessions(mInstallerPackageName, mUserId).getList(); 925 } catch (RemoteException e) { 926 throw e.rethrowFromSystemServer(); 927 } 928 } 929 930 /** 931 * Return list of all staged install sessions. Callers need to either declare <queries> 932 * element with the specific package name in the app's manifest, have the 933 * android.permission.QUERY_ALL_PACKAGES, or be the session owner to retrieve these details. 934 */ getStagedSessions()935 public @NonNull List<SessionInfo> getStagedSessions() { 936 try { 937 // TODO: limit this to the mUserId? 938 return mInstaller.getStagedSessions().getList(); 939 } catch (RemoteException e) { 940 throw e.rethrowFromSystemServer(); 941 } 942 } 943 944 /** 945 * Returns first active staged session, or {@code null} if there is none. 946 * 947 * <p>For more information on what sessions are considered active see 948 * {@link SessionInfo#isStagedSessionActive()}. 949 * 950 * @deprecated Use {@link #getActiveStagedSessions} as there can be more than one active staged 951 * session 952 */ 953 @Deprecated getActiveStagedSession()954 public @Nullable SessionInfo getActiveStagedSession() { 955 List<SessionInfo> activeSessions = getActiveStagedSessions(); 956 return activeSessions.isEmpty() ? null : activeSessions.get(0); 957 } 958 959 /** 960 * Returns list of active staged sessions. Returns empty list if there is none. 961 * 962 * <p>For more information on what sessions are considered active see 963 * * {@link SessionInfo#isStagedSessionActive()}. 964 */ getActiveStagedSessions()965 public @NonNull List<SessionInfo> getActiveStagedSessions() { 966 final List<SessionInfo> activeStagedSessions = new ArrayList<>(); 967 final List<SessionInfo> stagedSessions = getStagedSessions(); 968 for (int i = 0; i < stagedSessions.size(); i++) { 969 final SessionInfo sessionInfo = stagedSessions.get(i); 970 if (sessionInfo.isStagedSessionActive()) { 971 activeStagedSessions.add(sessionInfo); 972 } 973 } 974 return activeStagedSessions; 975 } 976 977 /** 978 * Uninstall the given package, removing it completely from the device. This 979 * method is available to: 980 * <ul> 981 * <li>the current "installer of record" for the package 982 * <li>the device owner 983 * <li>the affiliated profile owner 984 * </ul> 985 * 986 * @param packageName The package to uninstall. 987 * @param statusReceiver Where to deliver the result of the operation indicated by the extra 988 * {@link #EXTRA_STATUS}. Refer to the individual status codes 989 * on how to handle them. 990 * 991 * @see android.app.admin.DevicePolicyManager 992 */ 993 @RequiresPermission(anyOf = { 994 Manifest.permission.DELETE_PACKAGES, 995 Manifest.permission.REQUEST_DELETE_PACKAGES}) uninstall(@onNull String packageName, @NonNull IntentSender statusReceiver)996 public void uninstall(@NonNull String packageName, @NonNull IntentSender statusReceiver) { 997 uninstall(packageName, 0 /*flags*/, statusReceiver); 998 } 999 1000 /** 1001 * Uninstall the given package, removing it completely from the device. This 1002 * method is only available to the current "installer of record" for the 1003 * package. 1004 * 1005 * @param packageName The package to uninstall. 1006 * @param flags Flags for uninstall. 1007 * @param statusReceiver Where to deliver the result of the operation indicated by the extra 1008 * {@link #EXTRA_STATUS}. Refer to the individual status codes 1009 * on how to handle them. 1010 * 1011 * @hide 1012 */ uninstall(@onNull String packageName, @DeleteFlags int flags, @NonNull IntentSender statusReceiver)1013 public void uninstall(@NonNull String packageName, @DeleteFlags int flags, 1014 @NonNull IntentSender statusReceiver) { 1015 uninstall(new VersionedPackage(packageName, PackageManager.VERSION_CODE_HIGHEST), 1016 flags, statusReceiver); 1017 } 1018 1019 /** 1020 * Uninstall the given package with a specific version code, removing it 1021 * completely from the device. If the version code of the package 1022 * does not match the one passed in the versioned package argument this 1023 * method is a no-op. Use {@link PackageManager#VERSION_CODE_HIGHEST} to 1024 * uninstall the latest version of the package. 1025 * <p> 1026 * This method is available to: 1027 * <ul> 1028 * <li>the current "installer of record" for the package 1029 * <li>the device owner 1030 * <li>the affiliated profile owner 1031 * </ul> 1032 * 1033 * @param versionedPackage The versioned package to uninstall. 1034 * @param statusReceiver Where to deliver the result of the operation indicated by the extra 1035 * {@link #EXTRA_STATUS}. Refer to the individual status codes 1036 * on how to handle them. 1037 * 1038 * @see android.app.admin.DevicePolicyManager 1039 */ 1040 @RequiresPermission(anyOf = { 1041 Manifest.permission.DELETE_PACKAGES, 1042 Manifest.permission.REQUEST_DELETE_PACKAGES}) uninstall(@onNull VersionedPackage versionedPackage, @NonNull IntentSender statusReceiver)1043 public void uninstall(@NonNull VersionedPackage versionedPackage, 1044 @NonNull IntentSender statusReceiver) { 1045 uninstall(versionedPackage, 0 /*flags*/, statusReceiver); 1046 } 1047 1048 /** 1049 * Uninstall the given package with a specific version code, removing it 1050 * completely from the device. This method is only available to the current 1051 * "installer of record" for the package. If the version code of the package 1052 * does not match the one passed in the versioned package argument this 1053 * method is a no-op. Use {@link PackageManager#VERSION_CODE_HIGHEST} to 1054 * uninstall the latest version of the package. 1055 * 1056 * @param versionedPackage The versioned package to uninstall. 1057 * @param flags Flags for uninstall. 1058 * @param statusReceiver Where to deliver the result of the operation indicated by the extra 1059 * {@link #EXTRA_STATUS}. Refer to the individual status codes 1060 * on how to handle them. 1061 */ 1062 @RequiresPermission(anyOf = { 1063 Manifest.permission.DELETE_PACKAGES, 1064 Manifest.permission.REQUEST_DELETE_PACKAGES}) uninstall(@onNull VersionedPackage versionedPackage, @DeleteFlags int flags, @NonNull IntentSender statusReceiver)1065 public void uninstall(@NonNull VersionedPackage versionedPackage, @DeleteFlags int flags, 1066 @NonNull IntentSender statusReceiver) { 1067 Objects.requireNonNull(versionedPackage, "versionedPackage cannot be null"); 1068 try { 1069 mInstaller.uninstall(versionedPackage, mInstallerPackageName, 1070 flags, statusReceiver, mUserId); 1071 } catch (RemoteException e) { 1072 throw e.rethrowFromSystemServer(); 1073 } 1074 } 1075 1076 /** 1077 * Install the given package, which already exists on the device, for the user for which this 1078 * installer was created. 1079 * 1080 * <p>This will 1081 * {@link PackageInstaller.SessionParams#setWhitelistedRestrictedPermissions(Set) allowlist 1082 * all restricted permissions}. 1083 * 1084 * @param packageName The package to install. 1085 * @param installReason Reason for install. 1086 * @param statusReceiver Where to deliver the result of the operation indicated by the extra 1087 * {@link #EXTRA_STATUS}. Refer to the individual status codes 1088 * on how to handle them. 1089 */ 1090 @RequiresPermission(allOf = { 1091 Manifest.permission.INSTALL_PACKAGES, 1092 Manifest.permission.INSTALL_EXISTING_PACKAGES}) installExistingPackage(@onNull String packageName, @InstallReason int installReason, @Nullable IntentSender statusReceiver)1093 public void installExistingPackage(@NonNull String packageName, 1094 @InstallReason int installReason, 1095 @Nullable IntentSender statusReceiver) { 1096 Objects.requireNonNull(packageName, "packageName cannot be null"); 1097 try { 1098 mInstaller.installExistingPackage(packageName, 1099 PackageManager.INSTALL_ALL_WHITELIST_RESTRICTED_PERMISSIONS, installReason, 1100 statusReceiver, mUserId, null); 1101 } catch (RemoteException e) { 1102 throw e.rethrowFromSystemServer(); 1103 } 1104 } 1105 1106 /** 1107 * Uninstall the given package for the user for which this installer was created if the package 1108 * will still exist for other users on the device. 1109 * 1110 * @param packageName The package to uninstall. 1111 * @param statusReceiver Where to deliver the result of the operation indicated by the extra 1112 * {@link #EXTRA_STATUS}. Refer to the individual status codes 1113 * on how to handle them. 1114 */ 1115 @RequiresPermission(Manifest.permission.DELETE_PACKAGES) uninstallExistingPackage(@onNull String packageName, @Nullable IntentSender statusReceiver)1116 public void uninstallExistingPackage(@NonNull String packageName, 1117 @Nullable IntentSender statusReceiver) { 1118 Objects.requireNonNull(packageName, "packageName cannot be null"); 1119 try { 1120 mInstaller.uninstallExistingPackage( 1121 new VersionedPackage(packageName, PackageManager.VERSION_CODE_HIGHEST), 1122 mInstallerPackageName, statusReceiver, mUserId); 1123 } catch (RemoteException e) { 1124 throw e.rethrowFromSystemServer(); 1125 } 1126 } 1127 1128 /** 1129 * Install package in an archived state. 1130 * 1131 * @param archivedPackageInfo archived package data such as package name, signature etc. 1132 * @param sessionParams used to create an underlying installation session 1133 * @param statusReceiver Called when the state of the session changes. Intents 1134 * sent to this receiver contain {@link #EXTRA_STATUS}. Refer to the 1135 * individual status codes on how to handle them. 1136 * @see #createSession 1137 * @see PackageInstaller.Session#commit 1138 */ 1139 @RequiresPermission(Manifest.permission.INSTALL_PACKAGES) 1140 @FlaggedApi(Flags.FLAG_ARCHIVING) installPackageArchived(@onNull ArchivedPackageInfo archivedPackageInfo, @NonNull SessionParams sessionParams, @NonNull IntentSender statusReceiver)1141 public void installPackageArchived(@NonNull ArchivedPackageInfo archivedPackageInfo, 1142 @NonNull SessionParams sessionParams, 1143 @NonNull IntentSender statusReceiver) { 1144 Objects.requireNonNull(archivedPackageInfo, "archivedPackageInfo cannot be null"); 1145 Objects.requireNonNull(sessionParams, "sessionParams cannot be null"); 1146 Objects.requireNonNull(statusReceiver, "statusReceiver cannot be null"); 1147 try { 1148 mInstaller.installPackageArchived( 1149 archivedPackageInfo.getParcel(), 1150 sessionParams, 1151 statusReceiver, 1152 mInstallerPackageName, 1153 new UserHandle(mUserId)); 1154 } catch (RemoteException e) { 1155 throw e.rethrowFromSystemServer(); 1156 } 1157 } 1158 1159 /** {@hide} */ 1160 @SystemApi 1161 @RequiresPermission(android.Manifest.permission.INSTALL_PACKAGES) setPermissionsResult(int sessionId, boolean accepted)1162 public void setPermissionsResult(int sessionId, boolean accepted) { 1163 try { 1164 mInstaller.setPermissionsResult(sessionId, accepted); 1165 } catch (RemoteException e) { 1166 throw e.rethrowFromSystemServer(); 1167 } 1168 } 1169 1170 /** 1171 * Check if install constraints are satisfied for the given packages. 1172 * 1173 * Note this query result is just a hint and subject to race because system states could 1174 * change anytime in-between this query and committing the session. 1175 * 1176 * The result is returned by a callback because some constraints might take a long time 1177 * to evaluate. 1178 * 1179 * @param packageNames a list of package names to check the constraints for installation 1180 * @param constraints the constraints for installation. 1181 * @param executor the {@link Executor} on which to invoke the callback 1182 * @param callback called when the {@link InstallConstraintsResult} is ready 1183 * 1184 * @throws SecurityException if the given packages' installer of record doesn't match the 1185 * caller's own package name or the installerPackageName set by the caller doesn't 1186 * match the caller's own package name. 1187 */ checkInstallConstraints(@onNull List<String> packageNames, @NonNull InstallConstraints constraints, @NonNull @CallbackExecutor Executor executor, @NonNull Consumer<InstallConstraintsResult> callback)1188 public void checkInstallConstraints(@NonNull List<String> packageNames, 1189 @NonNull InstallConstraints constraints, 1190 @NonNull @CallbackExecutor Executor executor, 1191 @NonNull Consumer<InstallConstraintsResult> callback) { 1192 Objects.requireNonNull(executor); 1193 Objects.requireNonNull(callback); 1194 try { 1195 var remoteCallback = new RemoteCallback(b -> { 1196 executor.execute(() -> { 1197 callback.accept(b.getParcelable("result", InstallConstraintsResult.class)); 1198 }); 1199 }); 1200 mInstaller.checkInstallConstraints( 1201 mInstallerPackageName, packageNames, constraints, remoteCallback); 1202 } catch (RemoteException e) { 1203 throw e.rethrowFromSystemServer(); 1204 } 1205 } 1206 1207 /** 1208 * Similar to {@link #checkInstallConstraints(List, InstallConstraints, Executor, Consumer)}, 1209 * but the callback is invoked only when the constraints are satisfied or after timeout. 1210 * <p> 1211 * Note: the device idle constraint might take a long time to evaluate. The system will 1212 * ensure the constraint is evaluated completely before handling timeout. 1213 * 1214 * @param packageNames a list of package names to check the constraints for installation 1215 * @param constraints the constraints for installation. 1216 * @param callback Called when the constraints are satisfied or after timeout. 1217 * Intents sent to this callback contain: 1218 * {@link Intent#EXTRA_PACKAGES} for the input package names, 1219 * {@link #EXTRA_INSTALL_CONSTRAINTS} for the input constraints, 1220 * {@link #EXTRA_INSTALL_CONSTRAINTS_RESULT} for the result. 1221 * @param timeoutMillis The maximum time to wait, in milliseconds until the constraints are 1222 * satisfied. Valid range is from 0 to one week. {@code 0} means the 1223 * callback will be invoked immediately no matter constraints are 1224 * satisfied or not. 1225 * @throws SecurityException if the given packages' installer of record doesn't match the 1226 * caller's own package name or the installerPackageName set by the caller doesn't 1227 * match the caller's own package name. 1228 */ waitForInstallConstraints(@onNull List<String> packageNames, @NonNull InstallConstraints constraints, @NonNull IntentSender callback, @DurationMillisLong long timeoutMillis)1229 public void waitForInstallConstraints(@NonNull List<String> packageNames, 1230 @NonNull InstallConstraints constraints, 1231 @NonNull IntentSender callback, 1232 @DurationMillisLong long timeoutMillis) { 1233 try { 1234 mInstaller.waitForInstallConstraints( 1235 mInstallerPackageName, packageNames, constraints, callback, timeoutMillis); 1236 } catch (RemoteException e) { 1237 throw e.rethrowFromSystemServer(); 1238 } 1239 } 1240 1241 /** 1242 * Commit the session when all constraints are satisfied. This is a convenient method to 1243 * combine {@link #waitForInstallConstraints(List, InstallConstraints, IntentSender, long)} 1244 * and {@link Session#commit(IntentSender)}. 1245 * <p> 1246 * Once this method is called, the session is sealed and no additional mutations 1247 * may be performed on the session. In the case of timeout, you may commit the 1248 * session again using this method or {@link Session#commit(IntentSender)} for retries. 1249 * 1250 * @param sessionId the session ID to commit when all constraints are satisfied. 1251 * @param statusReceiver Called when the state of the session changes. Intents 1252 * sent to this receiver contain {@link #EXTRA_STATUS}. 1253 * Refer to the individual status codes on how to handle them. 1254 * @param constraints The requirements to satisfy before committing the session. 1255 * @param timeoutMillis The maximum time to wait, in milliseconds until the 1256 * constraints are satisfied. The caller will be notified via 1257 * {@code statusReceiver} if timeout happens before commit. 1258 * @throws IllegalArgumentException if the {@code statusReceiver} from an immutable 1259 * {@link android.app.PendingIntent} when caller has a target SDK of API 1260 * 35 or above. 1261 */ commitSessionAfterInstallConstraintsAreMet(int sessionId, @NonNull IntentSender statusReceiver, @NonNull InstallConstraints constraints, @DurationMillisLong long timeoutMillis)1262 public void commitSessionAfterInstallConstraintsAreMet(int sessionId, 1263 @NonNull IntentSender statusReceiver, @NonNull InstallConstraints constraints, 1264 @DurationMillisLong long timeoutMillis) { 1265 try { 1266 var session = mInstaller.openSession(sessionId); 1267 session.seal(); 1268 var packageNames = session.fetchPackageNames(); 1269 var context = ActivityThread.currentApplication(); 1270 var localIntentSender = new LocalIntentSender(context, sessionId, session, 1271 statusReceiver); 1272 waitForInstallConstraints(packageNames, constraints, 1273 localIntentSender.getIntentSender(), timeoutMillis); 1274 } catch (RemoteException e) { 1275 throw e.rethrowFromSystemServer(); 1276 } 1277 } 1278 1279 private static final class LocalIntentSender extends BroadcastReceiver { 1280 1281 private final Context mContext; 1282 private final IntentSender mStatusReceiver; 1283 private final int mSessionId; 1284 private final IPackageInstallerSession mSession; 1285 LocalIntentSender(Context context, int sessionId, IPackageInstallerSession session, IntentSender statusReceiver)1286 LocalIntentSender(Context context, int sessionId, IPackageInstallerSession session, 1287 IntentSender statusReceiver) { 1288 mContext = context; 1289 mSessionId = sessionId; 1290 mSession = session; 1291 mStatusReceiver = statusReceiver; 1292 } 1293 getIntentSender()1294 private IntentSender getIntentSender() { 1295 Intent intent = new Intent(ACTION_WAIT_INSTALL_CONSTRAINTS).setPackage( 1296 mContext.getPackageName()); 1297 mContext.registerReceiver(this, new IntentFilter(ACTION_WAIT_INSTALL_CONSTRAINTS), 1298 Context.RECEIVER_EXPORTED); 1299 PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0, intent, 1300 PendingIntent.FLAG_MUTABLE); 1301 return pendingIntent.getIntentSender(); 1302 } 1303 1304 @Override onReceive(Context context, Intent intent)1305 public void onReceive(Context context, Intent intent) { 1306 InstallConstraintsResult result = intent.getParcelableExtra( 1307 PackageInstaller.EXTRA_INSTALL_CONSTRAINTS_RESULT, 1308 InstallConstraintsResult.class); 1309 try { 1310 if (result.areAllConstraintsSatisfied()) { 1311 mSession.commit(mStatusReceiver, false); 1312 } else { 1313 // timeout 1314 final Intent fillIn = new Intent(); 1315 fillIn.putExtra(PackageInstaller.EXTRA_SESSION_ID, mSessionId); 1316 fillIn.putExtra(PackageInstaller.EXTRA_STATUS, STATUS_FAILURE_TIMEOUT); 1317 fillIn.putExtra(PackageInstaller.EXTRA_STATUS_MESSAGE, 1318 "Install constraints not satisfied within timeout"); 1319 mStatusReceiver.sendIntent(ActivityThread.currentApplication(), 0, fillIn, null, 1320 null); 1321 } 1322 } catch (Exception ignore) { 1323 // no-op 1324 } finally { 1325 unregisterReceiver(); 1326 } 1327 } 1328 unregisterReceiver()1329 private void unregisterReceiver() { 1330 mContext.unregisterReceiver(this); 1331 } 1332 } 1333 1334 /** 1335 * Events for observing session lifecycle. 1336 * <p> 1337 * A typical session lifecycle looks like this: 1338 * <ul> 1339 * <li>An installer creates a session to indicate pending app delivery. All 1340 * install details are available at this point. 1341 * <li>The installer opens the session to deliver APK data. Note that a 1342 * session may be opened and closed multiple times as network connectivity 1343 * changes. The installer may deliver periodic progress updates. 1344 * <li>The installer commits or abandons the session, resulting in the 1345 * session being finished. 1346 * </ul> 1347 */ 1348 public static abstract class SessionCallback { 1349 /** 1350 * New session has been created. Details about the session can be 1351 * obtained from {@link PackageInstaller#getSessionInfo(int)}. 1352 */ onCreated(int sessionId)1353 public abstract void onCreated(int sessionId); 1354 1355 /** 1356 * Badging details for an existing session has changed. For example, the 1357 * app icon or label has been updated. 1358 */ onBadgingChanged(int sessionId)1359 public abstract void onBadgingChanged(int sessionId); 1360 1361 /** 1362 * Active state for session has been changed. 1363 * <p> 1364 * A session is considered active whenever there is ongoing forward 1365 * progress being made, such as the installer holding an open 1366 * {@link Session} instance while streaming data into place, or the 1367 * system optimizing code as the result of 1368 * {@link Session#commit(IntentSender)}. 1369 * <p> 1370 * If the installer closes the {@link Session} without committing, the 1371 * session is considered inactive until the installer opens the session 1372 * again. 1373 */ onActiveChanged(int sessionId, boolean active)1374 public abstract void onActiveChanged(int sessionId, boolean active); 1375 1376 /** 1377 * Progress for given session has been updated. 1378 * <p> 1379 * Note that this progress may not directly correspond to the value 1380 * reported by 1381 * {@link PackageInstaller.Session#setStagingProgress(float)}, as the 1382 * system may carve out a portion of the overall progress to represent 1383 * its own internal installation work. 1384 */ onProgressChanged(int sessionId, float progress)1385 public abstract void onProgressChanged(int sessionId, float progress); 1386 1387 /** 1388 * Session has completely finished, either with success or failure. 1389 */ onFinished(int sessionId, boolean success)1390 public abstract void onFinished(int sessionId, boolean success); 1391 } 1392 1393 /** {@hide} */ 1394 static class SessionCallbackDelegate extends IPackageInstallerCallback.Stub { 1395 private static final int MSG_SESSION_CREATED = 1; 1396 private static final int MSG_SESSION_BADGING_CHANGED = 2; 1397 private static final int MSG_SESSION_ACTIVE_CHANGED = 3; 1398 private static final int MSG_SESSION_PROGRESS_CHANGED = 4; 1399 private static final int MSG_SESSION_FINISHED = 5; 1400 1401 final SessionCallback mCallback; 1402 final Executor mExecutor; 1403 SessionCallbackDelegate(SessionCallback callback, Executor executor)1404 SessionCallbackDelegate(SessionCallback callback, Executor executor) { 1405 mCallback = callback; 1406 mExecutor = executor; 1407 } 1408 1409 @Override onSessionCreated(int sessionId)1410 public void onSessionCreated(int sessionId) { 1411 mExecutor.execute(PooledLambda.obtainRunnable(SessionCallback::onCreated, mCallback, 1412 sessionId).recycleOnUse()); 1413 } 1414 1415 @Override onSessionBadgingChanged(int sessionId)1416 public void onSessionBadgingChanged(int sessionId) { 1417 mExecutor.execute(PooledLambda.obtainRunnable(SessionCallback::onBadgingChanged, 1418 mCallback, sessionId).recycleOnUse()); 1419 } 1420 1421 @Override onSessionActiveChanged(int sessionId, boolean active)1422 public void onSessionActiveChanged(int sessionId, boolean active) { 1423 mExecutor.execute(PooledLambda.obtainRunnable(SessionCallback::onActiveChanged, 1424 mCallback, sessionId, active).recycleOnUse()); 1425 } 1426 1427 @Override onSessionProgressChanged(int sessionId, float progress)1428 public void onSessionProgressChanged(int sessionId, float progress) { 1429 mExecutor.execute(PooledLambda.obtainRunnable(SessionCallback::onProgressChanged, 1430 mCallback, sessionId, progress).recycleOnUse()); 1431 } 1432 1433 @Override onSessionFinished(int sessionId, boolean success)1434 public void onSessionFinished(int sessionId, boolean success) { 1435 mExecutor.execute(PooledLambda.obtainRunnable(SessionCallback::onFinished, 1436 mCallback, sessionId, success).recycleOnUse()); 1437 } 1438 } 1439 1440 /** {@hide} */ 1441 @Deprecated addSessionCallback(@onNull SessionCallback callback)1442 public void addSessionCallback(@NonNull SessionCallback callback) { 1443 registerSessionCallback(callback); 1444 } 1445 1446 /** 1447 * Register to watch for session lifecycle events. The callers need to be the session 1448 * owner or have the android.permission.QUERY_ALL_PACKAGES to watch for these events. 1449 */ registerSessionCallback(@onNull SessionCallback callback)1450 public void registerSessionCallback(@NonNull SessionCallback callback) { 1451 registerSessionCallback(callback, new Handler()); 1452 } 1453 1454 /** {@hide} */ 1455 @Deprecated addSessionCallback(@onNull SessionCallback callback, @NonNull Handler handler)1456 public void addSessionCallback(@NonNull SessionCallback callback, @NonNull Handler handler) { 1457 registerSessionCallback(callback, handler); 1458 } 1459 1460 /** 1461 * Register to watch for session lifecycle events. No special permissions 1462 * are required to watch for these events. 1463 * 1464 * @param handler to dispatch callback events through, otherwise uses 1465 * calling thread. 1466 */ registerSessionCallback(@onNull SessionCallback callback, @NonNull Handler handler)1467 public void registerSessionCallback(@NonNull SessionCallback callback, @NonNull Handler handler) { 1468 synchronized (mDelegates) { 1469 final SessionCallbackDelegate delegate = new SessionCallbackDelegate(callback, 1470 new HandlerExecutor(handler)); 1471 try { 1472 mInstaller.registerCallback(delegate, mUserId); 1473 } catch (RemoteException e) { 1474 throw e.rethrowFromSystemServer(); 1475 } 1476 mDelegates.add(delegate); 1477 } 1478 } 1479 1480 /** {@hide} */ 1481 @Deprecated removeSessionCallback(@onNull SessionCallback callback)1482 public void removeSessionCallback(@NonNull SessionCallback callback) { 1483 unregisterSessionCallback(callback); 1484 } 1485 1486 /** 1487 * Unregister a previously registered callback. 1488 */ unregisterSessionCallback(@onNull SessionCallback callback)1489 public void unregisterSessionCallback(@NonNull SessionCallback callback) { 1490 synchronized (mDelegates) { 1491 for (Iterator<SessionCallbackDelegate> i = mDelegates.iterator(); i.hasNext();) { 1492 final SessionCallbackDelegate delegate = i.next(); 1493 if (delegate.mCallback == callback) { 1494 try { 1495 mInstaller.unregisterCallback(delegate); 1496 } catch (RemoteException e) { 1497 throw e.rethrowFromSystemServer(); 1498 } 1499 i.remove(); 1500 } 1501 } 1502 } 1503 } 1504 1505 /** 1506 * An installation that is being actively staged. For an install to succeed, 1507 * all existing and new packages must have identical package names, version 1508 * codes, and signing certificates. 1509 * <p> 1510 * A session may contain any number of split packages. If the application 1511 * does not yet exist, this session must include a base package. 1512 * <p> 1513 * If an APK included in this session is already defined by the existing 1514 * installation (for example, the same split name), the APK in this session 1515 * will replace the existing APK. 1516 * <p> 1517 * In such a case that multiple packages need to be committed simultaneously, 1518 * multiple sessions can be referenced by a single multi-package session. 1519 * This session is created with no package name and calling 1520 * {@link SessionParams#setMultiPackage()}. The individual session IDs can be 1521 * added with {@link #addChildSessionId(int)} and commit of the multi-package 1522 * session will result in all child sessions being committed atomically. 1523 */ 1524 public static class Session implements Closeable { 1525 /** {@hide} */ 1526 protected final IPackageInstallerSession mSession; 1527 1528 /** {@hide} */ Session(IPackageInstallerSession session)1529 public Session(IPackageInstallerSession session) { 1530 mSession = session; 1531 } 1532 1533 /** {@hide} */ 1534 @Deprecated setProgress(float progress)1535 public void setProgress(float progress) { 1536 setStagingProgress(progress); 1537 } 1538 1539 /** 1540 * Set current progress of staging this session. Valid values are 1541 * anywhere between 0 and 1. 1542 * <p> 1543 * Note that this progress may not directly correspond to the value 1544 * reported by {@link SessionCallback#onProgressChanged(int, float)}, as 1545 * the system may carve out a portion of the overall progress to 1546 * represent its own internal installation work. 1547 */ setStagingProgress(float progress)1548 public void setStagingProgress(float progress) { 1549 try { 1550 mSession.setClientProgress(progress); 1551 } catch (RemoteException e) { 1552 throw e.rethrowFromSystemServer(); 1553 } 1554 } 1555 1556 /** {@hide} */ 1557 @UnsupportedAppUsage addProgress(float progress)1558 public void addProgress(float progress) { 1559 try { 1560 mSession.addClientProgress(progress); 1561 } catch (RemoteException e) { 1562 throw e.rethrowFromSystemServer(); 1563 } 1564 } 1565 1566 /** 1567 * Open a stream to write an APK file into the session. 1568 * <p> 1569 * The returned stream will start writing data at the requested offset 1570 * in the underlying file, which can be used to resume a partially 1571 * written file. If a valid file length is specified, the system will 1572 * preallocate the underlying disk space to optimize placement on disk. 1573 * It's strongly recommended to provide a valid file length when known. 1574 * <p> 1575 * You can write data into the returned stream, optionally call 1576 * {@link #fsync(OutputStream)} as needed to ensure bytes have been 1577 * persisted to disk, and then close when finished. All streams must be 1578 * closed before calling {@link #commit(IntentSender)}. 1579 * 1580 * @param name arbitrary, unique name of your choosing to identify the 1581 * APK being written. You can open a file again for 1582 * additional writes (such as after a reboot) by using the 1583 * same name. This name is only meaningful within the context 1584 * of a single install session. 1585 * @param offsetBytes offset into the file to begin writing at, or 0 to 1586 * start at the beginning of the file. 1587 * @param lengthBytes total size of the file being written, used to 1588 * preallocate the underlying disk space, or -1 if unknown. 1589 * The system may clear various caches as needed to allocate 1590 * this space. 1591 * @throws IOException if trouble opening the file for writing, such as 1592 * lack of disk space or unavailable media. 1593 * @throws SecurityException if called after the session has been 1594 * sealed or abandoned 1595 */ openWrite(@onNull String name, long offsetBytes, long lengthBytes)1596 public @NonNull OutputStream openWrite(@NonNull String name, long offsetBytes, 1597 long lengthBytes) throws IOException { 1598 try { 1599 if (ENABLE_REVOCABLE_FD) { 1600 return new ParcelFileDescriptor.AutoCloseOutputStream( 1601 mSession.openWrite(name, offsetBytes, lengthBytes)); 1602 } else { 1603 final ParcelFileDescriptor clientSocket = mSession.openWrite(name, 1604 offsetBytes, lengthBytes); 1605 return new FileBridge.FileBridgeOutputStream(clientSocket); 1606 } 1607 } catch (RuntimeException e) { 1608 ExceptionUtils.maybeUnwrapIOException(e); 1609 throw e; 1610 } catch (RemoteException e) { 1611 throw e.rethrowFromSystemServer(); 1612 } 1613 } 1614 1615 /** {@hide} */ write(@onNull String name, long offsetBytes, long lengthBytes, @NonNull ParcelFileDescriptor fd)1616 public void write(@NonNull String name, long offsetBytes, long lengthBytes, 1617 @NonNull ParcelFileDescriptor fd) throws IOException { 1618 try { 1619 mSession.write(name, offsetBytes, lengthBytes, fd); 1620 } catch (RuntimeException e) { 1621 ExceptionUtils.maybeUnwrapIOException(e); 1622 throw e; 1623 } catch (RemoteException e) { 1624 throw e.rethrowFromSystemServer(); 1625 } 1626 } 1627 1628 /** 1629 * Populate an APK file by creating a hard link to avoid the need to copy. 1630 * <p> 1631 * Note this API is used by RollbackManager only and can only be called from system_server. 1632 * {@code target} will be relabeled if link is created successfully. RollbackManager has 1633 * to delete {@code target} when the session is committed successfully to avoid SELinux 1634 * label conflicts. 1635 * <p> 1636 * Note No more bytes should be written to the file once the link is created successfully. 1637 * 1638 * @param target the path of the link target 1639 * 1640 * @hide 1641 */ stageViaHardLink(String target)1642 public void stageViaHardLink(String target) throws IOException { 1643 try { 1644 mSession.stageViaHardLink(target); 1645 } catch (RuntimeException e) { 1646 ExceptionUtils.maybeUnwrapIOException(e); 1647 throw e; 1648 } catch (RemoteException e) { 1649 throw e.rethrowFromSystemServer(); 1650 } 1651 } 1652 1653 /** 1654 * Ensure that any outstanding data for given stream has been committed 1655 * to disk. This is only valid for streams returned from 1656 * {@link #openWrite(String, long, long)}. 1657 */ fsync(@onNull OutputStream out)1658 public void fsync(@NonNull OutputStream out) throws IOException { 1659 if (ENABLE_REVOCABLE_FD) { 1660 if (out instanceof ParcelFileDescriptor.AutoCloseOutputStream) { 1661 try { 1662 Os.fsync(((ParcelFileDescriptor.AutoCloseOutputStream) out).getFD()); 1663 } catch (ErrnoException e) { 1664 throw e.rethrowAsIOException(); 1665 } 1666 } else { 1667 throw new IllegalArgumentException("Unrecognized stream"); 1668 } 1669 } else { 1670 if (out instanceof FileBridge.FileBridgeOutputStream) { 1671 ((FileBridge.FileBridgeOutputStream) out).fsync(); 1672 } else { 1673 throw new IllegalArgumentException("Unrecognized stream"); 1674 } 1675 } 1676 } 1677 1678 /** 1679 * Return all APK names contained in this session. 1680 * <p> 1681 * This returns all names which have been previously written through 1682 * {@link #openWrite(String, long, long)} as part of this session. 1683 * 1684 * @throws SecurityException if called after the session has been abandoned. 1685 */ getNames()1686 public @NonNull String[] getNames() throws IOException { 1687 try { 1688 return mSession.getNames(); 1689 } catch (RuntimeException e) { 1690 ExceptionUtils.maybeUnwrapIOException(e); 1691 throw e; 1692 } catch (RemoteException e) { 1693 throw e.rethrowFromSystemServer(); 1694 } 1695 } 1696 1697 /** 1698 * Open a stream to read an APK file from the session. 1699 * <p> 1700 * This is only valid for names which have been previously written 1701 * through {@link #openWrite(String, long, long)} as part of this 1702 * session. For example, this stream may be used to calculate a 1703 * {@link MessageDigest} of a written APK before committing. 1704 * 1705 * @throws SecurityException if called after the session has been 1706 * committed or abandoned. 1707 */ openRead(@onNull String name)1708 public @NonNull InputStream openRead(@NonNull String name) throws IOException { 1709 try { 1710 final ParcelFileDescriptor pfd = mSession.openRead(name); 1711 return new ParcelFileDescriptor.AutoCloseInputStream(pfd); 1712 } catch (RuntimeException e) { 1713 ExceptionUtils.maybeUnwrapIOException(e); 1714 throw e; 1715 } catch (RemoteException e) { 1716 throw e.rethrowFromSystemServer(); 1717 } 1718 } 1719 1720 /** 1721 * Removes a split. 1722 * <p> 1723 * Split removals occur prior to adding new APKs. If upgrading a feature 1724 * split, it is not expected nor desirable to remove the split prior to 1725 * upgrading. 1726 * <p> 1727 * When split removal is bundled with new APKs, the packageName must be 1728 * identical. 1729 */ removeSplit(@onNull String splitName)1730 public void removeSplit(@NonNull String splitName) throws IOException { 1731 try { 1732 mSession.removeSplit(splitName); 1733 } catch (RuntimeException e) { 1734 ExceptionUtils.maybeUnwrapIOException(e); 1735 throw e; 1736 } catch (RemoteException e) { 1737 throw e.rethrowFromSystemServer(); 1738 } 1739 } 1740 1741 /** 1742 * @return data loader params or null if the session is not using one. 1743 * {@hide} 1744 */ 1745 @SystemApi 1746 @RequiresPermission(android.Manifest.permission.USE_INSTALLER_V2) getDataLoaderParams()1747 public @Nullable DataLoaderParams getDataLoaderParams() { 1748 try { 1749 DataLoaderParamsParcel data = mSession.getDataLoaderParams(); 1750 if (data == null) { 1751 return null; 1752 } 1753 return new DataLoaderParams(data); 1754 } catch (RemoteException e) { 1755 throw e.rethrowFromSystemServer(); 1756 } 1757 } 1758 1759 /** 1760 * Adds a file to session. On commit this file will be pulled from DataLoader {@code 1761 * android.service.dataloader.DataLoaderService.DataLoader}. 1762 * 1763 * @param location target location for the file. Possible values: 1764 * {@link #LOCATION_DATA_APP}, 1765 * {@link #LOCATION_MEDIA_OBB}, 1766 * {@link #LOCATION_MEDIA_DATA}. 1767 * @param name arbitrary, unique name of your choosing to identify the 1768 * APK being written. You can open a file again for 1769 * additional writes (such as after a reboot) by using the 1770 * same name. This name is only meaningful within the context 1771 * of a single install session. 1772 * @param lengthBytes total size of the file being written. 1773 * The system may clear various caches as needed to allocate 1774 * this space. 1775 * @param metadata additional info use by DataLoader to pull data for the file. 1776 * @param signature additional file signature, e.g. 1777 * <a href="https://source.android.com/security/apksigning/v4.html">APK Signature Scheme v4</a> 1778 * @throws SecurityException if called after the session has been 1779 * sealed or abandoned 1780 * @throws IllegalStateException if called for non-streaming session 1781 * 1782 * @see android.content.pm.InstallationFile 1783 * 1784 * {@hide} 1785 */ 1786 @SystemApi 1787 @RequiresPermission(android.Manifest.permission.USE_INSTALLER_V2) addFile(@ileLocation int location, @NonNull String name, long lengthBytes, @NonNull byte[] metadata, @Nullable byte[] signature)1788 public void addFile(@FileLocation int location, @NonNull String name, long lengthBytes, 1789 @NonNull byte[] metadata, @Nullable byte[] signature) { 1790 try { 1791 mSession.addFile(location, name, lengthBytes, metadata, signature); 1792 } catch (RemoteException e) { 1793 throw e.rethrowFromSystemServer(); 1794 } 1795 } 1796 1797 /** 1798 * Removes a file. 1799 * 1800 * @param location target location for the file. Possible values: 1801 * {@link #LOCATION_DATA_APP}, 1802 * {@link #LOCATION_MEDIA_OBB}, 1803 * {@link #LOCATION_MEDIA_DATA}. 1804 * @param name name of a file, e.g. split. 1805 * @throws SecurityException if called after the session has been 1806 * sealed or abandoned 1807 * @throws IllegalStateException if called for non-DataLoader session 1808 * {@hide} 1809 */ 1810 @SystemApi 1811 @RequiresPermission(android.Manifest.permission.USE_INSTALLER_V2) removeFile(@ileLocation int location, @NonNull String name)1812 public void removeFile(@FileLocation int location, @NonNull String name) { 1813 try { 1814 mSession.removeFile(location, name); 1815 } catch (RemoteException e) { 1816 throw e.rethrowFromSystemServer(); 1817 } 1818 } 1819 1820 /** 1821 * Sets installer-provided checksums for the APK file in session. 1822 * 1823 * @param name previously written as part of this session. 1824 * {@link #openWrite} 1825 * @param checksums installer intends to make available via 1826 * {@link PackageManager#requestChecksums} or {@link #requestChecksums}. 1827 * @param signature DER PKCS#7 detached signature bytes over binary serialized checksums 1828 * to enable integrity checking for the checksums or null for no integrity 1829 * checking. {@link PackageManager#requestChecksums} will return 1830 * the certificate used to create signature. 1831 * Binary format for checksums: 1832 * <pre>{@code DataOutputStream dos; 1833 * dos.writeInt(checksum.getType()); 1834 * dos.writeInt(checksum.getValue().length); 1835 * dos.write(checksum.getValue());}</pre> 1836 * If using <b>openssl cms</b>, make sure to specify -binary -nosmimecap. 1837 * @see <a href="https://www.openssl.org/docs/man1.0.2/man1/cms.html">openssl cms</a> 1838 * @throws SecurityException if called after the session has been 1839 * committed or abandoned. 1840 * @throws IllegalStateException if checksums for this file have already been added. 1841 * @deprecated do not use installer-provided checksums, 1842 * use platform-enforced checksums 1843 * e.g. {@link Checksum#TYPE_WHOLE_MERKLE_ROOT_4K_SHA256} 1844 * in {@link PackageManager#requestChecksums}. 1845 */ 1846 @Deprecated setChecksums(@onNull String name, @NonNull List<Checksum> checksums, @Nullable byte[] signature)1847 public void setChecksums(@NonNull String name, @NonNull List<Checksum> checksums, 1848 @Nullable byte[] signature) throws IOException { 1849 Objects.requireNonNull(name); 1850 Objects.requireNonNull(checksums); 1851 1852 try { 1853 mSession.setChecksums(name, checksums.toArray(new Checksum[checksums.size()]), 1854 signature); 1855 } catch (RuntimeException e) { 1856 ExceptionUtils.maybeUnwrapIOException(e); 1857 throw e; 1858 } catch (RemoteException e) { 1859 throw e.rethrowFromSystemServer(); 1860 } 1861 } 1862 encodeCertificates(List<Certificate> certs)1863 private static List<byte[]> encodeCertificates(List<Certificate> certs) throws 1864 CertificateEncodingException { 1865 if (certs == null) { 1866 return null; 1867 } 1868 List<byte[]> result = new ArrayList<>(certs.size()); 1869 for (Certificate cert : certs) { 1870 if (!(cert instanceof X509Certificate)) { 1871 throw new CertificateEncodingException("Only X509 certificates supported."); 1872 } 1873 result.add(cert.getEncoded()); 1874 } 1875 return result; 1876 } 1877 1878 /** 1879 * Requests checksums for the APK file in session. 1880 * <p> 1881 * A possible use case is replying to {@link Intent#ACTION_PACKAGE_NEEDS_VERIFICATION} 1882 * broadcast. 1883 * The checksums will be returned asynchronously via onChecksumsReadyListener. 1884 * <p> 1885 * By default returns all readily available checksums: 1886 * <ul> 1887 * <li>enforced by platform, 1888 * <li>enforced by the installer. 1889 * </ul> 1890 * If the caller needs a specific checksum type, they can specify it as required. 1891 * <p> 1892 * <b>Caution: Android can not verify installer-provided checksums. Make sure you specify 1893 * trusted installers.</b> 1894 * <p> 1895 * @param name previously written as part of this session. 1896 * {@link #openWrite} 1897 * @param required to explicitly request the checksum types. Will incur significant 1898 * CPU/memory/disk usage. 1899 * @param trustedInstallers for checksums enforced by installer, which installers are to be 1900 * trusted. 1901 * {@link PackageManager#TRUST_ALL} will return checksums from any 1902 * installer, 1903 * {@link PackageManager#TRUST_NONE} disables optimized 1904 * installer-enforced checksums, otherwise the list has to be 1905 * a non-empty list of certificates. 1906 * @param executor the {@link Executor} on which to invoke the callback 1907 * @param onChecksumsReadyListener called once when the results are available. 1908 * @throws CertificateEncodingException if an encoding error occurs for trustedInstallers. 1909 * @throws FileNotFoundException if the file does not exist. 1910 * @throws IllegalArgumentException if the list of trusted installer certificates is empty. 1911 */ requestChecksums(@onNull String name, @Checksum.TypeMask int required, @NonNull List<Certificate> trustedInstallers, @NonNull @CallbackExecutor Executor executor, @NonNull PackageManager.OnChecksumsReadyListener onChecksumsReadyListener)1912 public void requestChecksums(@NonNull String name, @Checksum.TypeMask int required, 1913 @NonNull List<Certificate> trustedInstallers, 1914 @NonNull @CallbackExecutor Executor executor, 1915 @NonNull PackageManager.OnChecksumsReadyListener onChecksumsReadyListener) 1916 throws CertificateEncodingException, FileNotFoundException { 1917 Objects.requireNonNull(name); 1918 Objects.requireNonNull(trustedInstallers); 1919 Objects.requireNonNull(executor); 1920 Objects.requireNonNull(onChecksumsReadyListener); 1921 if (trustedInstallers == PackageManager.TRUST_ALL) { 1922 trustedInstallers = null; 1923 } else if (trustedInstallers == PackageManager.TRUST_NONE) { 1924 trustedInstallers = Collections.emptyList(); 1925 } else if (trustedInstallers.isEmpty()) { 1926 throw new IllegalArgumentException( 1927 "trustedInstallers has to be one of TRUST_ALL/TRUST_NONE or a non-empty " 1928 + "list of certificates."); 1929 } 1930 try { 1931 IOnChecksumsReadyListener onChecksumsReadyListenerDelegate = 1932 new IOnChecksumsReadyListener.Stub() { 1933 @Override 1934 public void onChecksumsReady(List<ApkChecksum> checksums) 1935 throws RemoteException { 1936 executor.execute( 1937 () -> onChecksumsReadyListener.onChecksumsReady(checksums)); 1938 } 1939 }; 1940 mSession.requestChecksums(name, DEFAULT_CHECKSUMS, required, 1941 encodeCertificates(trustedInstallers), onChecksumsReadyListenerDelegate); 1942 } catch (ParcelableException e) { 1943 e.maybeRethrow(FileNotFoundException.class); 1944 throw new RuntimeException(e); 1945 } catch (RemoteException e) { 1946 throw e.rethrowFromSystemServer(); 1947 } 1948 } 1949 1950 /** 1951 * Attempt to commit everything staged in this session. This may require 1952 * user intervention, and so it may not happen immediately. The final 1953 * result of the commit will be reported through the given callback. 1954 * <p> 1955 * Once this method is called, the session is sealed and no additional mutations may be 1956 * performed on the session. In case of device reboot or data loader transient failure 1957 * before the session has been finalized, you may commit the session again. 1958 * <p> 1959 * If the installer is the device owner, the affiliated profile owner, or has received 1960 * user pre-approval of this session, there will be no user intervention. 1961 * 1962 * @param statusReceiver Called when the state of the session changes. Intents 1963 * sent to this receiver contain {@link #EXTRA_STATUS}. Refer to the 1964 * individual status codes on how to handle them. 1965 * 1966 * @throws SecurityException if streams opened through 1967 * {@link #openWrite(String, long, long)} are still open. 1968 * @throws IllegalArgumentException if the {@code statusReceiver} from an immutable 1969 * {@link android.app.PendingIntent} when caller has a target SDK of API 1970 * version 35 or above. 1971 * 1972 * @see android.app.admin.DevicePolicyManager 1973 * @see #requestUserPreapproval 1974 */ commit(@onNull IntentSender statusReceiver)1975 public void commit(@NonNull IntentSender statusReceiver) { 1976 try { 1977 mSession.commit(statusReceiver, false); 1978 } catch (RemoteException e) { 1979 throw e.rethrowFromSystemServer(); 1980 } 1981 } 1982 1983 /** 1984 * Attempt to commit a session that has been {@link #transfer(String) transferred}. 1985 * 1986 * <p>If the device reboots before the session has been finalized, you may commit the 1987 * session again. 1988 * 1989 * <p>The caller of this method is responsible to ensure the safety of the session. As the 1990 * session was created by another - usually less trusted - app, it is paramount that before 1991 * committing <u>all</u> public and system {@link SessionInfo properties of the session} 1992 * and <u>all</u> {@link #openRead(String) APKs} are verified by the caller. It might happen 1993 * that new properties are added to the session with a new API revision. In this case the 1994 * callers need to be updated. 1995 * 1996 * @param statusReceiver Called when the state of the session changes. Intents 1997 * sent to this receiver contain {@link #EXTRA_STATUS}. Refer to the 1998 * individual status codes on how to handle them. 1999 * @throws IllegalArgumentException if the {@code statusReceiver} from an immutable 2000 * {@link android.app.PendingIntent} when caller has a target SDK of API 2001 * 35 or above. 2002 * 2003 * @hide 2004 */ 2005 @SystemApi 2006 @RequiresPermission(android.Manifest.permission.INSTALL_PACKAGES) commitTransferred(@onNull IntentSender statusReceiver)2007 public void commitTransferred(@NonNull IntentSender statusReceiver) { 2008 try { 2009 mSession.commit(statusReceiver, true); 2010 } catch (RemoteException e) { 2011 throw e.rethrowFromSystemServer(); 2012 } 2013 } 2014 2015 /** 2016 * Transfer the session to a new owner. 2017 * <p> 2018 * Only sessions that update the installing app can be transferred. 2019 * <p> 2020 * After the transfer to a package with a different uid all method calls on the session 2021 * will cause {@link SecurityException}s. 2022 * <p> 2023 * Once this method is called, the session is sealed and no additional mutations beside 2024 * committing it may be performed on the session. 2025 * 2026 * @param packageName The package of the new owner. Needs to hold the INSTALL_PACKAGES 2027 * permission. 2028 * 2029 * @throws PackageManager.NameNotFoundException if the new owner could not be found. 2030 * @throws SecurityException if called after the session has been committed or abandoned. 2031 * @throws IllegalStateException if streams opened through 2032 * {@link #openWrite(String, long, long) are still open. 2033 * @throws IllegalArgumentException if {@code packageName} is invalid. 2034 */ transfer(@onNull String packageName)2035 public void transfer(@NonNull String packageName) 2036 throws PackageManager.NameNotFoundException { 2037 Preconditions.checkArgument(!TextUtils.isEmpty(packageName)); 2038 2039 try { 2040 mSession.transfer(packageName); 2041 } catch (ParcelableException e) { 2042 e.maybeRethrow(PackageManager.NameNotFoundException.class); 2043 throw new RuntimeException(e); 2044 } catch (RemoteException e) { 2045 throw e.rethrowFromSystemServer(); 2046 } 2047 } 2048 2049 /** 2050 * Release this session object. You can open the session again if it 2051 * hasn't been finalized. 2052 */ 2053 @Override close()2054 public void close() { 2055 try { 2056 mSession.close(); 2057 } catch (RemoteException e) { 2058 throw e.rethrowFromSystemServer(); 2059 } 2060 } 2061 2062 /** 2063 * Completely abandon this session, destroying all staged data and 2064 * rendering it invalid. Abandoned sessions will be reported to 2065 * {@link SessionCallback} listeners as failures. This is equivalent to 2066 * {@link #abandonSession(int)}. 2067 * <p>If the parent is abandoned, all children will also be abandoned. Any written data 2068 * would be destroyed and the created {@link Session} information will be discarded.</p> 2069 */ abandon()2070 public void abandon() { 2071 try { 2072 mSession.abandon(); 2073 } catch (RemoteException e) { 2074 throw e.rethrowFromSystemServer(); 2075 } 2076 } 2077 2078 /** 2079 * @return {@code true} if this session will commit more than one package when it is 2080 * committed. 2081 */ isMultiPackage()2082 public boolean isMultiPackage() { 2083 try { 2084 return mSession.isMultiPackage(); 2085 } catch (RemoteException e) { 2086 throw e.rethrowFromSystemServer(); 2087 } 2088 } 2089 2090 /** 2091 * @return {@code true} if this session will be staged and applied at next reboot. 2092 */ isStaged()2093 public boolean isStaged() { 2094 try { 2095 return mSession.isStaged(); 2096 } catch (RemoteException e) { 2097 throw e.rethrowFromSystemServer(); 2098 } 2099 } 2100 2101 /** 2102 * @return Session's {@link SessionParams#installFlags}. 2103 * @hide 2104 */ getInstallFlags()2105 public int getInstallFlags() { 2106 try { 2107 return mSession.getInstallFlags(); 2108 } catch (RemoteException e) { 2109 throw e.rethrowFromSystemServer(); 2110 } 2111 } 2112 2113 /** 2114 * @return the session ID of the multi-package session that this belongs to or 2115 * {@link SessionInfo#INVALID_ID} if it does not belong to a multi-package session. 2116 */ getParentSessionId()2117 public int getParentSessionId() { 2118 try { 2119 return mSession.getParentSessionId(); 2120 } catch (RemoteException e) { 2121 throw e.rethrowFromSystemServer(); 2122 } 2123 } 2124 2125 /** 2126 * @return the set of session IDs that will be committed atomically when this session is 2127 * committed if this is a multi-package session or null if none exist. 2128 */ 2129 @NonNull getChildSessionIds()2130 public int[] getChildSessionIds() { 2131 try { 2132 return mSession.getChildSessionIds(); 2133 } catch (RemoteException e) { 2134 throw e.rethrowFromSystemServer(); 2135 } 2136 } 2137 2138 /** 2139 * Adds a session ID to the set of sessions that will be committed atomically 2140 * when this session is committed. 2141 * 2142 * <p>If the parent is staged or has rollback enabled, all children must have 2143 * the same properties.</p> 2144 * <p>If the parent is abandoned, all children will also be abandoned.</p> 2145 * 2146 * @param sessionId the session ID to add to this multi-package session. 2147 */ addChildSessionId(int sessionId)2148 public void addChildSessionId(int sessionId) { 2149 try { 2150 mSession.addChildSessionId(sessionId); 2151 } catch (RemoteException e) { 2152 e.rethrowFromSystemServer(); 2153 } 2154 } 2155 2156 /** 2157 * Removes a session ID from the set of sessions that will be committed 2158 * atomically when this session is committed. 2159 * 2160 * @param sessionId the session ID to remove from this multi-package session. 2161 */ removeChildSessionId(int sessionId)2162 public void removeChildSessionId(int sessionId) { 2163 try { 2164 mSession.removeChildSessionId(sessionId); 2165 } catch (RemoteException e) { 2166 e.rethrowFromSystemServer(); 2167 } 2168 } 2169 2170 /** 2171 * @return A PersistableBundle containing the app metadata set with 2172 * {@link Session#setAppMetadata(PersistableBundle)}. In the case where this data does not 2173 * exist, an empty PersistableBundle is returned. 2174 */ 2175 @NonNull getAppMetadata()2176 public PersistableBundle getAppMetadata() { 2177 PersistableBundle data = null; 2178 try { 2179 ParcelFileDescriptor pfd = mSession.getAppMetadataFd(); 2180 if (pfd != null) { 2181 try (InputStream inputStream = 2182 new ParcelFileDescriptor.AutoCloseInputStream(pfd)) { 2183 data = PersistableBundle.readFromStream(inputStream); 2184 } 2185 } 2186 } catch (RemoteException e) { 2187 e.rethrowFromSystemServer(); 2188 } catch (IOException e) { 2189 throw new RuntimeException(e); 2190 } 2191 return data != null ? data : new PersistableBundle(); 2192 } 2193 openWriteAppMetadata()2194 private OutputStream openWriteAppMetadata() throws IOException { 2195 try { 2196 if (ENABLE_REVOCABLE_FD) { 2197 return new ParcelFileDescriptor.AutoCloseOutputStream( 2198 mSession.openWriteAppMetadata()); 2199 } else { 2200 final ParcelFileDescriptor clientSocket = mSession.openWriteAppMetadata(); 2201 return new FileBridge.FileBridgeOutputStream(clientSocket); 2202 } 2203 } catch (RuntimeException e) { 2204 ExceptionUtils.maybeUnwrapIOException(e); 2205 throw e; 2206 } catch (RemoteException e) { 2207 throw e.rethrowFromSystemServer(); 2208 } 2209 } 2210 2211 /** 2212 * Optionally set the app metadata. The size of this data cannot exceed the maximum allowed. 2213 * Any existing data from the previous install will not be retained even if no data is set 2214 * for the current install session. Setting data to null or an empty PersistableBundle will 2215 * remove any metadata that has previously been set in the same session. 2216 * 2217 * @param data a PersistableBundle containing the app metadata. 2218 * @throws IOException if writing the data fails. 2219 */ setAppMetadata(@ullable PersistableBundle data)2220 public void setAppMetadata(@Nullable PersistableBundle data) throws IOException { 2221 if (data == null || data.isEmpty()) { 2222 try { 2223 mSession.removeAppMetadata(); 2224 } catch (RemoteException e) { 2225 throw e.rethrowFromSystemServer(); 2226 } 2227 return; 2228 } 2229 Objects.requireNonNull(data); 2230 try (OutputStream outputStream = openWriteAppMetadata()) { 2231 data.writeToStream(outputStream); 2232 } 2233 } 2234 2235 /** 2236 * Attempt to request the approval before committing this session. 2237 * 2238 * For installers that have been granted the 2239 * {@link android.Manifest.permission#REQUEST_INSTALL_PACKAGES REQUEST_INSTALL_PACKAGES} 2240 * permission, they can request the approval from users before 2241 * {@link Session#commit(IntentSender)} is called. This may require user intervention as 2242 * well. When user intervention is required, installers will receive a 2243 * {@link #STATUS_PENDING_USER_ACTION} callback, and {@link #STATUS_SUCCESS} otherwise. 2244 * In case that requesting user pre-approval is not available, installers will receive 2245 * {@link #STATUS_FAILURE_BLOCKED} instead. Note that if the users decline the request, 2246 * this session will be abandoned. 2247 * 2248 * If user intervention is required but never resolved, or requesting user 2249 * pre-approval is not available, you may still call {@link Session#commit(IntentSender)} 2250 * as the typical installation. 2251 * 2252 * @param details the adequate context to this session for requesting the approval from 2253 * users prior to commit. 2254 * @param statusReceiver called when the state of the session changes. 2255 * Intents sent to this receiver contain {@link #EXTRA_STATUS} 2256 * and the {@link #EXTRA_PRE_APPROVAL} would be {@code true}. 2257 * Refer to the individual status codes on how to handle them. 2258 * 2259 * @throws IllegalArgumentException when {@link PreapprovalDetails} is {@code null}. 2260 * @throws IllegalArgumentException if {@link IntentSender} is {@code null}. 2261 * @throws IllegalStateException if called on a multi-package session (no matter 2262 * the parent session or any of the children sessions). 2263 * @throws IllegalStateException if called again after this method has been called on 2264 * this session. 2265 * @throws SecurityException when the caller does not own this session. 2266 * @throws SecurityException if called after the session has been committed or abandoned. 2267 */ requestUserPreapproval(@onNull PreapprovalDetails details, @NonNull IntentSender statusReceiver)2268 public void requestUserPreapproval(@NonNull PreapprovalDetails details, 2269 @NonNull IntentSender statusReceiver) { 2270 Preconditions.checkArgument(details != null, "preapprovalDetails cannot be null."); 2271 Preconditions.checkArgument(statusReceiver != null, "statusReceiver cannot be null."); 2272 try { 2273 mSession.requestUserPreapproval(details, statusReceiver); 2274 } catch (RemoteException e) { 2275 e.rethrowFromSystemServer(); 2276 } 2277 } 2278 2279 /** 2280 * @return {@code true} if this session will keep the existing application enabled setting 2281 * after installation. 2282 */ isApplicationEnabledSettingPersistent()2283 public boolean isApplicationEnabledSettingPersistent() { 2284 try { 2285 return mSession.isApplicationEnabledSettingPersistent(); 2286 } catch (RemoteException e) { 2287 throw e.rethrowFromSystemServer(); 2288 } 2289 } 2290 2291 /** 2292 * @return {@code true} if the installer requested the update ownership enforcement 2293 * for the packages in this session. 2294 * 2295 * @see PackageInstaller.SessionParams#setRequestUpdateOwnership 2296 */ isRequestUpdateOwnership()2297 public boolean isRequestUpdateOwnership() { 2298 try { 2299 return mSession.isRequestUpdateOwnership(); 2300 } catch (RemoteException e) { 2301 throw e.rethrowFromSystemServer(); 2302 } 2303 } 2304 2305 /** 2306 * Sets the pre-verified domains for the app to be installed. By setting pre-verified 2307 * domains, the installer allows the app to be opened by the app links of these domains 2308 * immediately after it is installed. 2309 * 2310 * <p>The specified pre-verified domains should be a subset of the hostnames declared with 2311 * {@code android:host} and {@code android:autoVerify=true} in the intent filters of the 2312 * AndroidManifest.xml of the app. If some of the specified domains are not declared in 2313 * the manifest, they will be ignored.</p> 2314 * <p>If this API is called multiple times on the same {@link #Session}, the last call 2315 * overrides the previous ones.</p> 2316 * <p>The instant app installer is the only entity that may call this API. 2317 * </p> 2318 * 2319 * @param preVerifiedDomains domains that are already pre-verified by the installer. 2320 * 2321 * @throws IllegalArgumentException if the number or the total size of the pre-verified 2322 * domains exceeds the maximum allowed, or if the domain 2323 * names contain invalid characters. 2324 * @throws SecurityException if called from an installer that is not the instant app 2325 * installer of the device, or if called after the session has 2326 * been committed or abandoned. 2327 * 2328 * @hide 2329 */ 2330 @SystemApi 2331 @FlaggedApi(Flags.FLAG_SET_PRE_VERIFIED_DOMAINS) 2332 @RequiresPermission(Manifest.permission.ACCESS_INSTANT_APPS) setPreVerifiedDomains(@onNull Set<String> preVerifiedDomains)2333 public void setPreVerifiedDomains(@NonNull Set<String> preVerifiedDomains) { 2334 Preconditions.checkArgument(preVerifiedDomains != null && !preVerifiedDomains.isEmpty(), 2335 "Provided pre-verified domains cannot be null or empty."); 2336 try { 2337 mSession.setPreVerifiedDomains(new DomainSet(preVerifiedDomains)); 2338 } catch (RemoteException e) { 2339 throw e.rethrowFromSystemServer(); 2340 } 2341 } 2342 2343 /** 2344 * Retrieve the pre-verified domains set in a session. 2345 * See {@link #setPreVerifiedDomains(Set)} for the definition of pre-verified domains. 2346 * 2347 * @throws SecurityException if called from an installer that is not the owner of the 2348 * session, or if called after the session has been committed or 2349 * abandoned. 2350 * @hide 2351 */ 2352 @SystemApi 2353 @FlaggedApi(Flags.FLAG_SET_PRE_VERIFIED_DOMAINS) 2354 @RequiresPermission(Manifest.permission.ACCESS_INSTANT_APPS) 2355 @NonNull getPreVerifiedDomains()2356 public Set<String> getPreVerifiedDomains() { 2357 try { 2358 DomainSet domainSet = mSession.getPreVerifiedDomains(); 2359 return domainSet != null ? domainSet.getDomains() : Collections.emptySet(); 2360 } catch (RemoteException e) { 2361 throw e.rethrowFromSystemServer(); 2362 } 2363 } 2364 } 2365 2366 /** 2367 * Parse a single APK or a directory of APKs to get install relevant information about 2368 * the package wrapped in {@link InstallInfo}. 2369 * @throws PackageParsingException if the package source file(s) provided is(are) not valid, 2370 * or the parser isn't able to parse the supplied source(s). 2371 * @hide 2372 */ 2373 @SystemApi 2374 @NonNull readInstallInfo(@onNull File file, int flags)2375 public InstallInfo readInstallInfo(@NonNull File file, int flags) 2376 throws PackageParsingException { 2377 final ParseTypeImpl input = ParseTypeImpl.forDefaultParsing(); 2378 final ParseResult<PackageLite> result = ApkLiteParseUtils.parsePackageLite( 2379 input.reset(), file, flags); 2380 if (result.isError()) { 2381 throw new PackageParsingException(result.getErrorCode(), result.getErrorMessage()); 2382 } 2383 return new InstallInfo(result); 2384 } 2385 2386 /** 2387 * Parse a single APK file passed as an FD to get install relevant information about 2388 * the package wrapped in {@link InstallInfo}. 2389 * @throws PackageParsingException if the package source file(s) provided is(are) not valid, 2390 * or the parser isn't able to parse the supplied source(s). 2391 * @hide 2392 */ 2393 @SystemApi 2394 @NonNull 2395 @FlaggedApi(Flags.FLAG_READ_INSTALL_INFO) readInstallInfo(@onNull ParcelFileDescriptor pfd, @Nullable String debugPathName, int flags)2396 public InstallInfo readInstallInfo(@NonNull ParcelFileDescriptor pfd, 2397 @Nullable String debugPathName, int flags) throws PackageParsingException { 2398 final ParseTypeImpl input = ParseTypeImpl.forDefaultParsing(); 2399 final ParseResult<PackageLite> result = ApkLiteParseUtils.parseMonolithicPackageLite(input, 2400 pfd.getFileDescriptor(), debugPathName, flags); 2401 if (result.isError()) { 2402 throw new PackageParsingException(result.getErrorCode(), result.getErrorMessage()); 2403 } 2404 return new InstallInfo(result); 2405 } 2406 2407 /** 2408 * Requests to archive a package which is currently installed. 2409 * 2410 * <p> During the archival process, the apps APKs and cache are removed from the device while 2411 * the user data is kept. Through the {@link #requestUnarchive} call, apps 2412 * can be restored again through their responsible installer. 2413 * 2414 * <p> Archived apps are returned as displayable apps through the {@link LauncherApps} APIs and 2415 * will be displayed to users with UI treatment to highlight that said apps are archived. If 2416 * a user taps on an archived app, the app will be unarchived and the restoration process is 2417 * communicated. 2418 * 2419 * @param statusReceiver Callback used to notify when the operation is completed. 2420 * @throws PackageManager.NameNotFoundException If {@code packageName} isn't found or not 2421 * available to the caller or isn't archived. 2422 */ 2423 @RequiresPermission(anyOf = { 2424 Manifest.permission.DELETE_PACKAGES, 2425 Manifest.permission.REQUEST_DELETE_PACKAGES}) 2426 @FlaggedApi(Flags.FLAG_ARCHIVING) requestArchive(@onNull String packageName, @NonNull IntentSender statusReceiver)2427 public void requestArchive(@NonNull String packageName, @NonNull IntentSender statusReceiver) 2428 throws PackageManager.NameNotFoundException { 2429 try { 2430 mInstaller.requestArchive(packageName, mInstallerPackageName, /*flags=*/ 0, 2431 statusReceiver, new UserHandle(mUserId)); 2432 } catch (ParcelableException e) { 2433 e.maybeRethrow(PackageManager.NameNotFoundException.class); 2434 throw new RuntimeException(e); 2435 } catch (RemoteException e) { 2436 throw e.rethrowFromSystemServer(); 2437 } 2438 } 2439 2440 /** 2441 * Requests to unarchive a currently archived package. 2442 * 2443 * <p> Sends a request to unarchive an app to the responsible installer. The installer is 2444 * determined by {@link InstallSourceInfo#getUpdateOwnerPackageName()}, or 2445 * {@link InstallSourceInfo#getInstallingPackageName()} if the former value is null. 2446 * 2447 * <p> The installation will happen asynchronously and can be observed through 2448 * {@link android.content.Intent#ACTION_PACKAGE_ADDED}. 2449 * 2450 * @param statusReceiver Callback used to notify whether the installer has accepted the 2451 * unarchival request or an error has occurred. The status update will be 2452 * sent though {@link #EXTRA_UNARCHIVE_STATUS}. Only one status will be 2453 * sent. 2454 * @throws PackageManager.NameNotFoundException If {@code packageName} isn't found or not 2455 * visible to the caller or if the package has no 2456 * installer on the device anymore to unarchive it. 2457 * @throws IOException If parameters were unsatisfiable, such as lack of disk space. 2458 */ 2459 @RequiresPermission(anyOf = { 2460 Manifest.permission.INSTALL_PACKAGES, 2461 Manifest.permission.REQUEST_INSTALL_PACKAGES}) 2462 @FlaggedApi(Flags.FLAG_ARCHIVING) requestUnarchive(@onNull String packageName, @NonNull IntentSender statusReceiver)2463 public void requestUnarchive(@NonNull String packageName, @NonNull IntentSender statusReceiver) 2464 throws IOException, PackageManager.NameNotFoundException { 2465 try { 2466 mInstaller.requestUnarchive(packageName, mInstallerPackageName, statusReceiver, 2467 new UserHandle(mUserId)); 2468 } catch (ParcelableException e) { 2469 e.maybeRethrow(IOException.class); 2470 e.maybeRethrow(PackageManager.NameNotFoundException.class); 2471 throw new RuntimeException(e); 2472 } catch (RemoteException e) { 2473 throw e.rethrowFromSystemServer(); 2474 } 2475 } 2476 2477 /** 2478 * Reports the status of an unarchival to the system. 2479 * 2480 * @param unarchiveId the ID provided by the system as part of the 2481 * intent.action.UNARCHIVE broadcast with EXTRA_UNARCHIVE_ID. 2482 * @param status is used for the system to provide the user with necessary 2483 * follow-up steps or errors. 2484 * @param requiredStorageBytes If the error is UNARCHIVAL_ERROR_INSUFFICIENT_STORAGE this field 2485 * should be set to specify how many additional bytes of storage 2486 * are required to unarchive the app. 2487 * @param userActionIntent Optional intent to start a follow up action required to 2488 * facilitate the unarchival flow (e.g. user needs to log in). 2489 * @throws PackageManager.NameNotFoundException if no unarchival with {@code unarchiveId} exists 2490 */ 2491 // TODO(b/314960798) Remove old API once it's unused 2492 @RequiresPermission(anyOf = { 2493 Manifest.permission.INSTALL_PACKAGES, 2494 Manifest.permission.REQUEST_INSTALL_PACKAGES}) 2495 @FlaggedApi(Flags.FLAG_ARCHIVING) reportUnarchivalStatus(int unarchiveId, @UnarchivalStatus int status, long requiredStorageBytes, @Nullable PendingIntent userActionIntent)2496 public void reportUnarchivalStatus(int unarchiveId, @UnarchivalStatus int status, 2497 long requiredStorageBytes, @Nullable PendingIntent userActionIntent) 2498 throws PackageManager.NameNotFoundException { 2499 try { 2500 mInstaller.reportUnarchivalStatus(unarchiveId, status, requiredStorageBytes, 2501 userActionIntent, new UserHandle(mUserId)); 2502 } catch (ParcelableException e) { 2503 e.maybeRethrow(PackageManager.NameNotFoundException.class); 2504 throw new RuntimeException(e); 2505 } catch (RemoteException e) { 2506 throw e.rethrowFromSystemServer(); 2507 } 2508 } 2509 2510 /** 2511 * Reports the state of an unarchival to the system. 2512 * 2513 * @see UnarchivalState for the different state options. 2514 * @throws PackageManager.NameNotFoundException if no unarchival with {@code unarchiveId} exists 2515 */ 2516 @RequiresPermission(anyOf = { 2517 Manifest.permission.INSTALL_PACKAGES, 2518 Manifest.permission.REQUEST_INSTALL_PACKAGES}) 2519 @FlaggedApi(Flags.FLAG_ARCHIVING) reportUnarchivalState(@onNull UnarchivalState unarchivalState)2520 public void reportUnarchivalState(@NonNull UnarchivalState unarchivalState) 2521 throws PackageManager.NameNotFoundException { 2522 Objects.requireNonNull(unarchivalState); 2523 try { 2524 mInstaller.reportUnarchivalStatus(unarchivalState.getUnarchiveId(), 2525 unarchivalState.getStatus(), unarchivalState.getRequiredStorageBytes(), 2526 unarchivalState.getUserActionIntent(), new UserHandle(mUserId)); 2527 } catch (ParcelableException e) { 2528 e.maybeRethrow(PackageManager.NameNotFoundException.class); 2529 } catch (RemoteException e) { 2530 throw e.rethrowFromSystemServer(); 2531 } 2532 } 2533 2534 // (b/239722738) This class serves as a bridge between the PackageLite class, which 2535 // is a hidden class, and the consumers of this class. (e.g. InstallInstalling.java) 2536 // This is a part of an effort to remove dependency on hidden APIs and use SystemAPIs or 2537 // public APIs. 2538 /** 2539 * Install related details from an APK or a folder of APK(s). 2540 * 2541 * @hide 2542 */ 2543 @SystemApi 2544 public static class InstallInfo { 2545 2546 /** @hide */ 2547 @IntDef(prefix = { "INSTALL_LOCATION_" }, value = { 2548 INSTALL_LOCATION_AUTO, 2549 INSTALL_LOCATION_INTERNAL_ONLY, 2550 INSTALL_LOCATION_PREFER_EXTERNAL 2551 }) 2552 @Retention(RetentionPolicy.SOURCE) 2553 public @interface InstallLocation{} 2554 2555 private PackageLite mPkg; 2556 InstallInfo(ParseResult<PackageLite> result)2557 InstallInfo(ParseResult<PackageLite> result) { 2558 mPkg = result.getResult(); 2559 } 2560 2561 /** 2562 * See {@link PackageLite#getPackageName()} 2563 */ 2564 @NonNull getPackageName()2565 public String getPackageName() { 2566 return mPkg.getPackageName(); 2567 } 2568 2569 /** 2570 * @return The default install location defined by an application in 2571 * {@link android.R.attr#installLocation} attribute. 2572 */ getInstallLocation()2573 public @InstallLocation int getInstallLocation() { 2574 return mPkg.getInstallLocation(); 2575 } 2576 2577 /** 2578 * @param params {@link SessionParams} of the installation 2579 * @return Total disk space occupied by an application after installation. 2580 * Includes the size of the raw APKs, possibly unpacked resources, raw dex metadata files, 2581 * and all relevant native code. 2582 * @throws IOException when size of native binaries cannot be calculated. 2583 */ calculateInstalledSize(@onNull SessionParams params)2584 public long calculateInstalledSize(@NonNull SessionParams params) throws IOException { 2585 return InstallLocationUtils.calculateInstalledSize(mPkg, params.abiOverride); 2586 } 2587 2588 /** 2589 * @param params {@link SessionParams} of the installation 2590 * @param pfd of an APK opened for read 2591 * @return Total disk space occupied by an application after installation. 2592 * Includes the size of the raw APKs, possibly unpacked resources, raw dex metadata files, 2593 * and all relevant native code. 2594 * @throws IOException when size of native binaries cannot be calculated. 2595 */ 2596 @FlaggedApi(Flags.FLAG_READ_INSTALL_INFO) calculateInstalledSize(@onNull SessionParams params, @NonNull ParcelFileDescriptor pfd)2597 public long calculateInstalledSize(@NonNull SessionParams params, 2598 @NonNull ParcelFileDescriptor pfd) throws IOException { 2599 return InstallLocationUtils.calculateInstalledSize(mPkg, params.abiOverride, 2600 pfd.getFileDescriptor()); 2601 } 2602 } 2603 2604 /** 2605 * Generic exception class for using with parsing operations. 2606 * 2607 * @hide 2608 */ 2609 @SystemApi 2610 public static class PackageParsingException extends Exception { 2611 private final int mErrorCode; 2612 2613 /** {@hide} */ PackageParsingException(int errorCode, @Nullable String detailedMessage)2614 public PackageParsingException(int errorCode, @Nullable String detailedMessage) { 2615 super(detailedMessage); 2616 mErrorCode = errorCode; 2617 } 2618 getErrorCode()2619 public int getErrorCode() { 2620 return mErrorCode; 2621 } 2622 } 2623 2624 /** 2625 * Parameters for creating a new {@link PackageInstaller.Session}. 2626 */ 2627 public static class SessionParams implements Parcelable { 2628 2629 /** {@hide} */ 2630 public static final int MODE_INVALID = -1; 2631 2632 /** 2633 * Mode for an install session whose staged APKs should fully replace any 2634 * existing APKs for the target app. 2635 */ 2636 public static final int MODE_FULL_INSTALL = 1; 2637 2638 /** 2639 * Mode for an install session that should inherit any existing APKs for the 2640 * target app, unless they have been explicitly overridden (based on split 2641 * name) by the session. For example, this can be used to add one or more 2642 * split APKs to an existing installation. 2643 * <p> 2644 * If there are no existing APKs for the target app, this behaves like 2645 * {@link #MODE_FULL_INSTALL}. 2646 */ 2647 public static final int MODE_INHERIT_EXISTING = 2; 2648 2649 /** 2650 * Special constant to refer to all restricted permissions. 2651 */ 2652 public static final @NonNull Set<String> RESTRICTED_PERMISSIONS_ALL = new ArraySet<>(); 2653 2654 /** {@hide} */ 2655 public static final int UID_UNKNOWN = -1; 2656 2657 /** 2658 * This value is derived from the maximum file name length. No package above this limit 2659 * can ever be successfully installed on the device. 2660 * @hide 2661 */ 2662 public static final int MAX_PACKAGE_NAME_LENGTH = 255; 2663 2664 /** @hide */ 2665 @IntDef(prefix = {"USER_ACTION_"}, value = { 2666 USER_ACTION_UNSPECIFIED, 2667 USER_ACTION_REQUIRED, 2668 USER_ACTION_NOT_REQUIRED 2669 }) 2670 @Retention(RetentionPolicy.SOURCE) 2671 public @interface UserActionRequirement {} 2672 2673 /** 2674 * This value is passed by the installer to {@link SessionParams#setRequireUserAction(int)} 2675 * to indicate that user action is unspecified for this install. 2676 * {@code requireUserAction} also defaults to this value unless modified by 2677 * {@link SessionParams#setRequireUserAction(int)} 2678 */ 2679 public static final int USER_ACTION_UNSPECIFIED = 0; 2680 2681 /** 2682 * This value is passed by the installer to {@link SessionParams#setRequireUserAction(int)} 2683 * to indicate that user action is required for this install. 2684 */ 2685 public static final int USER_ACTION_REQUIRED = 1; 2686 2687 /** 2688 * This value is passed by the installer to {@link SessionParams#setRequireUserAction(int)} 2689 * to indicate that user action is not required for this install. 2690 */ 2691 public static final int USER_ACTION_NOT_REQUIRED = 2; 2692 2693 /** @hide */ 2694 @IntDef(prefix = {"PERMISSION_STATE_"}, value = { 2695 PERMISSION_STATE_DEFAULT, 2696 PERMISSION_STATE_GRANTED, 2697 PERMISSION_STATE_DENIED, 2698 }) 2699 @Retention(RetentionPolicy.SOURCE) 2700 public @interface PermissionState {} 2701 2702 /** 2703 * Value is passed by the installer to {@link #setPermissionState(String, int)} to set 2704 * the state of a permission. This indicates no preference by the installer, relying on 2705 * the device's default policy to set the grant state of the permission. 2706 */ 2707 public static final int PERMISSION_STATE_DEFAULT = 0; 2708 2709 /** 2710 * Value is passed by the installer to {@link #setPermissionState(String, int)} to set 2711 * the state of a permission. This indicates the installers wants to automatically grant 2712 * the permission to the package being installed. The user and other actors in the system 2713 * may still be able to deny the permission after installation. 2714 */ 2715 public static final int PERMISSION_STATE_GRANTED = 1; 2716 2717 /** 2718 * Value is passed by the installer to {@link #setPermissionState(String, int)} to set 2719 * the state of a permission. This indicates the installers wants to deny the permission 2720 * by default to the package being installed. The user and other actors in the system may 2721 * still be able to grant the permission after installation. 2722 */ 2723 public static final int PERMISSION_STATE_DENIED = 2; 2724 2725 /** {@hide} */ 2726 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) 2727 public int mode = MODE_INVALID; 2728 /** {@hide} */ 2729 @UnsupportedAppUsage 2730 public int installFlags = PackageManager.INSTALL_ALL_WHITELIST_RESTRICTED_PERMISSIONS; 2731 /** {@hide} */ 2732 public int installLocation = PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY; 2733 /** {@hide} */ 2734 public @InstallReason int installReason = PackageManager.INSTALL_REASON_UNKNOWN; 2735 /** 2736 * {@hide} 2737 * 2738 * This flag indicates which installation scenario best describes this session. The system 2739 * may use this value when making decisions about how to handle the installation, such as 2740 * prioritizing system health or user experience. 2741 */ 2742 public @InstallScenario int installScenario = PackageManager.INSTALL_SCENARIO_DEFAULT; 2743 /** {@hide} */ 2744 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 2745 public long sizeBytes = -1; 2746 /** {@hide} */ 2747 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) 2748 public String appPackageName; 2749 /** {@hide} */ 2750 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 2751 public Bitmap appIcon; 2752 /** {@hide} */ 2753 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) 2754 public String appLabel; 2755 /** {@hide} */ 2756 public long appIconLastModified = -1; 2757 /** {@hide} */ 2758 public Uri originatingUri; 2759 /** {@hide} */ 2760 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 2761 public int originatingUid = UID_UNKNOWN; 2762 /** {@hide} */ 2763 public Uri referrerUri; 2764 /** {@hide} */ 2765 public String abiOverride; 2766 /** {@hide} */ 2767 public String volumeUuid; 2768 /** {@hide} */ 2769 public List<String> whitelistedRestrictedPermissions; 2770 /** {@hide} */ 2771 public int autoRevokePermissionsMode = MODE_DEFAULT; 2772 /** {@hide} */ 2773 public String installerPackageName; 2774 /** {@hide} */ 2775 public boolean isMultiPackage; 2776 /** {@hide} */ 2777 public int packageSource = PACKAGE_SOURCE_UNSPECIFIED; 2778 /** {@hide} */ 2779 public boolean isStaged; 2780 /** {@hide} */ 2781 public long requiredInstalledVersionCode = PackageManager.VERSION_CODE_HIGHEST; 2782 /** {@hide} */ 2783 public DataLoaderParams dataLoaderParams; 2784 /** {@hide} */ 2785 public int rollbackDataPolicy = PackageManager.ROLLBACK_DATA_POLICY_RESTORE; 2786 /** @hide */ 2787 public long rollbackLifetimeMillis = 0; 2788 /** {@hide} */ 2789 public int rollbackImpactLevel = PackageManager.ROLLBACK_USER_IMPACT_LOW; 2790 /** {@hide} */ 2791 public boolean forceQueryableOverride; 2792 /** {@hide} */ 2793 public int requireUserAction = USER_ACTION_UNSPECIFIED; 2794 /** {@hide} */ 2795 public boolean applicationEnabledSettingPersistent = false; 2796 /** {@hide} */ 2797 public int developmentInstallFlags = 0; 2798 /** {@hide} */ 2799 public int unarchiveId = -1; 2800 /** {@hide} */ 2801 public @Nullable String dexoptCompilerFilter = null; 2802 2803 private final ArrayMap<String, Integer> mPermissionStates; 2804 2805 /** 2806 * Construct parameters for a new package install session. 2807 * 2808 * @param mode one of {@link #MODE_FULL_INSTALL} or 2809 * {@link #MODE_INHERIT_EXISTING} describing how the session 2810 * should interact with an existing app. 2811 */ SessionParams(int mode)2812 public SessionParams(int mode) { 2813 this.mode = mode; 2814 mPermissionStates = new ArrayMap<>(); 2815 } 2816 2817 /** {@hide} */ SessionParams(Parcel source)2818 public SessionParams(Parcel source) { 2819 mode = source.readInt(); 2820 installFlags = source.readInt(); 2821 installLocation = source.readInt(); 2822 installReason = source.readInt(); 2823 installScenario = source.readInt(); 2824 sizeBytes = source.readLong(); 2825 appPackageName = source.readString(); 2826 appIcon = source.readParcelable(null, android.graphics.Bitmap.class); 2827 appLabel = source.readString(); 2828 originatingUri = source.readParcelable(null, android.net.Uri.class); 2829 originatingUid = source.readInt(); 2830 referrerUri = source.readParcelable(null, android.net.Uri.class); 2831 abiOverride = source.readString(); 2832 volumeUuid = source.readString(); 2833 mPermissionStates = new ArrayMap<>(); 2834 source.readMap(mPermissionStates, null, String.class, Integer.class); 2835 whitelistedRestrictedPermissions = source.createStringArrayList(); 2836 autoRevokePermissionsMode = source.readInt(); 2837 installerPackageName = source.readString(); 2838 isMultiPackage = source.readBoolean(); 2839 isStaged = source.readBoolean(); 2840 forceQueryableOverride = source.readBoolean(); 2841 requiredInstalledVersionCode = source.readLong(); 2842 DataLoaderParamsParcel dataLoaderParamsParcel = source.readParcelable( 2843 DataLoaderParamsParcel.class.getClassLoader(), android.content.pm.DataLoaderParamsParcel.class); 2844 if (dataLoaderParamsParcel != null) { 2845 dataLoaderParams = new DataLoaderParams(dataLoaderParamsParcel); 2846 } 2847 rollbackDataPolicy = source.readInt(); 2848 rollbackLifetimeMillis = source.readLong(); 2849 rollbackImpactLevel = source.readInt(); 2850 requireUserAction = source.readInt(); 2851 packageSource = source.readInt(); 2852 applicationEnabledSettingPersistent = source.readBoolean(); 2853 developmentInstallFlags = source.readInt(); 2854 unarchiveId = source.readInt(); 2855 dexoptCompilerFilter = source.readString(); 2856 } 2857 2858 /** {@hide} */ copy()2859 public SessionParams copy() { 2860 SessionParams ret = new SessionParams(mode); 2861 ret.installFlags = installFlags; 2862 ret.installLocation = installLocation; 2863 ret.installReason = installReason; 2864 ret.installScenario = installScenario; 2865 ret.sizeBytes = sizeBytes; 2866 ret.appPackageName = appPackageName; 2867 ret.appIcon = appIcon; // not a copy. 2868 ret.appLabel = appLabel; 2869 ret.originatingUri = originatingUri; // not a copy, but immutable. 2870 ret.originatingUid = originatingUid; 2871 ret.referrerUri = referrerUri; // not a copy, but immutable. 2872 ret.abiOverride = abiOverride; 2873 ret.volumeUuid = volumeUuid; 2874 ret.mPermissionStates.putAll(mPermissionStates); 2875 ret.whitelistedRestrictedPermissions = whitelistedRestrictedPermissions; 2876 ret.autoRevokePermissionsMode = autoRevokePermissionsMode; 2877 ret.installerPackageName = installerPackageName; 2878 ret.isMultiPackage = isMultiPackage; 2879 ret.isStaged = isStaged; 2880 ret.forceQueryableOverride = forceQueryableOverride; 2881 ret.requiredInstalledVersionCode = requiredInstalledVersionCode; 2882 ret.dataLoaderParams = dataLoaderParams; 2883 ret.rollbackDataPolicy = rollbackDataPolicy; 2884 ret.rollbackLifetimeMillis = rollbackLifetimeMillis; 2885 ret.rollbackImpactLevel = rollbackImpactLevel; 2886 ret.requireUserAction = requireUserAction; 2887 ret.packageSource = packageSource; 2888 ret.applicationEnabledSettingPersistent = applicationEnabledSettingPersistent; 2889 ret.developmentInstallFlags = developmentInstallFlags; 2890 ret.unarchiveId = unarchiveId; 2891 ret.dexoptCompilerFilter = dexoptCompilerFilter; 2892 return ret; 2893 } 2894 2895 /** 2896 * Check if there are hidden options set. 2897 * 2898 * <p>Hidden options are those options that cannot be verified via public or system-api 2899 * methods on {@link SessionInfo}. 2900 * 2901 * @return {@code true} if any hidden option is set. 2902 * 2903 * @hide 2904 */ areHiddenOptionsSet()2905 public boolean areHiddenOptionsSet() { 2906 return (installFlags & (PackageManager.INSTALL_REQUEST_DOWNGRADE 2907 | PackageManager.INSTALL_ALLOW_DOWNGRADE 2908 | PackageManager.INSTALL_DONT_KILL_APP 2909 | PackageManager.INSTALL_INSTANT_APP 2910 | PackageManager.INSTALL_FULL_APP 2911 | PackageManager.INSTALL_VIRTUAL_PRELOAD 2912 | PackageManager.INSTALL_ALLOCATE_AGGRESSIVE)) != installFlags 2913 || abiOverride != null || volumeUuid != null; 2914 } 2915 2916 /** 2917 * Provide value of {@link PackageInfo#installLocation}, which may be used 2918 * to determine where the app will be staged. Defaults to 2919 * {@link PackageInfo#INSTALL_LOCATION_INTERNAL_ONLY}. 2920 */ setInstallLocation(int installLocation)2921 public void setInstallLocation(int installLocation) { 2922 this.installLocation = installLocation; 2923 } 2924 2925 /** 2926 * Optionally indicate the total size (in bytes) of all APKs that will be 2927 * delivered in this session. The system may use this to ensure enough disk 2928 * space exists before proceeding, or to estimate container size for 2929 * installations living on external storage. 2930 * 2931 * @see PackageInfo#INSTALL_LOCATION_AUTO 2932 * @see PackageInfo#INSTALL_LOCATION_PREFER_EXTERNAL 2933 */ setSize(long sizeBytes)2934 public void setSize(long sizeBytes) { 2935 this.sizeBytes = sizeBytes; 2936 } 2937 2938 /** 2939 * Optionally set the package name of the app being installed. It's strongly 2940 * recommended that you provide this value when known, so that observers can 2941 * communicate installing apps to users. 2942 * <p> 2943 * If the APKs staged in the session aren't consistent with this package 2944 * name, the install will fail. Regardless of this value, all APKs in the 2945 * app must have the same package name. 2946 */ setAppPackageName(@ullable String appPackageName)2947 public void setAppPackageName(@Nullable String appPackageName) { 2948 this.appPackageName = appPackageName; 2949 } 2950 2951 /** 2952 * Optionally set an icon representing the app being installed. This should 2953 * be roughly {@link ActivityManager#getLauncherLargeIconSize()} in both 2954 * dimensions. 2955 */ setAppIcon(@ullable Bitmap appIcon)2956 public void setAppIcon(@Nullable Bitmap appIcon) { 2957 this.appIcon = appIcon; 2958 } 2959 2960 /** 2961 * Optionally set a label representing the app being installed. 2962 * 2963 * This value will be trimmed to the first 1000 characters. 2964 */ setAppLabel(@ullable CharSequence appLabel)2965 public void setAppLabel(@Nullable CharSequence appLabel) { 2966 this.appLabel = (appLabel != null) ? appLabel.toString() : null; 2967 } 2968 2969 /** 2970 * Optionally set the URI where this package was downloaded from. This is 2971 * informational and may be used as a signal for anti-malware purposes. 2972 * 2973 * @see Intent#EXTRA_ORIGINATING_URI 2974 */ setOriginatingUri(@ullable Uri originatingUri)2975 public void setOriginatingUri(@Nullable Uri originatingUri) { 2976 this.originatingUri = originatingUri; 2977 } 2978 2979 /** 2980 * Sets the UID that initiated the package installation. This is informational 2981 * and may be used as a signal for anti-malware purposes. 2982 */ setOriginatingUid(int originatingUid)2983 public void setOriginatingUid(int originatingUid) { 2984 this.originatingUid = originatingUid; 2985 } 2986 2987 /** 2988 * Optionally set the URI that referred you to install this package. This is 2989 * informational and may be used as a signal for anti-malware purposes. 2990 * 2991 * @see Intent#EXTRA_REFERRER 2992 */ setReferrerUri(@ullable Uri referrerUri)2993 public void setReferrerUri(@Nullable Uri referrerUri) { 2994 this.referrerUri = referrerUri; 2995 } 2996 2997 /** 2998 * Sets which runtime permissions to be granted to the package at installation. 2999 * 3000 * @param permissions The permissions to grant or null to grant all runtime 3001 * permissions. 3002 * 3003 * @deprecated Prefer {@link #setPermissionState(String, int)} instead starting in 3004 * {@link Build.VERSION_CODES#UPSIDE_DOWN_CAKE}. 3005 * @hide 3006 */ 3007 @Deprecated 3008 @SystemApi 3009 @RequiresPermission(android.Manifest.permission.INSTALL_GRANT_RUNTIME_PERMISSIONS) setGrantedRuntimePermissions(String[] permissions)3010 public void setGrantedRuntimePermissions(String[] permissions) { 3011 if (permissions == null) { 3012 // The new API has no mechanism to grant all requested permissions 3013 installFlags |= PackageManager.INSTALL_GRANT_ALL_REQUESTED_PERMISSIONS; 3014 mPermissionStates.clear(); 3015 } else { 3016 installFlags &= ~PackageManager.INSTALL_GRANT_ALL_REQUESTED_PERMISSIONS; 3017 // Otherwise call the new API to grant the permissions specified 3018 for (String permission : permissions) { 3019 setPermissionState(permission, PERMISSION_STATE_GRANTED); 3020 } 3021 } 3022 } 3023 3024 /** 3025 * Sets the state of permissions for the package at installation. 3026 * <p/> 3027 * Granting any runtime permissions require the 3028 * {@code android.Manifest.permission#INSTALL_GRANT_RUNTIME_PERMISSIONS} 3029 * permission to be held by the caller. Revoking runtime 3030 * permissions is not allowed, even during app update sessions. 3031 * <p/> 3032 * Holders without the permission are allowed to change the following special permissions: 3033 * <p/> 3034 * On platform {@link Build.VERSION_CODES#UPSIDE_DOWN_CAKE UPSIDE_DOWN_CAKE}: 3035 * <ul> 3036 * <li>{@link Manifest.permission#USE_FULL_SCREEN_INTENT}</li> 3037 * </ul> 3038 * Install time permissions, which cannot be revoked by the user, cannot be changed by the 3039 * installer. 3040 * <p/> 3041 * See <a href="https://developer.android.com/guide/topics/permissions/overview"> 3042 * Permissions on Android</a> for more information. 3043 * 3044 * @param permissionName The permission to change state for. 3045 * @param state Either {@link #PERMISSION_STATE_DEFAULT}, 3046 * {@link #PERMISSION_STATE_GRANTED}, 3047 * or {@link #PERMISSION_STATE_DENIED} to set the permission to. 3048 * 3049 * @return This object for easier chaining. 3050 */ 3051 @RequiresPermission(value = android.Manifest.permission.INSTALL_GRANT_RUNTIME_PERMISSIONS, 3052 conditional = true) 3053 @NonNull setPermissionState(@onNull String permissionName, @PermissionState int state)3054 public SessionParams setPermissionState(@NonNull String permissionName, 3055 @PermissionState int state) { 3056 if (TextUtils.isEmpty(permissionName)) { 3057 throw new IllegalArgumentException("Provided permissionName cannot be " 3058 + (permissionName == null ? "null" : "empty")); 3059 } 3060 3061 switch (state) { 3062 case PERMISSION_STATE_DEFAULT: 3063 mPermissionStates.remove(permissionName); 3064 break; 3065 case PERMISSION_STATE_GRANTED: 3066 case PERMISSION_STATE_DENIED: 3067 mPermissionStates.put(permissionName, state); 3068 break; 3069 default: 3070 throw new IllegalArgumentException("Unexpected permission state int: " + state); 3071 } 3072 3073 return this; 3074 } 3075 3076 /** @hide */ setPermissionStates(Collection<String> grantPermissions, Collection<String> denyPermissions)3077 public void setPermissionStates(Collection<String> grantPermissions, 3078 Collection<String> denyPermissions) { 3079 for (String grantPermission : grantPermissions) { 3080 mPermissionStates.put(grantPermission, PERMISSION_STATE_GRANTED); 3081 } 3082 for (String denyPermission : denyPermissions) { 3083 mPermissionStates.put(denyPermission, PERMISSION_STATE_DENIED); 3084 } 3085 } 3086 3087 /** 3088 * Optionally indicate the package source of the app being installed. This is 3089 * informational and may be used as a signal by the system. 3090 * 3091 * An installer should specify {@link #PACKAGE_SOURCE_OTHER} if no other package source 3092 * constant adequately reflects the source for this session. 3093 * 3094 * The default value is {@link #PACKAGE_SOURCE_UNSPECIFIED}. 3095 */ setPackageSource(@ackageSourceType int packageSource)3096 public void setPackageSource(@PackageSourceType int packageSource) { 3097 this.packageSource = packageSource; 3098 } 3099 3100 /** 3101 * Sets which restricted permissions to be allowlisted for the app. Allowlisting 3102 * is not granting the permissions, rather it allows the app to hold permissions 3103 * which are otherwise restricted. Allowlisting a non restricted permission has 3104 * no effect. 3105 * 3106 * <p> Permissions can be hard restricted which means that the app cannot hold 3107 * them or soft restricted where the app can hold the permission but in a weaker 3108 * form. Whether a permission is {@link PermissionInfo#FLAG_HARD_RESTRICTED hard 3109 * restricted} or {@link PermissionInfo#FLAG_SOFT_RESTRICTED soft restricted} 3110 * depends on the permission declaration. Allowlisting a hard restricted permission 3111 * allows the app to hold that permission and allowlisting a soft restricted 3112 * permission allows the app to hold the permission in its full, unrestricted form. 3113 * 3114 * <p> Permissions can also be immutably restricted which means that the allowlist 3115 * state of the permission can be determined only at install time and cannot be 3116 * changed on updated or at a later point via the package manager APIs. 3117 * 3118 * <p>Initially, all restricted permissions are allowlisted but you can change 3119 * which ones are allowlisted by calling this method or the corresponding ones 3120 * on the {@link PackageManager}. Only soft or hard restricted permissions on the current 3121 * Android version are supported and any invalid entries will be removed. 3122 * 3123 * @see PackageManager#addWhitelistedRestrictedPermission(String, String, int) 3124 * @see PackageManager#removeWhitelistedRestrictedPermission(String, String, int) 3125 */ setWhitelistedRestrictedPermissions(@ullable Set<String> permissions)3126 public void setWhitelistedRestrictedPermissions(@Nullable Set<String> permissions) { 3127 if (permissions == RESTRICTED_PERMISSIONS_ALL) { 3128 installFlags |= PackageManager.INSTALL_ALL_WHITELIST_RESTRICTED_PERMISSIONS; 3129 whitelistedRestrictedPermissions = null; 3130 } else { 3131 installFlags &= ~PackageManager.INSTALL_ALL_WHITELIST_RESTRICTED_PERMISSIONS; 3132 whitelistedRestrictedPermissions = (permissions != null) 3133 ? new ArrayList<>(permissions) : null; 3134 } 3135 } 3136 3137 /** 3138 * Sets whether permissions should be auto-revoked if this package is unused for an 3139 * extended periodd of time. 3140 * 3141 * It's disabled by default but generally the installer should enable it for most packages, 3142 * excluding only those where doing so might cause breakage that cannot be easily addressed 3143 * by simply re-requesting the permission(s). 3144 * 3145 * If user explicitly enabled or disabled it via settings, this call is ignored. 3146 * 3147 * @param shouldAutoRevoke whether permissions should be auto-revoked. 3148 * 3149 * @deprecated No longer used 3150 */ 3151 @Deprecated setAutoRevokePermissionsMode(boolean shouldAutoRevoke)3152 public void setAutoRevokePermissionsMode(boolean shouldAutoRevoke) { 3153 autoRevokePermissionsMode = shouldAutoRevoke ? MODE_ALLOWED : MODE_IGNORED; 3154 } 3155 3156 /** 3157 * Request that rollbacks be enabled or disabled for the given upgrade with rollback data 3158 * policy set to RESTORE. 3159 * 3160 * <p>If the parent session is staged or has rollback enabled, all children sessions 3161 * must have the same properties. 3162 * 3163 * @param enable set to {@code true} to enable, {@code false} to disable 3164 * @see SessionParams#setEnableRollback(boolean, int) 3165 * @hide 3166 */ 3167 @SystemApi setEnableRollback(boolean enable)3168 public void setEnableRollback(boolean enable) { 3169 setEnableRollback(enable, PackageManager.ROLLBACK_DATA_POLICY_RESTORE); 3170 } 3171 3172 /** 3173 * Request that rollbacks be enabled or disabled for the given upgrade. 3174 * 3175 * <p>If the parent session is staged or has rollback enabled, all children sessions 3176 * must have the same properties. 3177 * 3178 * <p> For a multi-package install, this method must be called on each child session to 3179 * specify rollback data policies explicitly. Note each child session is allowed to have 3180 * different policies. 3181 * 3182 * @param enable set to {@code true} to enable, {@code false} to disable 3183 * @param dataPolicy the rollback data policy for this session 3184 * @hide 3185 */ 3186 @SystemApi setEnableRollback(boolean enable, @PackageManager.RollbackDataPolicy int dataPolicy)3187 public void setEnableRollback(boolean enable, 3188 @PackageManager.RollbackDataPolicy int dataPolicy) { 3189 if (enable) { 3190 installFlags |= PackageManager.INSTALL_ENABLE_ROLLBACK; 3191 } else { 3192 installFlags &= ~PackageManager.INSTALL_ENABLE_ROLLBACK; 3193 rollbackLifetimeMillis = 0; 3194 } 3195 rollbackDataPolicy = dataPolicy; 3196 } 3197 3198 /** 3199 * If rollback enabled for this session (via {@link #setEnableRollback}, set period 3200 * after which rollback files will be deleted due to expiration 3201 * {@link RollbackManagerServiceImpl#deleteRollback}. 3202 * 3203 * <p>For multi-package installs, this value must be set on the parent session. 3204 * Child session rollback lifetime will be ignored. 3205 * 3206 * @param lifetimeMillis period after which rollback expires 3207 * @throws IllegalArgumentException if lifetimeMillis is negative or rollback is not 3208 * enabled via setEnableRollback. 3209 * @hide 3210 */ 3211 @SystemApi 3212 @RequiresPermission(android.Manifest.permission.MANAGE_ROLLBACKS) 3213 @FlaggedApi(Flags.FLAG_ROLLBACK_LIFETIME) setRollbackLifetimeMillis(@urationMillisLong long lifetimeMillis)3214 public void setRollbackLifetimeMillis(@DurationMillisLong long lifetimeMillis) { 3215 if (lifetimeMillis < 0) { 3216 throw new IllegalArgumentException("rollbackLifetimeMillis can't be negative."); 3217 } 3218 if ((installFlags & PackageManager.INSTALL_ENABLE_ROLLBACK) == 0) { 3219 throw new IllegalArgumentException( 3220 "Can't set rollbackLifetimeMillis when rollback is not enabled"); 3221 } 3222 rollbackLifetimeMillis = lifetimeMillis; 3223 } 3224 3225 /** 3226 * rollbackImpactLevel is a measure of impact a rollback has on the user. This can take one 3227 * of 3 values: 3228 * <ul> 3229 * <li>{@link PackageManager#ROLLBACK_USER_IMPACT_LOW} (default)</li> 3230 * <li>{@link PackageManager#ROLLBACK_USER_IMPACT_HIGH} (1)</li> 3231 * <li>{@link PackageManager#ROLLBACK_USER_IMPACT_ONLY_MANUAL} (2)</li> 3232 * </ul> 3233 * 3234 * @hide 3235 */ 3236 @SystemApi 3237 @RequiresPermission(android.Manifest.permission.MANAGE_ROLLBACKS) 3238 @FlaggedApi(Flags.FLAG_RECOVERABILITY_DETECTION) setRollbackImpactLevel(@ackageManager.RollbackImpactLevel int impactLevel)3239 public void setRollbackImpactLevel(@PackageManager.RollbackImpactLevel int impactLevel) { 3240 if ((installFlags & PackageManager.INSTALL_ENABLE_ROLLBACK) == 0) { 3241 throw new IllegalArgumentException( 3242 "Can't set rollbackImpactLevel when rollback is not enabled"); 3243 } 3244 rollbackImpactLevel = impactLevel; 3245 } 3246 3247 /** 3248 * @deprecated use {@link #setRequestDowngrade(boolean)}. 3249 * {@hide} 3250 */ 3251 @SystemApi 3252 @Deprecated setAllowDowngrade(boolean allowDowngrade)3253 public void setAllowDowngrade(boolean allowDowngrade) { 3254 setRequestDowngrade(allowDowngrade); 3255 } 3256 3257 /** {@hide} */ 3258 @SystemApi setRequestDowngrade(boolean requestDowngrade)3259 public void setRequestDowngrade(boolean requestDowngrade) { 3260 if (requestDowngrade) { 3261 installFlags |= PackageManager.INSTALL_REQUEST_DOWNGRADE; 3262 } else { 3263 installFlags &= ~PackageManager.INSTALL_REQUEST_DOWNGRADE; 3264 } 3265 } 3266 3267 /** 3268 * Require the given version of the package be installed. 3269 * The install will only be allowed if the existing version code of 3270 * the package installed on the device matches the given version code. 3271 * Use {@link * PackageManager#VERSION_CODE_HIGHEST} to allow 3272 * installation regardless of the currently installed package version. 3273 * 3274 * @hide 3275 */ setRequiredInstalledVersionCode(long versionCode)3276 public void setRequiredInstalledVersionCode(long versionCode) { 3277 requiredInstalledVersionCode = versionCode; 3278 } 3279 3280 /** {@hide} */ setInstallFlagsForcePermissionPrompt()3281 public void setInstallFlagsForcePermissionPrompt() { 3282 installFlags |= PackageManager.INSTALL_FORCE_PERMISSION_PROMPT; 3283 } 3284 3285 /** 3286 * Requests that the system not kill any of the package's running 3287 * processes as part of a {@link SessionParams#MODE_INHERIT_EXISTING} 3288 * session in which splits being added. By default, all installs will 3289 * result in the package's running processes being killed before the 3290 * install completes. 3291 * 3292 * @param dontKillApp set to {@code true} to request that the processes 3293 * belonging to the package not be killed as part of 3294 * this install. 3295 */ setDontKillApp(boolean dontKillApp)3296 public void setDontKillApp(boolean dontKillApp) { 3297 if (dontKillApp) { 3298 installFlags |= PackageManager.INSTALL_DONT_KILL_APP; 3299 } else { 3300 installFlags &= ~PackageManager.INSTALL_DONT_KILL_APP; 3301 } 3302 } 3303 3304 /** {@hide} */ 3305 @SystemApi setInstallAsInstantApp(boolean isInstantApp)3306 public void setInstallAsInstantApp(boolean isInstantApp) { 3307 if (isInstantApp) { 3308 installFlags |= PackageManager.INSTALL_INSTANT_APP; 3309 installFlags &= ~PackageManager.INSTALL_FULL_APP; 3310 } else { 3311 installFlags &= ~PackageManager.INSTALL_INSTANT_APP; 3312 installFlags |= PackageManager.INSTALL_FULL_APP; 3313 } 3314 } 3315 3316 /** 3317 * Sets the install as a virtual preload. Will only have effect when called 3318 * by the verifier. 3319 * {@hide} 3320 */ 3321 @SystemApi setInstallAsVirtualPreload()3322 public void setInstallAsVirtualPreload() { 3323 installFlags |= PackageManager.INSTALL_VIRTUAL_PRELOAD; 3324 } 3325 3326 /** 3327 * Set the reason for installing this package. 3328 * <p> 3329 * The install reason should be a pre-defined integer. The behavior is 3330 * undefined if other values are used. 3331 * 3332 * @see PackageManager#INSTALL_REASON_UNKNOWN 3333 * @see PackageManager#INSTALL_REASON_POLICY 3334 * @see PackageManager#INSTALL_REASON_DEVICE_RESTORE 3335 * @see PackageManager#INSTALL_REASON_DEVICE_SETUP 3336 * @see PackageManager#INSTALL_REASON_USER 3337 */ setInstallReason(@nstallReason int installReason)3338 public void setInstallReason(@InstallReason int installReason) { 3339 this.installReason = installReason; 3340 } 3341 3342 /** {@hide} */ 3343 @SystemApi 3344 @RequiresPermission(android.Manifest.permission.ALLOCATE_AGGRESSIVE) setAllocateAggressive(boolean allocateAggressive)3345 public void setAllocateAggressive(boolean allocateAggressive) { 3346 if (allocateAggressive) { 3347 installFlags |= PackageManager.INSTALL_ALLOCATE_AGGRESSIVE; 3348 } else { 3349 installFlags &= ~PackageManager.INSTALL_ALLOCATE_AGGRESSIVE; 3350 } 3351 } 3352 3353 /** 3354 * @hide 3355 */ 3356 @TestApi setInstallFlagAllowTest()3357 public void setInstallFlagAllowTest() { 3358 installFlags |= PackageManager.INSTALL_ALLOW_TEST; 3359 } 3360 3361 /** 3362 * Set the installer package for the app. 3363 * 3364 * By default this is the app that created the {@link PackageInstaller} object. 3365 * 3366 * Note: Only applications with {@link android.Manifest.permission#INSTALL_PACKAGES} 3367 * permission are allowed to set an installer that is not the caller's own installer 3368 * package name, otherwise it will cause a {@link SecurityException} when creating the 3369 * install session. 3370 * 3371 * @param installerPackageName The name of the installer package, its length must be less 3372 * than {@code 255}, otherwise it will be invalid. 3373 */ setInstallerPackageName(@ullable String installerPackageName)3374 public void setInstallerPackageName(@Nullable String installerPackageName) { 3375 this.installerPackageName = installerPackageName; 3376 } 3377 3378 /** 3379 * Set this session to be the parent of a multi-package install. 3380 * 3381 * A multi-package install session contains no APKs and only references other install 3382 * sessions via ID. When a multi-package session is committed, all of its children 3383 * are committed to the system in an atomic manner. If any children fail to install, 3384 * all of them do, including the multi-package session. 3385 */ setMultiPackage()3386 public void setMultiPackage() { 3387 this.isMultiPackage = true; 3388 } 3389 3390 /** 3391 * Set this session to be staged to be installed at reboot. 3392 * 3393 * Staged sessions are scheduled to be installed at next reboot. Staged sessions can also be 3394 * multi-package. In that case, if any of the children sessions fail to install at reboot, 3395 * all the other children sessions are aborted as well. 3396 * 3397 * <p>If the parent session is staged or has rollback enabled, all children sessions 3398 * must have the same properties. 3399 * 3400 * {@hide} 3401 */ 3402 @SystemApi 3403 @RequiresPermission(Manifest.permission.INSTALL_PACKAGES) setStaged()3404 public void setStaged() { 3405 this.isStaged = true; 3406 } 3407 3408 /** 3409 * Set this session to be installing an APEX package. 3410 * 3411 * {@hide} 3412 */ 3413 @SystemApi 3414 @RequiresPermission(Manifest.permission.INSTALL_PACKAGES) setInstallAsApex()3415 public void setInstallAsApex() { 3416 installFlags |= PackageManager.INSTALL_APEX; 3417 } 3418 3419 /** @hide */ getEnableRollback()3420 public boolean getEnableRollback() { 3421 return (installFlags & PackageManager.INSTALL_ENABLE_ROLLBACK) != 0; 3422 } 3423 3424 /** 3425 * Set the data loader params for the session. 3426 * This also switches installation into data loading mode and disallow direct writes into 3427 * staging folder. 3428 * 3429 * @see android.service.dataloader.DataLoaderService.DataLoader 3430 * 3431 * {@hide} 3432 */ 3433 @SystemApi 3434 @RequiresPermission(allOf = { 3435 Manifest.permission.INSTALL_PACKAGES, 3436 Manifest.permission.USE_INSTALLER_V2}) setDataLoaderParams(@onNull DataLoaderParams dataLoaderParams)3437 public void setDataLoaderParams(@NonNull DataLoaderParams dataLoaderParams) { 3438 this.dataLoaderParams = dataLoaderParams; 3439 } 3440 3441 /** 3442 * 3443 * {@hide} 3444 */ setForceQueryable()3445 public void setForceQueryable() { 3446 this.forceQueryableOverride = true; 3447 } 3448 3449 /** 3450 * Optionally indicate whether user action should be required when the session is 3451 * committed. 3452 * <p> 3453 * Defaults to {@link #USER_ACTION_UNSPECIFIED} unless otherwise set. When unspecified for 3454 * installers using the 3455 * {@link android.Manifest.permission#REQUEST_INSTALL_PACKAGES REQUEST_INSTALL_PACKAGES} 3456 * permission will behave as if set to {@link #USER_ACTION_REQUIRED}, and 3457 * {@link #USER_ACTION_NOT_REQUIRED} otherwise. When {@code requireUserAction} is set to 3458 * {@link #USER_ACTION_REQUIRED}, installers will receive a 3459 * {@link #STATUS_PENDING_USER_ACTION} callback once the session is committed, indicating 3460 * that user action is required for the install to proceed. 3461 * <p> 3462 * For installers that have been granted the 3463 * {@link android.Manifest.permission#REQUEST_INSTALL_PACKAGES REQUEST_INSTALL_PACKAGES} 3464 * permission, user action will not be required when all of the following conditions are 3465 * met: 3466 * 3467 * <ul> 3468 * <li>{@code requireUserAction} is set to {@link #USER_ACTION_NOT_REQUIRED}.</li> 3469 * <li>The app being installed targets: 3470 * <ul> 3471 * <li>{@link android.os.Build.VERSION_CODES#Q API 29} or higher on 3472 * Android S ({@link android.os.Build.VERSION_CODES#S API 31})</li> 3473 * <li>{@link android.os.Build.VERSION_CODES#R API 30} or higher on 3474 * Android T ({@link android.os.Build.VERSION_CODES#TIRAMISU API 33})</li> 3475 * <li>{@link android.os.Build.VERSION_CODES#S API 31} or higher on 3476 * Android U ({@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE API 34}) 3477 * </li> 3478 * <li>{@link android.os.Build.VERSION_CODES#TIRAMISU API 33} or higher on 3479 * Android V ({@link android.os.Build.VERSION_CODES#VANILLA_ICE_CREAM API 35}) 3480 * </li> 3481 * </ul> 3482 * </li> 3483 * <li>The installer is: 3484 * <ul> 3485 * <li>The {@link InstallSourceInfo#getUpdateOwnerPackageName() update owner} 3486 * of an existing version of the app (in other words, this install session is 3487 * an app update) if the update ownership enforcement is enabled.</li> 3488 * <li>The 3489 * {@link InstallSourceInfo#getInstallingPackageName() installer of record} 3490 * of an existing version of the app (in other words, this install 3491 * session is an app update) if the update ownership enforcement isn't 3492 * enabled.</li> 3493 * <li>Updating itself.</li> 3494 * </ul> 3495 * </li> 3496 * <li>The installer declares the 3497 * {@link android.Manifest.permission#UPDATE_PACKAGES_WITHOUT_USER_ACTION 3498 * UPDATE_PACKAGES_WITHOUT_USER_ACTION} permission.</li> 3499 * </ul> 3500 * <p> 3501 * Note: The target API level requirement will advance in future Android versions. 3502 * Session owners should always be prepared to handle {@link #STATUS_PENDING_USER_ACTION}. 3503 * 3504 * @param requireUserAction whether user action should be required. 3505 */ setRequireUserAction( @essionParams.UserActionRequirement int requireUserAction)3506 public void setRequireUserAction( 3507 @SessionParams.UserActionRequirement int requireUserAction) { 3508 if (requireUserAction != USER_ACTION_UNSPECIFIED 3509 && requireUserAction != USER_ACTION_REQUIRED 3510 && requireUserAction != USER_ACTION_NOT_REQUIRED) { 3511 throw new IllegalArgumentException("requireUserAction set as invalid value of " 3512 + requireUserAction + ", but must be one of [" 3513 + "USER_ACTION_UNSPECIFIED, USER_ACTION_REQUIRED, USER_ACTION_NOT_REQUIRED" 3514 + "]"); 3515 } 3516 this.requireUserAction = requireUserAction; 3517 } 3518 3519 /** 3520 * Sets the install scenario for this session, which describes the expected user journey. 3521 */ setInstallScenario(@nstallScenario int installScenario)3522 public void setInstallScenario(@InstallScenario int installScenario) { 3523 this.installScenario = installScenario; 3524 } 3525 3526 /** 3527 * Request to keep the original application enabled setting. This will prevent the 3528 * application from being enabled if it was previously in a disabled state. 3529 */ setApplicationEnabledSettingPersistent()3530 public void setApplicationEnabledSettingPersistent() { 3531 this.applicationEnabledSettingPersistent = true; 3532 } 3533 3534 /** 3535 * Optionally indicate whether the package being installed needs the update ownership 3536 * enforcement. Once the update ownership enforcement is enabled, the other installers 3537 * will need the user action to update the package even if the installers have been 3538 * granted the {@link android.Manifest.permission#INSTALL_PACKAGES INSTALL_PACKAGES} 3539 * permission. Default to {@code false}. 3540 * 3541 * The update ownership enforcement can only be enabled on initial installation. Set 3542 * this to {@code true} on package update is a no-op. 3543 * 3544 * Note: To enable the update ownership enforcement, the installer must have the 3545 * {@link android.Manifest.permission#ENFORCE_UPDATE_OWNERSHIP ENFORCE_UPDATE_OWNERSHIP} 3546 * permission. 3547 */ 3548 @RequiresPermission(Manifest.permission.ENFORCE_UPDATE_OWNERSHIP) setRequestUpdateOwnership(boolean enable)3549 public void setRequestUpdateOwnership(boolean enable) { 3550 if (enable) { 3551 this.installFlags |= PackageManager.INSTALL_REQUEST_UPDATE_OWNERSHIP; 3552 } else { 3553 this.installFlags &= ~PackageManager.INSTALL_REQUEST_UPDATE_OWNERSHIP; 3554 } 3555 } 3556 3557 /** 3558 * Used to set the unarchive ID received as part of an 3559 * {@link Intent#ACTION_UNARCHIVE_PACKAGE}. 3560 * 3561 * <p> The ID should be retrieved from the unarchive intent and passed into the 3562 * session that's being created to unarchive the app in question. Used to link the unarchive 3563 * intent and the install session to disambiguate. 3564 */ 3565 @FlaggedApi(Flags.FLAG_ARCHIVING) setUnarchiveId(int unarchiveId)3566 public void setUnarchiveId(int unarchiveId) { 3567 this.unarchiveId = unarchiveId; 3568 } 3569 3570 /** @hide */ setDexoptCompilerFilter(@ullable String dexoptCompilerFilter)3571 public void setDexoptCompilerFilter(@Nullable String dexoptCompilerFilter) { 3572 this.dexoptCompilerFilter = dexoptCompilerFilter; 3573 } 3574 3575 /** @hide */ 3576 @NonNull getPermissionStates()3577 public ArrayMap<String, Integer> getPermissionStates() { 3578 return mPermissionStates; 3579 } 3580 3581 /** @hide */ 3582 @Nullable getLegacyGrantedRuntimePermissions()3583 public String[] getLegacyGrantedRuntimePermissions() { 3584 if ((installFlags & PackageManager.INSTALL_GRANT_ALL_REQUESTED_PERMISSIONS) != 0) { 3585 return null; 3586 } 3587 3588 var grantedPermissions = new ArrayList<String>(); 3589 for (int index = 0; index < mPermissionStates.size(); index++) { 3590 var permissionName = mPermissionStates.keyAt(index); 3591 var state = mPermissionStates.valueAt(index); 3592 if (state == PERMISSION_STATE_GRANTED) { 3593 grantedPermissions.add(permissionName); 3594 } 3595 } 3596 3597 return grantedPermissions.toArray(ArrayUtils.emptyArray(String.class)); 3598 } 3599 3600 /** {@hide} */ dump(IndentingPrintWriter pw)3601 public void dump(IndentingPrintWriter pw) { 3602 pw.printPair("mode", mode); 3603 pw.printHexPair("installFlags", installFlags); 3604 pw.printPair("installLocation", installLocation); 3605 pw.printPair("installReason", installReason); 3606 pw.printPair("installScenario", installScenario); 3607 pw.printPair("sizeBytes", sizeBytes); 3608 pw.printPair("appPackageName", appPackageName); 3609 pw.printPair("appIcon", (appIcon != null)); 3610 pw.printPair("appLabel", appLabel); 3611 pw.printPair("originatingUri", originatingUri); 3612 pw.printPair("originatingUid", originatingUid); 3613 pw.printPair("referrerUri", referrerUri); 3614 pw.printPair("abiOverride", abiOverride); 3615 pw.printPair("volumeUuid", volumeUuid); 3616 pw.printPair("mPermissionStates", mPermissionStates); 3617 pw.printPair("packageSource", packageSource); 3618 pw.printPair("whitelistedRestrictedPermissions", whitelistedRestrictedPermissions); 3619 pw.printPair("autoRevokePermissions", autoRevokePermissionsMode); 3620 pw.printPair("installerPackageName", installerPackageName); 3621 pw.printPair("isMultiPackage", isMultiPackage); 3622 pw.printPair("isStaged", isStaged); 3623 pw.printPair("forceQueryable", forceQueryableOverride); 3624 pw.printPair("requireUserAction", SessionInfo.userActionToString(requireUserAction)); 3625 pw.printPair("requiredInstalledVersionCode", requiredInstalledVersionCode); 3626 pw.printPair("dataLoaderParams", dataLoaderParams); 3627 pw.printPair("rollbackDataPolicy", rollbackDataPolicy); 3628 pw.printPair("rollbackLifetimeMillis", rollbackLifetimeMillis); 3629 pw.printPair("rollbackImpactLevel", rollbackImpactLevel); 3630 pw.printPair("applicationEnabledSettingPersistent", 3631 applicationEnabledSettingPersistent); 3632 pw.printHexPair("developmentInstallFlags", developmentInstallFlags); 3633 pw.printPair("unarchiveId", unarchiveId); 3634 pw.printPair("dexoptCompilerFilter", dexoptCompilerFilter); 3635 pw.println(); 3636 } 3637 3638 @Override describeContents()3639 public int describeContents() { 3640 return 0; 3641 } 3642 3643 @Override writeToParcel(Parcel dest, int flags)3644 public void writeToParcel(Parcel dest, int flags) { 3645 dest.writeInt(mode); 3646 dest.writeInt(installFlags); 3647 dest.writeInt(installLocation); 3648 dest.writeInt(installReason); 3649 dest.writeInt(installScenario); 3650 dest.writeLong(sizeBytes); 3651 dest.writeString(appPackageName); 3652 dest.writeParcelable(appIcon, flags); 3653 dest.writeString(appLabel); 3654 dest.writeParcelable(originatingUri, flags); 3655 dest.writeInt(originatingUid); 3656 dest.writeParcelable(referrerUri, flags); 3657 dest.writeString(abiOverride); 3658 dest.writeString(volumeUuid); 3659 dest.writeMap(mPermissionStates); 3660 dest.writeStringList(whitelistedRestrictedPermissions); 3661 dest.writeInt(autoRevokePermissionsMode); 3662 dest.writeString(installerPackageName); 3663 dest.writeBoolean(isMultiPackage); 3664 dest.writeBoolean(isStaged); 3665 dest.writeBoolean(forceQueryableOverride); 3666 dest.writeLong(requiredInstalledVersionCode); 3667 if (dataLoaderParams != null) { 3668 dest.writeParcelable(dataLoaderParams.getData(), flags); 3669 } else { 3670 dest.writeParcelable(null, flags); 3671 } 3672 dest.writeInt(rollbackDataPolicy); 3673 dest.writeLong(rollbackLifetimeMillis); 3674 dest.writeInt(rollbackImpactLevel); 3675 dest.writeInt(requireUserAction); 3676 dest.writeInt(packageSource); 3677 dest.writeBoolean(applicationEnabledSettingPersistent); 3678 dest.writeInt(developmentInstallFlags); 3679 dest.writeInt(unarchiveId); 3680 dest.writeString(dexoptCompilerFilter); 3681 } 3682 3683 public static final Parcelable.Creator<SessionParams> 3684 CREATOR = new Parcelable.Creator<SessionParams>() { 3685 @Override 3686 public SessionParams createFromParcel(Parcel p) { 3687 return new SessionParams(p); 3688 } 3689 3690 @Override 3691 public SessionParams[] newArray(int size) { 3692 return new SessionParams[size]; 3693 } 3694 }; 3695 } 3696 3697 /** 3698 * Details for an active install session. 3699 */ 3700 public static class SessionInfo implements Parcelable { 3701 3702 /** 3703 * A session ID that does not exist or is invalid. 3704 */ 3705 public static final int INVALID_ID = -1; 3706 /** {@hide} */ 3707 private static final int[] NO_SESSIONS = {}; 3708 3709 /** 3710 * @deprecated use {@link #SESSION_NO_ERROR}. 3711 */ 3712 @Deprecated 3713 public static final int STAGED_SESSION_NO_ERROR = 0; 3714 3715 /** 3716 * @deprecated use {@link #SESSION_VERIFICATION_FAILED}. 3717 */ 3718 @Deprecated 3719 public static final int STAGED_SESSION_VERIFICATION_FAILED = 1; 3720 3721 /** 3722 * @deprecated use {@link #SESSION_ACTIVATION_FAILED}. 3723 */ 3724 @Deprecated 3725 public static final int STAGED_SESSION_ACTIVATION_FAILED = 2; 3726 3727 /** 3728 * @deprecated use {@link #SESSION_UNKNOWN_ERROR}. 3729 */ 3730 @Deprecated 3731 public static final int STAGED_SESSION_UNKNOWN = 3; 3732 3733 /** 3734 * @deprecated use {@link #SESSION_CONFLICT}. 3735 */ 3736 @Deprecated 3737 public static final int STAGED_SESSION_CONFLICT = 4; 3738 3739 /** 3740 * Constant indicating that no error occurred during the preparation or the activation of 3741 * this session. 3742 */ 3743 public static final int SESSION_NO_ERROR = 0; 3744 3745 /** 3746 * Constant indicating that an error occurred during the verification phase of 3747 * this session. 3748 */ 3749 public static final int SESSION_VERIFICATION_FAILED = 1; 3750 3751 /** 3752 * Constant indicating that an error occurred during the activation phase of 3753 * this session. 3754 */ 3755 public static final int SESSION_ACTIVATION_FAILED = 2; 3756 3757 /** 3758 * Constant indicating that an unknown error occurred while processing this session. 3759 */ 3760 public static final int SESSION_UNKNOWN_ERROR = 3; 3761 3762 /** 3763 * Constant indicating that the session was in conflict with another session and had 3764 * to be sacrificed for resolution. 3765 */ 3766 public static final int SESSION_CONFLICT = 4; 3767 userActionToString(int requireUserAction)3768 private static String userActionToString(int requireUserAction) { 3769 switch(requireUserAction) { 3770 case SessionParams.USER_ACTION_REQUIRED: 3771 return "REQUIRED"; 3772 case SessionParams.USER_ACTION_NOT_REQUIRED: 3773 return "NOT_REQUIRED"; 3774 default: 3775 return "UNSPECIFIED"; 3776 } 3777 } 3778 3779 /** {@hide} */ 3780 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) 3781 public int sessionId; 3782 /** {@hide} */ 3783 public int userId; 3784 /** {@hide} */ 3785 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) 3786 public String installerPackageName; 3787 /** {@hide} */ 3788 public String installerAttributionTag; 3789 /** {@hide} */ 3790 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 3791 public String resolvedBaseCodePath; 3792 /** {@hide} */ 3793 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) 3794 public float progress; 3795 /** {@hide} */ 3796 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 3797 public boolean sealed; 3798 /** {@hide} */ 3799 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) 3800 public boolean active; 3801 3802 /** {@hide} */ 3803 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) 3804 public int mode; 3805 /** {@hide} */ 3806 public @InstallReason int installReason; 3807 /** {@hide} */ 3808 public @InstallScenario int installScenario; 3809 /** {@hide} */ 3810 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) 3811 public long sizeBytes; 3812 /** {@hide} */ 3813 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) 3814 public String appPackageName; 3815 /** {@hide} */ 3816 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) 3817 public Bitmap appIcon; 3818 /** {@hide} */ 3819 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) 3820 public CharSequence appLabel; 3821 3822 /** {@hide} */ 3823 public int installLocation; 3824 /** {@hide} */ 3825 public Uri originatingUri; 3826 /** {@hide} */ 3827 public int originatingUid; 3828 /** {@hide} */ 3829 public Uri referrerUri; 3830 /** {@hide} */ 3831 public String[] grantedRuntimePermissions; 3832 /** {@hide}*/ 3833 public List<String> whitelistedRestrictedPermissions; 3834 /** {@hide}*/ 3835 public int autoRevokePermissionsMode = MODE_DEFAULT; 3836 /** {@hide} */ 3837 public int installFlags; 3838 /** {@hide} */ 3839 public boolean isMultiPackage; 3840 /** {@hide} */ 3841 public boolean isStaged; 3842 /** {@hide} */ 3843 public boolean forceQueryable; 3844 /** {@hide} */ 3845 public int parentSessionId = INVALID_ID; 3846 /** {@hide} */ 3847 public int[] childSessionIds = NO_SESSIONS; 3848 3849 /** {@hide} */ 3850 public boolean isSessionApplied; 3851 /** {@hide} */ 3852 public boolean isSessionReady; 3853 /** {@hide} */ 3854 public boolean isSessionFailed; 3855 private int mSessionErrorCode; 3856 private String mSessionErrorMessage; 3857 3858 /** {@hide} */ 3859 public boolean isCommitted; 3860 3861 /** {@hide} */ 3862 public long createdMillis; 3863 3864 /** {@hide} */ 3865 public long updatedMillis; 3866 3867 /** {@hide} */ 3868 public int rollbackDataPolicy; 3869 3870 /** @hide */ 3871 public long rollbackLifetimeMillis; 3872 3873 /** {@hide} */ 3874 public int rollbackImpactLevel; 3875 3876 /** {@hide} */ 3877 public int requireUserAction; 3878 3879 /** {@hide} */ 3880 public int packageSource = PACKAGE_SOURCE_UNSPECIFIED; 3881 3882 /** {@hide} */ 3883 public int installerUid; 3884 3885 /** @hide */ 3886 public boolean isPreapprovalRequested; 3887 3888 /** @hide */ 3889 public boolean applicationEnabledSettingPersistent; 3890 3891 /** @hide */ 3892 public int pendingUserActionReason; 3893 3894 /** {@hide} */ 3895 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) SessionInfo()3896 public SessionInfo() { 3897 } 3898 3899 /** {@hide} */ SessionInfo(Parcel source)3900 public SessionInfo(Parcel source) { 3901 sessionId = source.readInt(); 3902 userId = source.readInt(); 3903 installerPackageName = source.readString(); 3904 installerAttributionTag = source.readString(); 3905 resolvedBaseCodePath = source.readString(); 3906 progress = source.readFloat(); 3907 sealed = source.readInt() != 0; 3908 active = source.readInt() != 0; 3909 3910 mode = source.readInt(); 3911 installReason = source.readInt(); 3912 installScenario = source.readInt(); 3913 sizeBytes = source.readLong(); 3914 appPackageName = source.readString(); 3915 appIcon = source.readParcelable(null, android.graphics.Bitmap.class); 3916 appLabel = source.readString(); 3917 3918 installLocation = source.readInt(); 3919 originatingUri = source.readParcelable(null, android.net.Uri.class); 3920 originatingUid = source.readInt(); 3921 referrerUri = source.readParcelable(null, android.net.Uri.class); 3922 grantedRuntimePermissions = source.readStringArray(); 3923 whitelistedRestrictedPermissions = source.createStringArrayList(); 3924 autoRevokePermissionsMode = source.readInt(); 3925 3926 installFlags = source.readInt(); 3927 isMultiPackage = source.readBoolean(); 3928 isStaged = source.readBoolean(); 3929 forceQueryable = source.readBoolean(); 3930 parentSessionId = source.readInt(); 3931 childSessionIds = source.createIntArray(); 3932 if (childSessionIds == null) { 3933 childSessionIds = NO_SESSIONS; 3934 } 3935 isSessionApplied = source.readBoolean(); 3936 isSessionReady = source.readBoolean(); 3937 isSessionFailed = source.readBoolean(); 3938 mSessionErrorCode = source.readInt(); 3939 mSessionErrorMessage = source.readString(); 3940 isCommitted = source.readBoolean(); 3941 isPreapprovalRequested = source.readBoolean(); 3942 rollbackDataPolicy = source.readInt(); 3943 rollbackLifetimeMillis = source.readLong(); 3944 rollbackImpactLevel = source.readInt(); 3945 createdMillis = source.readLong(); 3946 requireUserAction = source.readInt(); 3947 installerUid = source.readInt(); 3948 packageSource = source.readInt(); 3949 applicationEnabledSettingPersistent = source.readBoolean(); 3950 pendingUserActionReason = source.readInt(); 3951 } 3952 3953 /** 3954 * Return the ID for this session. 3955 */ getSessionId()3956 public int getSessionId() { 3957 return sessionId; 3958 } 3959 3960 /** 3961 * Return the user associated with this session. 3962 */ getUser()3963 public @NonNull UserHandle getUser() { 3964 return new UserHandle(userId); 3965 } 3966 3967 /** 3968 * Return the package name of the app that owns this session. 3969 */ getInstallerPackageName()3970 public @Nullable String getInstallerPackageName() { 3971 return installerPackageName; 3972 } 3973 3974 /** 3975 * @return {@link android.content.Context#getAttributionTag attribution tag} of the context 3976 * that created this session 3977 */ getInstallerAttributionTag()3978 public @Nullable String getInstallerAttributionTag() { 3979 return installerAttributionTag; 3980 } 3981 3982 /** 3983 * Return current overall progress of this session, between 0 and 1. 3984 * <p> 3985 * Note that this progress may not directly correspond to the value 3986 * reported by 3987 * {@link PackageInstaller.Session#setStagingProgress(float)}, as the 3988 * system may carve out a portion of the overall progress to represent 3989 * its own internal installation work. 3990 */ getProgress()3991 public float getProgress() { 3992 return progress; 3993 } 3994 3995 /** 3996 * Return if this session is currently active. 3997 * <p> 3998 * A session is considered active whenever there is ongoing forward 3999 * progress being made, such as the installer holding an open 4000 * {@link Session} instance while streaming data into place, or the 4001 * system optimizing code as the result of 4002 * {@link Session#commit(IntentSender)}. 4003 * <p> 4004 * If the installer closes the {@link Session} without committing, the 4005 * session is considered inactive until the installer opens the session 4006 * again. 4007 */ isActive()4008 public boolean isActive() { 4009 return active; 4010 } 4011 4012 /** 4013 * Return if this session is sealed. 4014 * <p> 4015 * Once sealed, no further changes may be made to the session. A session 4016 * is sealed the moment {@link Session#commit(IntentSender)} is called. 4017 */ isSealed()4018 public boolean isSealed() { 4019 return sealed; 4020 } 4021 4022 /** 4023 * Return the reason for installing this package. 4024 * 4025 * @return The install reason. 4026 */ getInstallReason()4027 public @InstallReason int getInstallReason() { 4028 return installReason; 4029 } 4030 4031 /** {@hide} */ 4032 @Deprecated isOpen()4033 public boolean isOpen() { 4034 return isActive(); 4035 } 4036 4037 /** 4038 * Return the package name this session is working with. May be {@code null} 4039 * if unknown. 4040 */ getAppPackageName()4041 public @Nullable String getAppPackageName() { 4042 return appPackageName; 4043 } 4044 4045 /** 4046 * Return an icon representing the app being installed. May be {@code null} 4047 * if unavailable. 4048 */ getAppIcon()4049 public @Nullable Bitmap getAppIcon() { 4050 if (appIcon == null) { 4051 // Icon may have been omitted for calls that return bulk session 4052 // lists, so try fetching the specific icon. 4053 try { 4054 final SessionInfo info = AppGlobals.getPackageManager().getPackageInstaller() 4055 .getSessionInfo(sessionId); 4056 appIcon = (info != null) ? info.appIcon : null; 4057 } catch (RemoteException e) { 4058 throw e.rethrowFromSystemServer(); 4059 } 4060 } 4061 return appIcon; 4062 } 4063 4064 /** 4065 * Return a label representing the app being installed. May be {@code null} 4066 * if unavailable. 4067 */ getAppLabel()4068 public @Nullable CharSequence getAppLabel() { 4069 return appLabel; 4070 } 4071 4072 /** 4073 * Return an Intent that can be started to view details about this install 4074 * session. This may surface actions such as pause, resume, or cancel. 4075 * <p> 4076 * In some cases, a matching Activity may not exist, so ensure you safeguard 4077 * against this. 4078 * 4079 * @see PackageInstaller#ACTION_SESSION_DETAILS 4080 */ createDetailsIntent()4081 public @Nullable Intent createDetailsIntent() { 4082 final Intent intent = new Intent(PackageInstaller.ACTION_SESSION_DETAILS); 4083 intent.putExtra(PackageInstaller.EXTRA_SESSION_ID, sessionId); 4084 intent.setPackage(installerPackageName); 4085 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 4086 return intent; 4087 } 4088 4089 /** 4090 * Get the mode of the session as set in the constructor of the {@link SessionParams}. 4091 * 4092 * @return One of {@link SessionParams#MODE_FULL_INSTALL} 4093 * or {@link SessionParams#MODE_INHERIT_EXISTING} 4094 */ getMode()4095 public int getMode() { 4096 return mode; 4097 } 4098 4099 /** 4100 * Get the value set in {@link SessionParams#setInstallLocation(int)}. 4101 */ getInstallLocation()4102 public int getInstallLocation() { 4103 return installLocation; 4104 } 4105 4106 /** 4107 * Get the value as set in {@link SessionParams#setSize(long)}. 4108 * 4109 * <p>The value is a hint and does not have to match the actual size. 4110 */ getSize()4111 public long getSize() { 4112 return sizeBytes; 4113 } 4114 4115 /** 4116 * Get the value set in {@link SessionParams#setOriginatingUri(Uri)}. 4117 * Note: This value will only be non-null for the owner of the session. 4118 */ getOriginatingUri()4119 public @Nullable Uri getOriginatingUri() { 4120 return originatingUri; 4121 } 4122 4123 /** 4124 * Get the value set in {@link SessionParams#setOriginatingUid(int)}. 4125 */ getOriginatingUid()4126 public int getOriginatingUid() { 4127 return originatingUid; 4128 } 4129 4130 /** 4131 * Get the value set in {@link SessionParams#setReferrerUri(Uri)} 4132 * Note: This value will only be non-null for the owner of the session. 4133 */ getReferrerUri()4134 public @Nullable Uri getReferrerUri() { 4135 return referrerUri; 4136 } 4137 4138 /** 4139 * @return the path to the validated base APK for this session, which may point at an 4140 * APK inside the session (when the session defines the base), or it may 4141 * point at the existing base APK (when adding splits to an existing app). 4142 * 4143 * @hide 4144 */ 4145 @SystemApi 4146 @RequiresPermission(Manifest.permission.READ_INSTALLED_SESSION_PATHS) 4147 @FlaggedApi(Flags.FLAG_GET_RESOLVED_APK_PATH) getResolvedBaseApkPath()4148 public @Nullable String getResolvedBaseApkPath() { 4149 return resolvedBaseCodePath; 4150 } 4151 4152 /** 4153 * Get the value set in {@link SessionParams#setGrantedRuntimePermissions(String[])}. 4154 * 4155 * @hide 4156 */ 4157 @SystemApi getGrantedRuntimePermissions()4158 public @Nullable String[] getGrantedRuntimePermissions() { 4159 return grantedRuntimePermissions; 4160 } 4161 4162 /** 4163 * Get the value set in {@link SessionParams#setWhitelistedRestrictedPermissions(Set)}. 4164 * Note that if all permissions are allowlisted this method returns {@link 4165 * SessionParams#RESTRICTED_PERMISSIONS_ALL}. 4166 * 4167 * @hide 4168 */ 4169 @SystemApi getWhitelistedRestrictedPermissions()4170 public @NonNull Set<String> getWhitelistedRestrictedPermissions() { 4171 if ((installFlags & PackageManager.INSTALL_ALL_WHITELIST_RESTRICTED_PERMISSIONS) != 0) { 4172 return SessionParams.RESTRICTED_PERMISSIONS_ALL; 4173 } 4174 if (whitelistedRestrictedPermissions != null) { 4175 return new ArraySet<>(whitelistedRestrictedPermissions); 4176 } 4177 return Collections.emptySet(); 4178 } 4179 4180 /** 4181 * Get the status of whether permission auto-revocation should be allowed, ignored, or 4182 * deferred to manifest data. 4183 * 4184 * @see android.app.AppOpsManager#MODE_ALLOWED 4185 * @see android.app.AppOpsManager#MODE_IGNORED 4186 * @see android.app.AppOpsManager#MODE_DEFAULT 4187 * 4188 * @return the status of auto-revoke for this package 4189 * 4190 * @hide 4191 */ 4192 @SystemApi getAutoRevokePermissionsMode()4193 public int getAutoRevokePermissionsMode() { 4194 return autoRevokePermissionsMode; 4195 } 4196 4197 /** 4198 * Get the value set in {@link SessionParams#setAllowDowngrade(boolean)}. 4199 * 4200 * @deprecated use {@link #getRequestDowngrade()}. 4201 * @hide 4202 */ 4203 @SystemApi 4204 @Deprecated getAllowDowngrade()4205 public boolean getAllowDowngrade() { 4206 return getRequestDowngrade(); 4207 } 4208 4209 /** 4210 * Get the value set in {@link SessionParams#setRequestDowngrade(boolean)}. 4211 * 4212 * @hide 4213 */ 4214 @SystemApi getRequestDowngrade()4215 public boolean getRequestDowngrade() { 4216 return (installFlags & PackageManager.INSTALL_REQUEST_DOWNGRADE) != 0; 4217 } 4218 4219 /** 4220 * Get the value set in {@link SessionParams#setDontKillApp(boolean)}. 4221 */ getDontKillApp()4222 public boolean getDontKillApp() { 4223 return (installFlags & PackageManager.INSTALL_DONT_KILL_APP) != 0; 4224 } 4225 4226 /** 4227 * Get if this session is to be installed as Instant Apps. 4228 * 4229 * @param isInstantApp an unused parameter and is ignored. 4230 * @return {@code true} if {@link SessionParams#setInstallAsInstantApp(boolean)} was called 4231 * with {@code true}; {@code false} if it was called with {@code false} or if it was not 4232 * called. 4233 * 4234 * @see #getInstallAsFullApp 4235 * 4236 * @hide 4237 */ 4238 @SystemApi getInstallAsInstantApp(boolean isInstantApp)4239 public boolean getInstallAsInstantApp(boolean isInstantApp) { 4240 return (installFlags & PackageManager.INSTALL_INSTANT_APP) != 0; 4241 } 4242 4243 /** 4244 * Get if this session is to be installed as full apps. 4245 * 4246 * @param isInstantApp an unused parameter and is ignored. 4247 * @return {@code true} if {@link SessionParams#setInstallAsInstantApp(boolean)} was called 4248 * with {@code false}; {code false} if it was called with {@code true} or if it was not 4249 * called. 4250 * 4251 * @see #getInstallAsInstantApp 4252 * 4253 * @hide 4254 */ 4255 @SystemApi getInstallAsFullApp(boolean isInstantApp)4256 public boolean getInstallAsFullApp(boolean isInstantApp) { 4257 return (installFlags & PackageManager.INSTALL_FULL_APP) != 0; 4258 } 4259 4260 /** 4261 * Get if {@link SessionParams#setInstallAsVirtualPreload()} was called. 4262 * 4263 * @hide 4264 */ 4265 @SystemApi getInstallAsVirtualPreload()4266 public boolean getInstallAsVirtualPreload() { 4267 return (installFlags & PackageManager.INSTALL_VIRTUAL_PRELOAD) != 0; 4268 } 4269 4270 /** 4271 * Return whether rollback is enabled or disabled for the given upgrade. 4272 * 4273 * @hide 4274 */ 4275 @SystemApi getEnableRollback()4276 public boolean getEnableRollback() { 4277 return (installFlags & PackageManager.INSTALL_ENABLE_ROLLBACK) != 0; 4278 } 4279 4280 /** 4281 * Get the value set in {@link SessionParams#setAllocateAggressive(boolean)}. 4282 * 4283 * @hide 4284 */ 4285 @SystemApi getAllocateAggressive()4286 public boolean getAllocateAggressive() { 4287 return (installFlags & PackageManager.INSTALL_ALLOCATE_AGGRESSIVE) != 0; 4288 } 4289 4290 4291 /** {@hide} */ 4292 @Deprecated getDetailsIntent()4293 public @Nullable Intent getDetailsIntent() { 4294 return createDetailsIntent(); 4295 } 4296 4297 /** 4298 * Get the package source that was set in 4299 * {@link PackageInstaller.SessionParams#setPackageSource(int)}. 4300 */ getPackageSource()4301 public @PackageSourceType int getPackageSource() { 4302 return packageSource; 4303 } 4304 4305 /** 4306 * Returns true if this session is a multi-package session containing references to other 4307 * sessions. 4308 */ isMultiPackage()4309 public boolean isMultiPackage() { 4310 return isMultiPackage; 4311 } 4312 4313 /** 4314 * Returns true if this session is a staged session. 4315 */ isStaged()4316 public boolean isStaged() { 4317 return isStaged; 4318 } 4319 4320 /** 4321 * Return the data policy associated with the rollback for the given upgrade. 4322 * 4323 * @hide 4324 */ 4325 @SystemApi 4326 @PackageManager.RollbackDataPolicy getRollbackDataPolicy()4327 public int getRollbackDataPolicy() { 4328 return rollbackDataPolicy; 4329 } 4330 4331 /** 4332 * Returns true if this session is marked as forceQueryable 4333 * {@hide} 4334 */ isForceQueryable()4335 public boolean isForceQueryable() { 4336 return forceQueryable; 4337 } 4338 4339 /** 4340 * Returns {@code true} if this session is an active staged session. 4341 * 4342 * We consider a session active if it has been committed and it is either pending 4343 * verification, or will be applied at next reboot. 4344 * 4345 * <p>Staged session is active iff: 4346 * <ul> 4347 * <li>It is committed, i.e. {@link SessionInfo#isCommitted()} is {@code true}, and 4348 * <li>it is not applied, i.e. {@link SessionInfo#isStagedSessionApplied()} is {@code 4349 * false}, and 4350 * <li>it is not failed, i.e. {@link SessionInfo#isStagedSessionFailed()} is 4351 * {@code false}. 4352 * </ul> 4353 * 4354 * <p>In case of a multi-package session, reasoning above is applied to the parent session, 4355 * since that is the one that should have been {@link Session#commit committed}. 4356 */ isStagedSessionActive()4357 public boolean isStagedSessionActive() { 4358 return isStaged && isCommitted && !isSessionApplied && !isSessionFailed 4359 && !hasParentSessionId(); 4360 } 4361 4362 /** 4363 * Returns the parent multi-package session ID if this session belongs to one, 4364 * {@link #INVALID_ID} otherwise. 4365 */ getParentSessionId()4366 public int getParentSessionId() { 4367 return parentSessionId; 4368 } 4369 4370 /** 4371 * Returns true if session has a valid parent session, otherwise false. 4372 */ hasParentSessionId()4373 public boolean hasParentSessionId() { 4374 return parentSessionId != INVALID_ID; 4375 } 4376 4377 /** 4378 * Returns the set of session IDs that will be committed when this session is committed if 4379 * this session is a multi-package session. 4380 */ 4381 @NonNull getChildSessionIds()4382 public int[] getChildSessionIds() { 4383 return childSessionIds; 4384 } 4385 checkSessionIsStaged()4386 private void checkSessionIsStaged() { 4387 if (!isStaged) { 4388 throw new IllegalStateException("Session is not marked as staged."); 4389 } 4390 } 4391 4392 /** 4393 * Whether the staged session has been applied successfully, meaning that all of its 4394 * packages have been activated and no further action is required. 4395 * Only meaningful if {@code isStaged} is true. 4396 */ isStagedSessionApplied()4397 public boolean isStagedSessionApplied() { 4398 checkSessionIsStaged(); 4399 return isSessionApplied; 4400 } 4401 4402 /** 4403 * Whether the staged session is ready to be applied at next reboot. Only meaningful if 4404 * {@code isStaged} is true. 4405 */ isStagedSessionReady()4406 public boolean isStagedSessionReady() { 4407 checkSessionIsStaged(); 4408 return isSessionReady; 4409 } 4410 4411 /** 4412 * Whether something went wrong and the staged session is declared as failed, meaning that 4413 * it will be ignored at next reboot. Only meaningful if {@code isStaged} is true. 4414 */ isStagedSessionFailed()4415 public boolean isStagedSessionFailed() { 4416 checkSessionIsStaged(); 4417 return isSessionFailed; 4418 } 4419 4420 /** 4421 * If something went wrong with a staged session, clients can check this error code to 4422 * understand which kind of failure happened. Only meaningful if {@code isStaged} is true. 4423 */ getStagedSessionErrorCode()4424 public int getStagedSessionErrorCode() { 4425 checkSessionIsStaged(); 4426 return mSessionErrorCode; 4427 } 4428 4429 /** 4430 * Text description of the error code returned by {@code getStagedSessionErrorCode}, or 4431 * empty string if no error was encountered. 4432 */ getStagedSessionErrorMessage()4433 public @NonNull String getStagedSessionErrorMessage() { 4434 checkSessionIsStaged(); 4435 return mSessionErrorMessage; 4436 } 4437 4438 /** {@hide} */ setSessionErrorCode(int errorCode, String errorMessage)4439 public void setSessionErrorCode(int errorCode, String errorMessage) { 4440 mSessionErrorCode = errorCode; 4441 mSessionErrorMessage = errorMessage; 4442 } 4443 4444 /** 4445 * Returns {@code true} if {@link Session#commit(IntentSender)}} was called for this 4446 * session. 4447 */ isCommitted()4448 public boolean isCommitted() { 4449 return isCommitted; 4450 } 4451 4452 /** 4453 * The timestamp of the initial creation of the session. 4454 */ getCreatedMillis()4455 public long getCreatedMillis() { 4456 return createdMillis; 4457 } 4458 4459 /** 4460 * The timestamp of the last update that occurred to the session, including changing of 4461 * states in case of staged sessions. 4462 */ 4463 @CurrentTimeMillisLong getUpdatedMillis()4464 public long getUpdatedMillis() { 4465 return updatedMillis; 4466 } 4467 4468 /** 4469 * Whether user action was required by the installer. 4470 * 4471 * <p> 4472 * Note: a return value of {@code USER_ACTION_NOT_REQUIRED} does not guarantee that the 4473 * install will not result in user action. 4474 * 4475 * @return {@link SessionParams#USER_ACTION_NOT_REQUIRED}, 4476 * {@link SessionParams#USER_ACTION_REQUIRED} or 4477 * {@link SessionParams#USER_ACTION_UNSPECIFIED} 4478 */ 4479 @SessionParams.UserActionRequirement getRequireUserAction()4480 public int getRequireUserAction() { 4481 return requireUserAction; 4482 } 4483 4484 /** 4485 * Returns the Uid of the owner of the session. 4486 */ getInstallerUid()4487 public int getInstallerUid() { 4488 return installerUid; 4489 } 4490 4491 /** 4492 * Returns {@code true} if this session will keep the existing application enabled setting 4493 * after installation. 4494 */ isApplicationEnabledSettingPersistent()4495 public boolean isApplicationEnabledSettingPersistent() { 4496 return applicationEnabledSettingPersistent; 4497 } 4498 4499 /** 4500 * Returns whether this session has requested user pre-approval. 4501 */ isPreApprovalRequested()4502 public boolean isPreApprovalRequested() { 4503 return isPreapprovalRequested; 4504 } 4505 4506 /** 4507 * @return {@code true} if the installer requested the update ownership enforcement 4508 * for the packages in this session. 4509 * 4510 * @see PackageInstaller.SessionParams#setRequestUpdateOwnership 4511 */ isRequestUpdateOwnership()4512 public boolean isRequestUpdateOwnership() { 4513 return (installFlags & PackageManager.INSTALL_REQUEST_UPDATE_OWNERSHIP) != 0; 4514 } 4515 4516 /** 4517 * Return the reason for requiring the user action. 4518 * @hide 4519 */ 4520 @SystemApi getPendingUserActionReason()4521 public @UserActionReason int getPendingUserActionReason() { 4522 return pendingUserActionReason; 4523 } 4524 4525 /** 4526 * Returns true if the session is an unarchival. 4527 * 4528 * @see PackageInstaller#requestUnarchive 4529 */ 4530 @FlaggedApi(Flags.FLAG_ARCHIVING) isUnarchival()4531 public boolean isUnarchival() { 4532 return (installFlags & PackageManager.INSTALL_UNARCHIVE) != 0; 4533 } 4534 4535 4536 @Override describeContents()4537 public int describeContents() { 4538 return 0; 4539 } 4540 4541 @Override writeToParcel(Parcel dest, int flags)4542 public void writeToParcel(Parcel dest, int flags) { 4543 dest.writeInt(sessionId); 4544 dest.writeInt(userId); 4545 dest.writeString(installerPackageName); 4546 dest.writeString(installerAttributionTag); 4547 dest.writeString(resolvedBaseCodePath); 4548 dest.writeFloat(progress); 4549 dest.writeInt(sealed ? 1 : 0); 4550 dest.writeInt(active ? 1 : 0); 4551 4552 dest.writeInt(mode); 4553 dest.writeInt(installReason); 4554 dest.writeInt(installScenario); 4555 dest.writeLong(sizeBytes); 4556 dest.writeString(appPackageName); 4557 dest.writeParcelable(appIcon, flags); 4558 dest.writeString(appLabel != null ? appLabel.toString() : null); 4559 4560 dest.writeInt(installLocation); 4561 dest.writeParcelable(originatingUri, flags); 4562 dest.writeInt(originatingUid); 4563 dest.writeParcelable(referrerUri, flags); 4564 dest.writeStringArray(grantedRuntimePermissions); 4565 dest.writeStringList(whitelistedRestrictedPermissions); 4566 dest.writeInt(autoRevokePermissionsMode); 4567 dest.writeInt(installFlags); 4568 dest.writeBoolean(isMultiPackage); 4569 dest.writeBoolean(isStaged); 4570 dest.writeBoolean(forceQueryable); 4571 dest.writeInt(parentSessionId); 4572 dest.writeIntArray(childSessionIds); 4573 dest.writeBoolean(isSessionApplied); 4574 dest.writeBoolean(isSessionReady); 4575 dest.writeBoolean(isSessionFailed); 4576 dest.writeInt(mSessionErrorCode); 4577 dest.writeString(mSessionErrorMessage); 4578 dest.writeBoolean(isCommitted); 4579 dest.writeBoolean(isPreapprovalRequested); 4580 dest.writeInt(rollbackDataPolicy); 4581 dest.writeLong(rollbackLifetimeMillis); 4582 dest.writeInt(rollbackImpactLevel); 4583 dest.writeLong(createdMillis); 4584 dest.writeInt(requireUserAction); 4585 dest.writeInt(installerUid); 4586 dest.writeInt(packageSource); 4587 dest.writeBoolean(applicationEnabledSettingPersistent); 4588 dest.writeInt(pendingUserActionReason); 4589 } 4590 4591 public static final Parcelable.Creator<SessionInfo> 4592 CREATOR = new Parcelable.Creator<SessionInfo>() { 4593 @Override 4594 public SessionInfo createFromParcel(Parcel p) { 4595 return new SessionInfo(p); 4596 } 4597 4598 @Override 4599 public SessionInfo[] newArray(int size) { 4600 return new SessionInfo[size]; 4601 } 4602 }; 4603 } 4604 4605 /** 4606 * Details for requesting the pre-commit install approval. 4607 */ 4608 @DataClass(genConstructor = false, genToString = true) 4609 public static final class PreapprovalDetails implements Parcelable { 4610 /** 4611 * The icon representing the app to be installed. 4612 */ 4613 private final @Nullable Bitmap mIcon; 4614 /** 4615 * The label representing the app to be installed. 4616 */ 4617 private final @NonNull CharSequence mLabel; 4618 /** 4619 * The locale of the app label being used. 4620 */ 4621 private final @NonNull ULocale mLocale; 4622 /** 4623 * The package name of the app to be installed. 4624 */ 4625 private final @NonNull String mPackageName; 4626 4627 /** 4628 * Creates a new PreapprovalDetails. 4629 * 4630 * @param icon 4631 * The icon representing the app to be installed. 4632 * @param label 4633 * The label representing the app to be installed. 4634 * @param locale 4635 * The locale is used to get the app label from the APKs (includes the base APK and 4636 * split APKs) related to the package to be installed. 4637 * @param packageName 4638 * The package name of the app to be installed. 4639 * @hide 4640 */ PreapprovalDetails( @ullable Bitmap icon, @NonNull CharSequence label, @NonNull ULocale locale, @NonNull String packageName)4641 public PreapprovalDetails( 4642 @Nullable Bitmap icon, 4643 @NonNull CharSequence label, 4644 @NonNull ULocale locale, 4645 @NonNull String packageName) { 4646 mIcon = icon; 4647 mLabel = label; 4648 Preconditions.checkArgument(!TextUtils.isEmpty(mLabel), 4649 "App label cannot be empty."); 4650 mLocale = locale; 4651 Preconditions.checkArgument(!Objects.isNull(mLocale), 4652 "Locale cannot be null."); 4653 mPackageName = packageName; 4654 Preconditions.checkArgument(!TextUtils.isEmpty(mPackageName), 4655 "Package name cannot be empty."); 4656 } 4657 4658 @Override writeToParcel(@onNull Parcel dest, int flags)4659 public void writeToParcel(@NonNull Parcel dest, int flags) { 4660 byte flg = 0; 4661 if (mIcon != null) flg |= 0x1; 4662 dest.writeByte(flg); 4663 if (mIcon != null) mIcon.writeToParcel(dest, flags); 4664 dest.writeCharSequence(mLabel); 4665 dest.writeString8(mLocale.toString()); 4666 dest.writeString8(mPackageName); 4667 } 4668 4669 @Override describeContents()4670 public int describeContents() { return 0; } 4671 4672 /** @hide */ PreapprovalDetails(@onNull Parcel in)4673 /* package-private */ PreapprovalDetails(@NonNull Parcel in) { 4674 byte flg = in.readByte(); 4675 final Bitmap icon = (flg & 0x1) == 0 ? null : Bitmap.CREATOR.createFromParcel(in); 4676 final CharSequence label = in.readCharSequence(); 4677 final ULocale locale = new ULocale(in.readString8()); 4678 final String packageName = in.readString8(); 4679 4680 mIcon = icon; 4681 mLabel = label; 4682 Preconditions.checkArgument(!TextUtils.isEmpty(mLabel), 4683 "App label cannot be empty."); 4684 mLocale = locale; 4685 Preconditions.checkArgument(!Objects.isNull(mLocale), 4686 "Locale cannot be null."); 4687 mPackageName = packageName; 4688 Preconditions.checkArgument(!TextUtils.isEmpty(mPackageName), 4689 "Package name cannot be empty."); 4690 } 4691 4692 public static final @NonNull Parcelable.Creator<PreapprovalDetails> CREATOR 4693 = new Parcelable.Creator<PreapprovalDetails>() { 4694 @Override 4695 public PreapprovalDetails[] newArray(int size) { 4696 return new PreapprovalDetails[size]; 4697 } 4698 4699 @Override 4700 public PreapprovalDetails createFromParcel(@NonNull Parcel in) { 4701 return new PreapprovalDetails(in); 4702 } 4703 }; 4704 4705 /** 4706 * A builder for {@link PreapprovalDetails} 4707 */ 4708 public static final class Builder { 4709 4710 private @Nullable Bitmap mIcon; 4711 private @NonNull CharSequence mLabel; 4712 private @NonNull ULocale mLocale; 4713 private @NonNull String mPackageName; 4714 4715 private long mBuilderFieldsSet = 0L; 4716 4717 /** 4718 * Creates a new Builder. 4719 */ Builder()4720 public Builder() {} 4721 4722 /** 4723 * The icon representing the app to be installed. 4724 */ setIcon(@onNull Bitmap value)4725 public @NonNull Builder setIcon(@NonNull Bitmap value) { 4726 checkNotUsed(); 4727 mBuilderFieldsSet |= 0x1; 4728 mIcon = value; 4729 return this; 4730 } 4731 4732 /** 4733 * The label representing the app to be installed. 4734 */ setLabel(@onNull CharSequence value)4735 public @NonNull Builder setLabel(@NonNull CharSequence value) { 4736 checkNotUsed(); 4737 mBuilderFieldsSet |= 0x2; 4738 mLabel = value; 4739 return this; 4740 } 4741 4742 /** 4743 * The locale is used to get the app label from the APKs (includes the base APK and 4744 * split APKs) related to the package to be installed. The caller needs to make sure 4745 * the app label is consistent with the app label of {@link PreapprovalDetails} when 4746 * validating the installation. Otherwise, the pre-approval install session will fail. 4747 */ setLocale(@onNull ULocale value)4748 public @NonNull Builder setLocale(@NonNull ULocale value) { 4749 checkNotUsed(); 4750 mBuilderFieldsSet |= 0x4; 4751 mLocale = value; 4752 return this; 4753 } 4754 4755 /** 4756 * The package name of the app to be installed. 4757 */ setPackageName(@onNull String value)4758 public @NonNull Builder setPackageName(@NonNull String value) { 4759 checkNotUsed(); 4760 mBuilderFieldsSet |= 0x8; 4761 mPackageName = value; 4762 return this; 4763 } 4764 4765 /** Builds the instance. This builder should not be touched after calling this! */ build()4766 public @NonNull PreapprovalDetails build() { 4767 checkNotUsed(); 4768 mBuilderFieldsSet |= 0x10; // Mark builder used 4769 4770 PreapprovalDetails o = new PreapprovalDetails( 4771 mIcon, 4772 mLabel, 4773 mLocale, 4774 mPackageName); 4775 return o; 4776 } 4777 checkNotUsed()4778 private void checkNotUsed() { 4779 if ((mBuilderFieldsSet & 0x10) != 0) { 4780 throw new IllegalStateException("This Builder should not be reused. " 4781 + "Use a new Builder instance instead"); 4782 } 4783 } 4784 } 4785 4786 4787 4788 4789 // Code below generated by codegen v1.0.23. 4790 // 4791 // DO NOT MODIFY! 4792 // CHECKSTYLE:OFF Generated code 4793 // 4794 // To regenerate run: 4795 // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/content/pm/PackageInstaller.java 4796 // 4797 // To exclude the generated code from IntelliJ auto-formatting enable (one-time): 4798 // Settings > Editor > Code Style > Formatter Control 4799 //@formatter:off 4800 4801 4802 /** 4803 * The icon representing the app to be installed. 4804 */ 4805 @DataClass.Generated.Member getIcon()4806 public @Nullable Bitmap getIcon() { 4807 return mIcon; 4808 } 4809 4810 /** 4811 * The label representing the app to be installed. 4812 */ 4813 @DataClass.Generated.Member getLabel()4814 public @NonNull CharSequence getLabel() { 4815 return mLabel; 4816 } 4817 4818 /** 4819 * The locale of the app label being used. 4820 */ 4821 @DataClass.Generated.Member getLocale()4822 public @NonNull ULocale getLocale() { 4823 return mLocale; 4824 } 4825 4826 /** 4827 * The package name of the app to be installed. 4828 */ 4829 @DataClass.Generated.Member getPackageName()4830 public @NonNull String getPackageName() { 4831 return mPackageName; 4832 } 4833 4834 @Override 4835 @DataClass.Generated.Member toString()4836 public String toString() { 4837 // You can override field toString logic by defining methods like: 4838 // String fieldNameToString() { ... } 4839 4840 return "PreapprovalDetails { " + 4841 "icon = " + mIcon + ", " + 4842 "label = " + mLabel + ", " + 4843 "locale = " + mLocale + ", " + 4844 "packageName = " + mPackageName + 4845 " }"; 4846 } 4847 4848 @DataClass.Generated( 4849 time = 1676970504308L, 4850 codegenVersion = "1.0.23", 4851 sourceFile = "frameworks/base/core/java/android/content/pm/PackageInstaller.java", 4852 inputSignatures = "private final @android.annotation.Nullable android.graphics.Bitmap mIcon\nprivate final @android.annotation.NonNull java.lang.CharSequence mLabel\nprivate final @android.annotation.NonNull android.icu.util.ULocale mLocale\nprivate final @android.annotation.NonNull java.lang.String mPackageName\npublic static final @android.annotation.NonNull android.os.Parcelable.Creator<android.content.pm.PackageInstaller.PreapprovalDetails> CREATOR\npublic @java.lang.Override void writeToParcel(android.os.Parcel,int)\npublic @java.lang.Override int describeContents()\nclass PreapprovalDetails extends java.lang.Object implements [android.os.Parcelable]\nprivate @android.annotation.Nullable android.graphics.Bitmap mIcon\nprivate @android.annotation.NonNull java.lang.CharSequence mLabel\nprivate @android.annotation.NonNull android.icu.util.ULocale mLocale\nprivate @android.annotation.NonNull java.lang.String mPackageName\nprivate long mBuilderFieldsSet\npublic @android.annotation.NonNull android.content.pm.PackageInstaller.PreapprovalDetails.Builder setIcon(android.graphics.Bitmap)\npublic @android.annotation.NonNull android.content.pm.PackageInstaller.PreapprovalDetails.Builder setLabel(java.lang.CharSequence)\npublic @android.annotation.NonNull android.content.pm.PackageInstaller.PreapprovalDetails.Builder setLocale(android.icu.util.ULocale)\npublic @android.annotation.NonNull android.content.pm.PackageInstaller.PreapprovalDetails.Builder setPackageName(java.lang.String)\npublic @android.annotation.NonNull android.content.pm.PackageInstaller.PreapprovalDetails build()\nprivate void checkNotUsed()\nclass Builder extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genConstructor=false, genToString=true)") 4853 4854 @Deprecated __metadata()4855 private void __metadata() {} 4856 4857 //@formatter:on 4858 // End of generated code 4859 4860 } 4861 4862 /** 4863 * The callback result of {@link #checkInstallConstraints(List, InstallConstraints, Executor, Consumer)}. 4864 */ 4865 @DataClass(genParcelable = true, genHiddenConstructor = true) 4866 @DataClass.Suppress("isAllConstraintsSatisfied") 4867 public static final class InstallConstraintsResult implements Parcelable { 4868 /** 4869 * True if all constraints are satisfied. 4870 */ 4871 private boolean mAllConstraintsSatisfied; 4872 4873 /** 4874 * True if all constraints are satisfied. 4875 */ areAllConstraintsSatisfied()4876 public boolean areAllConstraintsSatisfied() { 4877 return mAllConstraintsSatisfied; 4878 } 4879 4880 4881 4882 // Code below generated by codegen v1.0.23. 4883 // 4884 // DO NOT MODIFY! 4885 // CHECKSTYLE:OFF Generated code 4886 // 4887 // To regenerate run: 4888 // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/content/pm/PackageInstaller.java 4889 // 4890 // To exclude the generated code from IntelliJ auto-formatting enable (one-time): 4891 // Settings > Editor > Code Style > Formatter Control 4892 //@formatter:off 4893 4894 4895 /** 4896 * Creates a new InstallConstraintsResult. 4897 * 4898 * @param allConstraintsSatisfied 4899 * True if all constraints are satisfied. 4900 * @hide 4901 */ 4902 @DataClass.Generated.Member InstallConstraintsResult( boolean allConstraintsSatisfied)4903 public InstallConstraintsResult( 4904 boolean allConstraintsSatisfied) { 4905 this.mAllConstraintsSatisfied = allConstraintsSatisfied; 4906 4907 // onConstructed(); // You can define this method to get a callback 4908 } 4909 4910 @Override 4911 @DataClass.Generated.Member writeToParcel(@onNull Parcel dest, int flags)4912 public void writeToParcel(@NonNull Parcel dest, int flags) { 4913 // You can override field parcelling by defining methods like: 4914 // void parcelFieldName(Parcel dest, int flags) { ... } 4915 4916 byte flg = 0; 4917 if (mAllConstraintsSatisfied) flg |= 0x1; 4918 dest.writeByte(flg); 4919 } 4920 4921 @Override 4922 @DataClass.Generated.Member describeContents()4923 public int describeContents() { return 0; } 4924 4925 /** @hide */ 4926 @SuppressWarnings({"unchecked", "RedundantCast"}) 4927 @DataClass.Generated.Member InstallConstraintsResult(@onNull Parcel in)4928 /* package-private */ InstallConstraintsResult(@NonNull Parcel in) { 4929 // You can override field unparcelling by defining methods like: 4930 // static FieldType unparcelFieldName(Parcel in) { ... } 4931 4932 byte flg = in.readByte(); 4933 boolean allConstraintsSatisfied = (flg & 0x1) != 0; 4934 4935 this.mAllConstraintsSatisfied = allConstraintsSatisfied; 4936 4937 // onConstructed(); // You can define this method to get a callback 4938 } 4939 4940 @DataClass.Generated.Member 4941 public static final @NonNull Parcelable.Creator<InstallConstraintsResult> CREATOR 4942 = new Parcelable.Creator<InstallConstraintsResult>() { 4943 @Override 4944 public InstallConstraintsResult[] newArray(int size) { 4945 return new InstallConstraintsResult[size]; 4946 } 4947 4948 @Override 4949 public InstallConstraintsResult createFromParcel(@NonNull Parcel in) { 4950 return new InstallConstraintsResult(in); 4951 } 4952 }; 4953 4954 @DataClass.Generated( 4955 time = 1676970504336L, 4956 codegenVersion = "1.0.23", 4957 sourceFile = "frameworks/base/core/java/android/content/pm/PackageInstaller.java", 4958 inputSignatures = "private boolean mAllConstraintsSatisfied\npublic boolean areAllConstraintsSatisfied()\nclass InstallConstraintsResult extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genParcelable=true, genHiddenConstructor=true)") 4959 @Deprecated __metadata()4960 private void __metadata() {} 4961 4962 4963 //@formatter:on 4964 // End of generated code 4965 4966 } 4967 4968 /** 4969 * A class to encapsulate constraints for installation. 4970 * 4971 * When used with {@link #checkInstallConstraints(List, InstallConstraints, Executor, Consumer)}, it 4972 * specifies the conditions to check against for the packages in question. This can be used 4973 * by app stores to deliver auto updates without disrupting the user experience (referred as 4974 * gentle update) - for example, an app store might hold off updates when it find out the 4975 * app to update is interacting with the user. 4976 * 4977 * Use {@link Builder} to create a new instance and call mutator methods to add constraints. 4978 * If no mutators were called, default constraints will be generated which implies no 4979 * constraints. It is recommended to use preset constraints which are useful in most 4980 * cases. 4981 * 4982 * For the purpose of gentle update, it is recommended to always use {@link #GENTLE_UPDATE} 4983 * for the system knows best how to do it. It will also benefits the installer as the 4984 * platform evolves and add more constraints to improve the accuracy and efficiency of 4985 * gentle update. 4986 * 4987 * Note the constraints are applied transitively. If app Foo is used by app Bar (via shared 4988 * library or bounded service), the constraints will also be applied to Bar. 4989 */ 4990 @DataClass(genParcelable = true, genHiddenConstructor = true, genEqualsHashCode=true) 4991 public static final class InstallConstraints implements Parcelable { 4992 /** 4993 * Preset constraints suitable for gentle update. 4994 */ 4995 @NonNull 4996 public static final InstallConstraints GENTLE_UPDATE = 4997 new Builder().setAppNotInteractingRequired().build(); 4998 4999 private final boolean mDeviceIdleRequired; 5000 private final boolean mAppNotForegroundRequired; 5001 private final boolean mAppNotInteractingRequired; 5002 private final boolean mAppNotTopVisibleRequired; 5003 private final boolean mNotInCallRequired; 5004 5005 /** 5006 * Builder class for constructing {@link InstallConstraints}. 5007 */ 5008 public static final class Builder { 5009 private boolean mDeviceIdleRequired; 5010 private boolean mAppNotForegroundRequired; 5011 private boolean mAppNotInteractingRequired; 5012 private boolean mAppNotTopVisibleRequired; 5013 private boolean mNotInCallRequired; 5014 5015 /** 5016 * This constraint requires the device is idle. 5017 */ 5018 @SuppressLint("MissingGetterMatchingBuilder") 5019 @NonNull setDeviceIdleRequired()5020 public Builder setDeviceIdleRequired() { 5021 mDeviceIdleRequired = true; 5022 return this; 5023 } 5024 5025 /** 5026 * This constraint requires the app in question is not in the foreground. 5027 */ 5028 @SuppressLint("MissingGetterMatchingBuilder") 5029 @NonNull setAppNotForegroundRequired()5030 public Builder setAppNotForegroundRequired() { 5031 mAppNotForegroundRequired = true; 5032 return this; 5033 } 5034 5035 /** 5036 * This constraint requires the app in question is not interacting with the user. 5037 * User interaction includes: 5038 * <ul> 5039 * <li>playing or recording audio/video</li> 5040 * <li>sending or receiving network data</li> 5041 * <li>being visible to the user</li> 5042 * </ul> 5043 */ 5044 @SuppressLint("MissingGetterMatchingBuilder") 5045 @NonNull setAppNotInteractingRequired()5046 public Builder setAppNotInteractingRequired() { 5047 mAppNotInteractingRequired = true; 5048 return this; 5049 } 5050 5051 /** 5052 * This constraint requires the app in question is not top-visible to the user. 5053 * A top-visible app is showing UI at the top of the screen that the user is 5054 * interacting with. 5055 * 5056 * Note this constraint is a subset of {@link #setAppNotForegroundRequired()} 5057 * because a top-visible app is also a foreground app. This is also a subset 5058 * of {@link #setAppNotInteractingRequired()} because a top-visible app is interacting 5059 * with the user. 5060 * 5061 * @see ActivityManager.RunningAppProcessInfo#IMPORTANCE_FOREGROUND 5062 */ 5063 @SuppressLint("MissingGetterMatchingBuilder") 5064 @NonNull setAppNotTopVisibleRequired()5065 public Builder setAppNotTopVisibleRequired() { 5066 mAppNotTopVisibleRequired = true; 5067 return this; 5068 } 5069 5070 /** 5071 * This constraint requires there is no ongoing call in the device. 5072 */ 5073 @SuppressLint("MissingGetterMatchingBuilder") 5074 @NonNull setNotInCallRequired()5075 public Builder setNotInCallRequired() { 5076 mNotInCallRequired = true; 5077 return this; 5078 } 5079 5080 /** 5081 * Builds a new {@link InstallConstraints} instance. 5082 */ 5083 @NonNull build()5084 public InstallConstraints build() { 5085 return new InstallConstraints(mDeviceIdleRequired, mAppNotForegroundRequired, 5086 mAppNotInteractingRequired, mAppNotTopVisibleRequired, mNotInCallRequired); 5087 } 5088 } 5089 5090 5091 5092 // Code below generated by codegen v1.0.23. 5093 // 5094 // DO NOT MODIFY! 5095 // CHECKSTYLE:OFF Generated code 5096 // 5097 // To regenerate run: 5098 // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/content/pm/PackageInstaller.java 5099 // 5100 // To exclude the generated code from IntelliJ auto-formatting enable (one-time): 5101 // Settings > Editor > Code Style > Formatter Control 5102 //@formatter:off 5103 5104 5105 /** 5106 * Creates a new InstallConstraints. 5107 * 5108 * @hide 5109 */ 5110 @DataClass.Generated.Member InstallConstraints( boolean deviceIdleRequired, boolean appNotForegroundRequired, boolean appNotInteractingRequired, boolean appNotTopVisibleRequired, boolean notInCallRequired)5111 public InstallConstraints( 5112 boolean deviceIdleRequired, 5113 boolean appNotForegroundRequired, 5114 boolean appNotInteractingRequired, 5115 boolean appNotTopVisibleRequired, 5116 boolean notInCallRequired) { 5117 this.mDeviceIdleRequired = deviceIdleRequired; 5118 this.mAppNotForegroundRequired = appNotForegroundRequired; 5119 this.mAppNotInteractingRequired = appNotInteractingRequired; 5120 this.mAppNotTopVisibleRequired = appNotTopVisibleRequired; 5121 this.mNotInCallRequired = notInCallRequired; 5122 5123 // onConstructed(); // You can define this method to get a callback 5124 } 5125 5126 @DataClass.Generated.Member isDeviceIdleRequired()5127 public boolean isDeviceIdleRequired() { 5128 return mDeviceIdleRequired; 5129 } 5130 5131 @DataClass.Generated.Member isAppNotForegroundRequired()5132 public boolean isAppNotForegroundRequired() { 5133 return mAppNotForegroundRequired; 5134 } 5135 5136 @DataClass.Generated.Member isAppNotInteractingRequired()5137 public boolean isAppNotInteractingRequired() { 5138 return mAppNotInteractingRequired; 5139 } 5140 5141 @DataClass.Generated.Member isAppNotTopVisibleRequired()5142 public boolean isAppNotTopVisibleRequired() { 5143 return mAppNotTopVisibleRequired; 5144 } 5145 5146 @DataClass.Generated.Member isNotInCallRequired()5147 public boolean isNotInCallRequired() { 5148 return mNotInCallRequired; 5149 } 5150 5151 @Override 5152 @DataClass.Generated.Member equals(@ullable Object o)5153 public boolean equals(@Nullable Object o) { 5154 // You can override field equality logic by defining either of the methods like: 5155 // boolean fieldNameEquals(InstallConstraints other) { ... } 5156 // boolean fieldNameEquals(FieldType otherValue) { ... } 5157 5158 if (this == o) return true; 5159 if (o == null || getClass() != o.getClass()) return false; 5160 @SuppressWarnings("unchecked") 5161 InstallConstraints that = (InstallConstraints) o; 5162 //noinspection PointlessBooleanExpression 5163 return true 5164 && mDeviceIdleRequired == that.mDeviceIdleRequired 5165 && mAppNotForegroundRequired == that.mAppNotForegroundRequired 5166 && mAppNotInteractingRequired == that.mAppNotInteractingRequired 5167 && mAppNotTopVisibleRequired == that.mAppNotTopVisibleRequired 5168 && mNotInCallRequired == that.mNotInCallRequired; 5169 } 5170 5171 @Override 5172 @DataClass.Generated.Member hashCode()5173 public int hashCode() { 5174 // You can override field hashCode logic by defining methods like: 5175 // int fieldNameHashCode() { ... } 5176 5177 int _hash = 1; 5178 _hash = 31 * _hash + Boolean.hashCode(mDeviceIdleRequired); 5179 _hash = 31 * _hash + Boolean.hashCode(mAppNotForegroundRequired); 5180 _hash = 31 * _hash + Boolean.hashCode(mAppNotInteractingRequired); 5181 _hash = 31 * _hash + Boolean.hashCode(mAppNotTopVisibleRequired); 5182 _hash = 31 * _hash + Boolean.hashCode(mNotInCallRequired); 5183 return _hash; 5184 } 5185 5186 @Override 5187 @DataClass.Generated.Member writeToParcel(@onNull Parcel dest, int flags)5188 public void writeToParcel(@NonNull Parcel dest, int flags) { 5189 // You can override field parcelling by defining methods like: 5190 // void parcelFieldName(Parcel dest, int flags) { ... } 5191 5192 byte flg = 0; 5193 if (mDeviceIdleRequired) flg |= 0x1; 5194 if (mAppNotForegroundRequired) flg |= 0x2; 5195 if (mAppNotInteractingRequired) flg |= 0x4; 5196 if (mAppNotTopVisibleRequired) flg |= 0x8; 5197 if (mNotInCallRequired) flg |= 0x10; 5198 dest.writeByte(flg); 5199 } 5200 5201 @Override 5202 @DataClass.Generated.Member describeContents()5203 public int describeContents() { return 0; } 5204 5205 /** @hide */ 5206 @SuppressWarnings({"unchecked", "RedundantCast"}) 5207 @DataClass.Generated.Member InstallConstraints(@onNull Parcel in)5208 /* package-private */ InstallConstraints(@NonNull Parcel in) { 5209 // You can override field unparcelling by defining methods like: 5210 // static FieldType unparcelFieldName(Parcel in) { ... } 5211 5212 byte flg = in.readByte(); 5213 boolean deviceIdleRequired = (flg & 0x1) != 0; 5214 boolean appNotForegroundRequired = (flg & 0x2) != 0; 5215 boolean appNotInteractingRequired = (flg & 0x4) != 0; 5216 boolean appNotTopVisibleRequired = (flg & 0x8) != 0; 5217 boolean notInCallRequired = (flg & 0x10) != 0; 5218 5219 this.mDeviceIdleRequired = deviceIdleRequired; 5220 this.mAppNotForegroundRequired = appNotForegroundRequired; 5221 this.mAppNotInteractingRequired = appNotInteractingRequired; 5222 this.mAppNotTopVisibleRequired = appNotTopVisibleRequired; 5223 this.mNotInCallRequired = notInCallRequired; 5224 5225 // onConstructed(); // You can define this method to get a callback 5226 } 5227 5228 @DataClass.Generated.Member 5229 public static final @NonNull Parcelable.Creator<InstallConstraints> CREATOR 5230 = new Parcelable.Creator<InstallConstraints>() { 5231 @Override 5232 public InstallConstraints[] newArray(int size) { 5233 return new InstallConstraints[size]; 5234 } 5235 5236 @Override 5237 public InstallConstraints createFromParcel(@NonNull Parcel in) { 5238 return new InstallConstraints(in); 5239 } 5240 }; 5241 5242 @DataClass.Generated( 5243 time = 1676970504352L, 5244 codegenVersion = "1.0.23", 5245 sourceFile = "frameworks/base/core/java/android/content/pm/PackageInstaller.java", 5246 inputSignatures = "public static final @android.annotation.NonNull android.content.pm.PackageInstaller.InstallConstraints GENTLE_UPDATE\nprivate final boolean mDeviceIdleRequired\nprivate final boolean mAppNotForegroundRequired\nprivate final boolean mAppNotInteractingRequired\nprivate final boolean mAppNotTopVisibleRequired\nprivate final boolean mNotInCallRequired\nclass InstallConstraints extends java.lang.Object implements [android.os.Parcelable]\nprivate boolean mDeviceIdleRequired\nprivate boolean mAppNotForegroundRequired\nprivate boolean mAppNotInteractingRequired\nprivate boolean mAppNotTopVisibleRequired\nprivate boolean mNotInCallRequired\npublic @android.annotation.SuppressLint @android.annotation.NonNull android.content.pm.PackageInstaller.InstallConstraints.Builder setDeviceIdleRequired()\npublic @android.annotation.SuppressLint @android.annotation.NonNull android.content.pm.PackageInstaller.InstallConstraints.Builder setAppNotForegroundRequired()\npublic @android.annotation.SuppressLint @android.annotation.NonNull android.content.pm.PackageInstaller.InstallConstraints.Builder setAppNotInteractingRequired()\npublic @android.annotation.SuppressLint @android.annotation.NonNull android.content.pm.PackageInstaller.InstallConstraints.Builder setAppNotTopVisibleRequired()\npublic @android.annotation.SuppressLint @android.annotation.NonNull android.content.pm.PackageInstaller.InstallConstraints.Builder setNotInCallRequired()\npublic @android.annotation.NonNull android.content.pm.PackageInstaller.InstallConstraints build()\nclass Builder extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genParcelable=true, genHiddenConstructor=true, genEqualsHashCode=true)") 5247 5248 @Deprecated __metadata()5249 private void __metadata() {} 5250 5251 //@formatter:on 5252 // End of generated code 5253 5254 } 5255 5256 /** 5257 * Used to communicate the unarchival state in {@link #reportUnarchivalState}. 5258 */ 5259 @FlaggedApi(Flags.FLAG_ARCHIVING) 5260 public static final class UnarchivalState { 5261 5262 /** 5263 * The caller is able to facilitate the unarchival for the given {@code unarchiveId}. 5264 * 5265 * @param unarchiveId the ID provided by the system as part of the intent.action.UNARCHIVE 5266 * broadcast with EXTRA_UNARCHIVE_ID. 5267 */ 5268 @NonNull createOkState(int unarchiveId)5269 public static UnarchivalState createOkState(int unarchiveId) { 5270 return new UnarchivalState(unarchiveId, UNARCHIVAL_OK, /* requiredStorageBytes= */ -1, 5271 /* userActionIntent= */ null); 5272 } 5273 5274 /** 5275 * User action is required before commencing with the unarchival for the given 5276 * {@code unarchiveId}. E.g., this could be used if it's necessary for the user to sign-in 5277 * first. 5278 * 5279 * @param unarchiveId the ID provided by the system as part of the 5280 * intent.action.UNARCHIVE 5281 * broadcast with EXTRA_UNARCHIVE_ID. 5282 * @param userActionIntent optional intent to start a follow up action required to 5283 * facilitate the unarchival flow (e.g. user needs to log in). 5284 */ 5285 @NonNull createUserActionRequiredState(int unarchiveId, @NonNull PendingIntent userActionIntent)5286 public static UnarchivalState createUserActionRequiredState(int unarchiveId, 5287 @NonNull PendingIntent userActionIntent) { 5288 Objects.requireNonNull(userActionIntent); 5289 return new UnarchivalState(unarchiveId, UNARCHIVAL_ERROR_USER_ACTION_NEEDED, 5290 /* requiredStorageBytes= */ -1, userActionIntent); 5291 } 5292 5293 /** 5294 * There is not enough storage to start the unarchival for the given {@code unarchiveId}. 5295 * 5296 * @param unarchiveId the ID provided by the system as part of the 5297 * intent.action.UNARCHIVE 5298 * broadcast with EXTRA_UNARCHIVE_ID. 5299 * @param requiredStorageBytes ff the error is UNARCHIVAL_ERROR_INSUFFICIENT_STORAGE this 5300 * field should be set to specify how many additional bytes of 5301 * storage are required to unarchive the app. 5302 * @param userActionIntent can optionally be set to provide a custom storage-clearing 5303 * action. 5304 */ 5305 @NonNull createInsufficientStorageState(int unarchiveId, long requiredStorageBytes, @Nullable PendingIntent userActionIntent)5306 public static UnarchivalState createInsufficientStorageState(int unarchiveId, 5307 long requiredStorageBytes, @Nullable PendingIntent userActionIntent) { 5308 return new UnarchivalState(unarchiveId, UNARCHIVAL_ERROR_INSUFFICIENT_STORAGE, 5309 requiredStorageBytes, userActionIntent); 5310 } 5311 5312 /** 5313 * The device has no data connectivity and unarchival cannot be started for the given 5314 * {@code unarchiveId}. 5315 * 5316 * @param unarchiveId the ID provided by the system as part of the intent.action.UNARCHIVE 5317 * broadcast with EXTRA_UNARCHIVE_ID. 5318 */ 5319 @NonNull createNoConnectivityState(int unarchiveId)5320 public static UnarchivalState createNoConnectivityState(int unarchiveId) { 5321 return new UnarchivalState(unarchiveId, UNARCHIVAL_ERROR_NO_CONNECTIVITY, 5322 /* requiredStorageBytes= */ -1,/* userActionIntent= */ null); 5323 } 5324 5325 /** 5326 * Generic error state for all cases that are not covered by other methods in this class. 5327 * 5328 * @param unarchiveId the ID provided by the system as part of the intent.action.UNARCHIVE 5329 * broadcast with EXTRA_UNARCHIVE_ID. 5330 */ 5331 @NonNull createGenericErrorState(int unarchiveId)5332 public static UnarchivalState createGenericErrorState(int unarchiveId) { 5333 return new UnarchivalState(unarchiveId, UNARCHIVAL_GENERIC_ERROR, 5334 /* requiredStorageBytes= */ -1,/* userActionIntent= */ null); 5335 } 5336 5337 5338 /** 5339 * The ID provided by the system as part of the intent.action.UNARCHIVE broadcast with 5340 * EXTRA_UNARCHIVE_ID. 5341 */ 5342 private final int mUnarchiveId; 5343 5344 /** Used for the system to provide the user with necessary follow-up steps or errors. */ 5345 @UnarchivalStatus 5346 private final int mStatus; 5347 5348 /** 5349 * If the error is UNARCHIVAL_ERROR_INSUFFICIENT_STORAGE this field should be set to specify 5350 * how many additional bytes of storage are required to unarchive the app. 5351 */ 5352 private final long mRequiredStorageBytes; 5353 5354 /** 5355 * Optional intent to start a follow up action required to facilitate the unarchival flow 5356 * (e.g., user needs to log in). 5357 */ 5358 @Nullable 5359 private final PendingIntent mUserActionIntent; 5360 5361 /** 5362 * Creates a new UnarchivalState. 5363 * 5364 * @param unarchiveId The ID provided by the system as part of the 5365 * intent.action.UNARCHIVE broadcast with 5366 * EXTRA_UNARCHIVE_ID. 5367 * @param status Used for the system to provide the user with necessary 5368 * follow-up steps or errors. 5369 * @param requiredStorageBytes If the error is UNARCHIVAL_ERROR_INSUFFICIENT_STORAGE this 5370 * field should be set to specify 5371 * how many additional bytes of storage are required to 5372 * unarchive the app. 5373 * @param userActionIntent Optional intent to start a follow up action required to 5374 * facilitate the unarchival flow 5375 * (e.g,. user needs to log in). 5376 * @hide 5377 */ UnarchivalState( int unarchiveId, @UnarchivalStatus int status, long requiredStorageBytes, @Nullable PendingIntent userActionIntent)5378 private UnarchivalState( 5379 int unarchiveId, 5380 @UnarchivalStatus int status, 5381 long requiredStorageBytes, 5382 @Nullable PendingIntent userActionIntent) { 5383 this.mUnarchiveId = unarchiveId; 5384 this.mStatus = status; 5385 com.android.internal.util.AnnotationValidations.validate( 5386 UnarchivalStatus.class, null, mStatus); 5387 this.mRequiredStorageBytes = requiredStorageBytes; 5388 this.mUserActionIntent = userActionIntent; 5389 } 5390 5391 /** 5392 * The ID provided by the system as part of the intent.action.UNARCHIVE broadcast with 5393 * EXTRA_UNARCHIVE_ID. 5394 * 5395 * @hide 5396 */ getUnarchiveId()5397 int getUnarchiveId() { 5398 return mUnarchiveId; 5399 } 5400 5401 /** 5402 * Used for the system to provide the user with necessary follow-up steps or errors. 5403 * 5404 * @hide 5405 */ getStatus()5406 @UnarchivalStatus int getStatus() { 5407 return mStatus; 5408 } 5409 5410 /** 5411 * If the error is UNARCHIVAL_ERROR_INSUFFICIENT_STORAGE this field should be set to specify 5412 * how many additional bytes of storage are required to unarchive the app. 5413 * 5414 * @hide 5415 */ getRequiredStorageBytes()5416 long getRequiredStorageBytes() { 5417 return mRequiredStorageBytes; 5418 } 5419 5420 /** 5421 * Optional intent to start a follow up action required to facilitate the unarchival flow 5422 * (e.g. user needs to log in). 5423 * 5424 * @hide 5425 */ getUserActionIntent()5426 @Nullable PendingIntent getUserActionIntent() { 5427 return mUserActionIntent; 5428 } 5429 } 5430 5431 } 5432