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