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