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