diff options
| author | 2024-07-15 15:19:40 -0700 | |
|---|---|---|
| committer | 2024-07-24 00:36:10 +0000 | |
| commit | 9846820b882f8741f0261b82b3c7777d73cd7942 (patch) | |
| tree | c6148b8c685eba6f274c06516b1f3a2043b166fe | |
| parent | aa97cd9d2de38cf9223dac6ff259848e30114a6e (diff) | |
[pm/archive] align draft session's icon overlay state with the current
launcher
The draft session's app icon is displayed at the beginning of the
unarchiving. Adapt its style to match the cloud icon overlay style of
the current launcher to avoid UI flickering.
BUG: 350758155
Test: manual
Test: atest android.content.pm.cts.PackageInstallerArchiveTest#archiveApp_getApplicationIcon_draftSessionOverlayDisabledIfLauncherOverlayDisabled
Change-Id: I37e553e0f144ff0b3cc86dafae8d857f1b6fcf24
Flag: EXEMPT bugfix
| -rw-r--r-- | services/core/java/com/android/server/pm/PackageArchiver.java | 43 |
1 files changed, 35 insertions, 8 deletions
diff --git a/services/core/java/com/android/server/pm/PackageArchiver.java b/services/core/java/com/android/server/pm/PackageArchiver.java index 6b7b702b9157..5e45b4c2d5af 100644 --- a/services/core/java/com/android/server/pm/PackageArchiver.java +++ b/services/core/java/com/android/server/pm/PackageArchiver.java @@ -869,18 +869,25 @@ public class PackageArchiver { private int createDraftSession(String packageName, String installerPackage, String callerPackageName, IntentSender statusReceiver, int userId) throws IOException { + Computer snapshot = mPm.snapshotComputer(); PackageInstaller.SessionParams sessionParams = new PackageInstaller.SessionParams( PackageInstaller.SessionParams.MODE_FULL_INSTALL); sessionParams.setAppPackageName(packageName); sessionParams.setAppLabel( mContext.getString(com.android.internal.R.string.unarchival_session_app_label)); - sessionParams.setAppIcon( - getArchivedAppIcon(packageName, UserHandle.of(userId), callerPackageName)); + // The draft session's app icon is based on the current launcher's icon overlay appops mode + String launcherPackageName = getCurrentLauncherPackageName(userId); + int launcherUid = launcherPackageName != null + ? snapshot.getPackageUid(launcherPackageName, 0, userId) + : Process.SYSTEM_UID; + sessionParams.setAppIcon(getArchivedAppIcon(packageName, UserHandle.of(userId), + isOverlayEnabled(launcherUid, + launcherPackageName == null ? callerPackageName : launcherPackageName))); // To make sure SessionInfo::isUnarchival returns true for draft sessions, // INSTALL_UNARCHIVE is also set. sessionParams.installFlags = (INSTALL_UNARCHIVE_DRAFT | INSTALL_UNARCHIVE); - int installerUid = mPm.snapshotComputer().getPackageUid(installerPackage, 0, userId); + int installerUid = snapshot.getPackageUid(installerPackage, 0, userId); // Handles case of repeated unarchival calls for the same package. int existingSessionId = mPm.mInstallerService.getExistingDraftSessionId(installerUid, sessionParams, @@ -926,12 +933,27 @@ public class PackageArchiver { /** * Returns the icon of an archived app. This is the icon of the main activity of the app. * - * <p> The icon is returned without any treatment/overlay. In the rare case the app had multiple - * launcher activities, only one of the icons is returned arbitrarily. + * <p> In the rare case the app had multiple launcher activities, only one of the icons is + * returned arbitrarily. + * + * <p> By default, the icon will be overlay'd with a cloud icon on top. A launcher app can + * disable the cloud overlay via the + * {@link LauncherApps.ArchiveCompatibilityParams#setEnableIconOverlay(boolean)} API. + * The default launcher's cloud overlay mode determines the cloud overlay status returned by + * any other callers. That is, if the current launcher has the cloud overlay disabled, any other + * app that fetches the app icon will also get an icon that has the cloud overlay disabled. + * This is to prevent style mismatch caused by icons that are fetched by different callers. */ @Nullable public Bitmap getArchivedAppIcon(@NonNull String packageName, @NonNull UserHandle user, String callingPackageName) { + return getArchivedAppIcon(packageName, user, + isOverlayEnabled(Binder.getCallingUid(), callingPackageName)); + } + + @Nullable + private Bitmap getArchivedAppIcon(@NonNull String packageName, @NonNull UserHandle user, + boolean isOverlayEnabled) { Objects.requireNonNull(packageName); Objects.requireNonNull(user); @@ -955,14 +977,19 @@ public class PackageArchiver { // In the rare case the archived app defined more than two launcher activities, we choose // the first one arbitrarily. Bitmap icon = decodeIcon(archiveState.getActivityInfos().get(0)); - if (icon != null && getAppOpsManager().checkOp( - AppOpsManager.OP_ARCHIVE_ICON_OVERLAY, callingUid, callingPackageName) - == MODE_ALLOWED) { + + if (icon != null && isOverlayEnabled) { icon = includeCloudOverlay(icon); } return icon; } + private boolean isOverlayEnabled(int callingUid, String packageName) { + return getAppOpsManager().checkOp( + AppOpsManager.OP_ARCHIVE_ICON_OVERLAY, callingUid, packageName) + == MODE_ALLOWED; + } + /** * This method first checks the ArchiveState for the provided userId and then tries to fallback * to other users if the current user is not archived. |