Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4ec6c0ea authored by Chris Poultney's avatar Chris Poultney
Browse files

Persist WallpaperDescription for static wallpapers

Bug: 380245309
Bug: 395679036
Bug: 421242090
Flag: android.app.update_recents_from_system
Test: cannot test with CTS tests per b/421242090
Test: manually tested persisting and missing id creation
Change-Id: Ieb6d46c67ff5d0ae0e67ac60671ba5ad3c5a8dfb
parent 2fecc801
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -72,6 +72,10 @@ interface IWallpaperManager {
    @UnsupportedAppUsage
    void setWallpaperComponent(in ComponentName name);

    /**
     * Sets the ID field in WallpaperDescription for the current wallpaper for the given screen.
     */
    void setWallpaperDescriptionId(in String newId, int which, int userId);

    /**
     * @deprecated Use {@link #getWallpaperWithFeature(String, IWallpaperManagerCallback, int,
+76 −1
Original line number Diff line number Diff line
@@ -2144,19 +2144,94 @@ public class WallpaperManager {
    @RequiresPermission(READ_WALLPAPER_INTERNAL)
    @SystemApi
    public WallpaperInstance getWallpaperInstance(@SetWallpaperFlags int which) {
        return getWallpaperInstance(which, false);
    }

    /**
     * Returns the description of the designated wallpaper. Returns null if the lock screen
     * wallpaper is requested and lock screen wallpaper is not set.
     *
     * @param which           Specifies wallpaper to request (home or lock).
     * @param createMissingId If an image wallpaper has no id and this is true, block to
     *                        calculate a new id and update the stored WallpaperInfo with it
     * @throws IllegalArgumentException if {@code which} is not exactly one of
     *                                  {{@link #FLAG_SYSTEM},{@link #FLAG_LOCK}}.
     * @hide
     */
    @Nullable
    @FlaggedApi(FLAG_LIVE_WALLPAPER_CONTENT_HANDLING)
    @RequiresPermission(READ_WALLPAPER_INTERNAL)
    public WallpaperInstance getWallpaperInstance(@SetWallpaperFlags int which,
            boolean createMissingId) {
        checkExactlyOneWallpaperFlagSet(which);
        try {
            if (sGlobals.mService == null) {
                Log.w(TAG, "WallpaperService not running");
                throw new RuntimeException(new DeadSystemException());
            } else {
                return sGlobals.mService.getWallpaperInstance(which, mContext.getUserId());
                WallpaperInstance instance = sGlobals.mService.getWallpaperInstance(which,
                        mContext.getUserId());
                boolean isStaticWithoutId =
                        (instance != null && instance.getInfo() == null && instance.getId().equals(
                                WallpaperInstance.DEFAULT_ID));
                if (isStaticWithoutId && createMissingId) {
                    Bitmap bitmap = null;
                    ParcelFileDescriptor fd = getWallpaperFile(which, false);
                    if (fd != null) {
                        try (FileInputStream fileStream = new FileInputStream(
                                fd.getFileDescriptor())) {
                            bitmap = BitmapFactory.decodeStream(fileStream);
                        } catch (IOException e) {
                            Log.e(TAG, "Error closing file stream when calculating hash", e);
                        } finally {
                            try {
                                fd.close();
                            } catch (IOException e) {
                                Log.e(TAG, "Error closing file description when calculating hash",
                                        e);
                            }
                        }
                    } else {
                        Drawable drawable = peekDrawable(which);
                        if (drawable instanceof BitmapDrawable bd && bd.getBitmap() != null) {
                            bitmap = bd.getBitmap();
                        }
                    }
                    if (bitmap != null) {
                        String newId = String.valueOf(generateHashCode(bitmap));
                        sGlobals.mService.setWallpaperDescriptionId(newId, which,
                                mContext.getUserId());
                        instance = sGlobals.mService.getWallpaperInstance(which,
                                mContext.getUserId());
                    }
                }
                return instance;
            }
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    // TODO(b/421366650) Find a better place for this method.
    static long generateHashCode(Bitmap bitmap) {
        long result = 17;

        int width = bitmap.getWidth();
        int height = bitmap.getHeight();

        result = 31 * result + width;
        result = 31 * result + height;

        // Traverse pixels exponentially so that hash code generation scales well with large images.
        for (int x = 0; x < width; x = x * 2 + 1) {
            for (int y = 0; y < height; y = y * 2 + 1) {
                result = 31 * result + bitmap.getPixel(x, y);
            }
        }

        return result;
    }

    /**
     * Get an open, readable file descriptor for the file that contains metadata about the
     * context user's wallpaper.
+7 −1
Original line number Diff line number Diff line
@@ -43,7 +43,13 @@ import java.util.Objects;
 */
@FlaggedApi(FLAG_LIVE_WALLPAPER_CONTENT_HANDLING)
public final class WallpaperInstance implements Parcelable {
    private static final String DEFAULT_ID = "default_id";
    /**
     * Default id to use when none is provided.
     *
     * @hide
     */
    public static final String DEFAULT_ID = "default_id";

    @Nullable private final WallpaperInfo mInfo;
    @NonNull private final WallpaperDescription mDescription;
    @Nullable private final String mIdOverride;
+9 −1
Original line number Diff line number Diff line
@@ -47,10 +47,18 @@ class WallpaperData {

    final int userId;

    /**
     * Description of the static wallpaper in the process of being applied. This is set when
     * starting the process of applying a static wallpaper and cleared after it's successfully done.
     */
    WallpaperDescription mPendingStaticDescription = null;

    /**
     * True while the client is writing a new wallpaper
     */
    boolean imageWallpaperPending;
    boolean imageWallpaperPending() {
        return mPendingStaticDescription != null;
    }

    /**
     * Which wallpaper is set. Flag values are from {@link SetWallpaperFlags}.
+42 −8
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@ import static android.app.Flags.fixWallpaperChanged;
import static android.app.Flags.liveWallpaperContentHandling;
import static android.app.Flags.notifyKeyguardEvents;
import static android.app.Flags.removeNextWallpaperComponent;
import static android.app.Flags.updateRecentsFromSystem;
import static android.app.WallpaperManager.COMMAND_REAPPLY;
import static android.app.WallpaperManager.FLAG_LOCK;
import static android.app.WallpaperManager.FLAG_SYSTEM;
@@ -288,7 +289,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
            final boolean isAppliedToLock = (wallpaper.mWhich & FLAG_LOCK) != 0;
            final boolean needsUpdate = wallpaper.getComponent() == null
                    || event != CLOSE_WRITE // includes the MOVED_TO case
                    || wallpaper.imageWallpaperPending;
                    || wallpaper.imageWallpaperPending();

            if (isMigration) {
                // When separate lock screen engine is supported, migration will be handled by
@@ -304,7 +305,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
                        + " path=" + path
                        + " sys=" + sysWallpaperChanged
                        + " lock=" + lockWallpaperChanged
                        + " imagePending=" + wallpaper.imageWallpaperPending
                        + " imagePending=" + wallpaper.imageWallpaperPending()
                        + " mWhich=0x" + Integer.toHexString(wallpaper.mWhich)
                        + " written=" + written
                        + " isMigration=" + isMigration
@@ -347,7 +348,15 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
                if (DEBUG) {
                    Slog.v(TAG, "Crop done; invoking completion callback");
                }
                wallpaper.imageWallpaperPending = false;
                WallpaperDescription description;
                if (wallpaper.mPendingStaticDescription != null) {
                    description = wallpaper.mPendingStaticDescription.toBuilder()
                            .setComponent(mImageWallpaper).build();
                } else {
                    description = new WallpaperDescription.Builder().setComponent(
                            mImageWallpaper).build();
                }
                wallpaper.mPendingStaticDescription = null;

                if (sysWallpaperChanged) {
                    if (DEBUG) {
@@ -368,7 +377,13 @@ public class WallpaperManagerService extends IWallpaperManager.Stub

                    // If this was the system wallpaper, rebind...
                    wallpaper.mBindSource = BindSource.SET_STATIC;
                    bindWallpaperComponentLocked(mImageWallpaper, true, false, wallpaper, callback);
                    if (updateRecentsFromSystem()) {
                        bindWallpaperDescriptionLocked(description, /* force= */ true,
                                /* fromUser= */ false, wallpaper, callback);
                    } else {
                        bindWallpaperComponentLocked(mImageWallpaper, /* force= */ true,
                                /* fromUser= */ false, wallpaper, callback);
                    }
                }

                if (lockWallpaperChanged) {
@@ -390,8 +405,13 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
                    };

                    wallpaper.mBindSource = BindSource.SET_STATIC;
                    bindWallpaperComponentLocked(mImageWallpaper, true /* force */,
                            false /* fromUser */, wallpaper, callback);
                    if (updateRecentsFromSystem()) {
                        bindWallpaperDescriptionLocked(description, /* force= */ true,
                                /* fromUser= */ false, wallpaper, callback);
                    } else {
                        bindWallpaperComponentLocked(mImageWallpaper, /* force= */ true,
                                /* fromUser= */ false, wallpaper, callback);
                    }
                } else if (isAppliedToLock) {
                    // This is system-plus-lock: we need to wipe the lock bookkeeping since
                    // we're falling back to displaying the system wallpaper there.
@@ -2712,6 +2732,20 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
        }
    }

    @Override
    public void setWallpaperDescriptionId(String newId, int which, int userId) {
        if (!updateRecentsFromSystem()) return;
        synchronized (mLock) {
            WallpaperData wallpaper = (which == FLAG_LOCK) ? mLockWallpaperMap.get(userId)
                    : mWallpaperMap.get(userId);
            if (wallpaper != null) {
                wallpaper.setDescription(
                        wallpaper.getDescription().toBuilder().setId(newId).build());
                Slog.i(TAG, "Set description id for " + which + ": " + newId);
            }
        }
    }

    @Override
    public ParcelFileDescriptor getWallpaperInfoFile(int userId) {
        synchronized (mLock) {
@@ -3346,7 +3380,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
            try {
                ParcelFileDescriptor pfd = updateWallpaperBitmapLocked(name, wallpaper, extras);
                if (pfd != null) {
                    wallpaper.imageWallpaperPending = true;
                    wallpaper.mPendingStaticDescription = description;
                    wallpaper.mSystemWasBoth = systemIsBoth;
                    wallpaper.mWhich = which;
                    wallpaper.setComplete = completion;
@@ -3551,7 +3585,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
            final long ident = Binder.clearCallingIdentity();

            try {
                newWallpaper.imageWallpaperPending = false;
                newWallpaper.mPendingStaticDescription = null;
                newWallpaper.mWhich = which;
                newWallpaper.mSystemWasBoth = systemIsBoth;
                newWallpaper.fromForegroundApp = fromForeground;