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