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

Commit d4e11c9a authored by Chris Poultney's avatar Chris Poultney
Browse files

Use WallpaperDescription crops for static wallpapers

We have two ways to set static wallpapers with crop hints: one takes
crop hints as one or two arguments, and the other takes a
WallpaperDescription. Before this change, the description methods just
used the crop hints in the description and passed them to the crop hints
methods. The change makes the WallpaperDescription methods the main
ones, with the crop hint methods creating a WallpaperDescription and
calling them.

This is the first step to setting static wallpapers with
WallpaperDescription and storing the description on the framework side.

Bug: 380245309
Bug: 395679036
Flag: EXEMPT refactor
Test: CTS tests
Test: manually verified cropping behavior
Change-Id: If1352733d9da0fe7d63dca3a2f45a852606e29e3
parent ae575cd7
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -57,8 +57,8 @@ interface IWallpaperManager {
     */
    @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.SET_WALLPAPER)")
    ParcelFileDescriptor setWallpaper(String name, in String callingPackage,
            in int[] screenOrientations, in List<Rect> crops, boolean allowBackup,
            out Bundle extras, int which, IWallpaperManagerCallback completion, int userId);
            in WallpaperDescription description, boolean allowBackup, out Bundle extras, int which,
            IWallpaperManagerCallback completion, int userId);

    /**
     * Set the live wallpaper.
+77 −77
Original line number Diff line number Diff line
@@ -2257,11 +2257,12 @@ public class WallpaperManager {
        final WallpaperSetCompletion completion = new WallpaperSetCompletion();
        try {
            Resources resources = mContext.getResources();
            /* Set the wallpaper to the default values */
            WallpaperDescription description = new WallpaperDescription.Builder().build();
            // This code no longer executes because multiCrop() is always true. This is just so
            // that this compiles.
            ParcelFileDescriptor fd = sGlobals.mService.setWallpaper(
                    "res:" + resources.getResourceName(resid),
                    mContext.getOpPackageName(), null, null, false, result, which, completion,
                    mContext.getUserId());
                    "res:" + resources.getResourceName(resid), mContext.getOpPackageName(),
                    description, false, result, which, completion, mContext.getUserId());
            if (fd != null) {
                FileOutputStream fos = null;
                try {
@@ -2381,7 +2382,9 @@ public class WallpaperManager {
        if (multiCrop()) {
            SparseArray<Rect> cropMap = new SparseArray<>();
            if (visibleCropHint != null) cropMap.put(ORIENTATION_UNKNOWN, visibleCropHint);
            return setBitmapWithCrops(fullImage, cropMap, allowBackup, which, userId);
            WallpaperDescription description = new WallpaperDescription.Builder().setCropHints(
                    cropMap).build();
            return setBitmapWithDescription(fullImage, description, allowBackup, which, userId);
        }
        validateRect(visibleCropHint);
        if (sGlobals.mService == null) {
@@ -2392,8 +2395,11 @@ public class WallpaperManager {
        final WallpaperSetCompletion completion = new WallpaperSetCompletion();
        final List<Rect> crops = visibleCropHint == null ? null : List.of(visibleCropHint);
        try {
            // This code no longer executes because multiCrop() is always true. This is just so
            // that this compiles.
            WallpaperDescription description = new WallpaperDescription.Builder().build();
            ParcelFileDescriptor fd = sGlobals.mService.setWallpaper(null,
                    mContext.getOpPackageName(), null, crops, allowBackup, result, which,
                    mContext.getOpPackageName(), description, allowBackup, result, which,
                    completion, userId);
            if (fd != null) {
                FileOutputStream fos = null;
@@ -2427,32 +2433,48 @@ public class WallpaperManager {
    @RequiresPermission(android.Manifest.permission.SET_WALLPAPER)
    public int setBitmapWithCrops(@Nullable Bitmap fullImage, @NonNull Map<Point, Rect> cropHints,
            boolean allowBackup, @SetWallpaperFlags int which) throws IOException {
        SparseArray<Rect> crops = new SparseArray<>();
        cropHints.forEach((k, v) -> crops.put(getOrientation(k), v));
        return setBitmapWithCrops(fullImage, crops, allowBackup, which, mContext.getUserId());
        WallpaperDescription description = new WallpaperDescription.Builder().setCropHints(
                cropHints).build();
        return setBitmapWithDescription(fullImage, description, allowBackup, which,
                mContext.getUserId());
    }

    /**
     * Version of setBitmap that allows specification of wallpaper metadata including how the
     * wallpaper will be positioned for different display sizes.
     *
     * @param fullImage   A bitmap that will supply the wallpaper imagery.
     * @param description Wallpaper metadata including desired cropping
     * @param allowBackup {@code true} if the OS is permitted to back up this wallpaper
     *                    image for restore to a future device; {@code false} otherwise.
     * @param which       Flags indicating which wallpaper(s) to configure with the new imagery.
     * @hide
     */
    @FlaggedApi(FLAG_LIVE_WALLPAPER_CONTENT_HANDLING)
    @TestApi
    @RequiresPermission(android.Manifest.permission.SET_WALLPAPER)
    private int setBitmapWithCrops(@Nullable Bitmap fullImage, @NonNull SparseArray<Rect> cropHints,
            boolean allowBackup, @SetWallpaperFlags int which, int userId) throws IOException {
    public int setBitmapWithDescription(@Nullable Bitmap fullImage,
            @NonNull WallpaperDescription description, boolean allowBackup,
            @SetWallpaperFlags int which) throws IOException {
        return setBitmapWithDescription(fullImage, description, allowBackup, which,
                mContext.getUserId());
    }

    private int setBitmapWithDescription(@Nullable Bitmap fullImage,
            @NonNull WallpaperDescription description, boolean allowBackup,
            @SetWallpaperFlags int which, int userId) throws IOException {
        if (sGlobals.mService == null) {
            Log.w(TAG, "WallpaperService not running");
            throw new RuntimeException(new DeadSystemException());
        }
        int size = cropHints.size();
        int[] screenOrientations = new int[size];
        List<Rect> crops = new ArrayList<>(size);
        for (int i = 0; i < size; i++) {
            screenOrientations[i] = cropHints.keyAt(i);
            Rect cropHint = cropHints.valueAt(i);
            validateRect(cropHint);
            crops.add(cropHint);
        for (int i = 0; i < description.getCropHints().size(); i++) {
            validateRect(description.getCropHints().valueAt(i));
        }
        final Bundle result = new Bundle();
        final WallpaperSetCompletion completion = new WallpaperSetCompletion();
        try {
            ParcelFileDescriptor fd = sGlobals.mService.setWallpaper(null,
                    mContext.getOpPackageName(), screenOrientations, crops, allowBackup,
                    mContext.getOpPackageName(), description, allowBackup,
                    result, which, completion, userId);
            if (fd != null) {
                FileOutputStream fos = null;
@@ -2471,27 +2493,6 @@ public class WallpaperManager {
        return result.getInt(EXTRA_NEW_WALLPAPER_ID, 0);
    }

    /**
     * Version of setBitmap that allows specification of wallpaper metadata including how the
     * wallpaper will be positioned for different display sizes.
     *
     * @param fullImage   A bitmap that will supply the wallpaper imagery.
     * @param description Wallpaper metadata including desired cropping
     * @param allowBackup {@code true} if the OS is permitted to back up this wallpaper
     *                    image for restore to a future device; {@code false} otherwise.
     * @param which       Flags indicating which wallpaper(s) to configure with the new imagery.
     * @hide
     */
    @FlaggedApi(FLAG_LIVE_WALLPAPER_CONTENT_HANDLING)
    @TestApi
    @RequiresPermission(android.Manifest.permission.SET_WALLPAPER)
    public int setBitmapWithDescription(@Nullable Bitmap fullImage,
            @NonNull WallpaperDescription description, boolean allowBackup,
            @SetWallpaperFlags int which) throws IOException {
        return setBitmapWithCrops(fullImage, description.getCropHints(), allowBackup, which,
                mContext.getUserId());
    }

    private final void validateRect(Rect rect) {
        if (rect != null && rect.isEmpty()) {
            throw new IllegalArgumentException("visibleCrop rectangle must be valid and non-empty");
@@ -2603,8 +2604,11 @@ public class WallpaperManager {
        final WallpaperSetCompletion completion = new WallpaperSetCompletion();
        final List<Rect> crops = visibleCropHint == null ? null : List.of(visibleCropHint);
        try {
            // This code no longer executes because multiCrop() is always true. This is just so
            // that this compiles.
            WallpaperDescription description = new WallpaperDescription.Builder().build();
            ParcelFileDescriptor fd = sGlobals.mService.setWallpaper(null,
                    mContext.getOpPackageName(), null, crops, allowBackup, result, which,
                    mContext.getOpPackageName(), description, allowBackup, result, which,
                    completion, mContext.getUserId());
            if (fd != null) {
                FileOutputStream fos = null;
@@ -2640,9 +2644,9 @@ public class WallpaperManager {
    public int setStreamWithCrops(@NonNull InputStream bitmapData,
            @NonNull Map<Point, Rect> cropHints, boolean allowBackup, @SetWallpaperFlags int which)
            throws IOException {
        SparseArray<Rect> crops = new SparseArray<>();
        cropHints.forEach((k, v) -> crops.put(getOrientation(k), v));
        return setStreamWithCrops(bitmapData, crops, allowBackup, which);
        WallpaperDescription description = new WallpaperDescription.Builder().setCropHints(
                cropHints).build();
        return setStreamWithDescription(bitmapData, description, allowBackup, which);
    }

    /**
@@ -2664,25 +2668,43 @@ public class WallpaperManager {
    public int setStreamWithCrops(@NonNull InputStream bitmapData,
            @NonNull SparseArray<Rect> cropHints, boolean allowBackup, @SetWallpaperFlags int which)
            throws IOException {
        WallpaperDescription description = new WallpaperDescription.Builder().setCropHints(
                cropHints).build();
        return setStreamWithDescription(bitmapData, description, allowBackup, which);
    }

    /**
     * Version of setStream that allows specification of wallpaper metadata including how the
     * wallpaper will be positioned for different display sizes.
     *
     * @param bitmapData  A stream containing the raw data to install as a wallpaper. This
     *                    data can be in any format handled by {@link BitmapRegionDecoder}.
     * @param description Wallpaper metadata including desired cropping
     * @param allowBackup {@code true} if the OS is permitted to back up this wallpaper
     *                    image for restore to a future device; {@code false} otherwise.
     * @param which       Flags indicating which wallpaper(s) to configure with the new imagery.
     * @return An integer ID assigned to the newly active wallpaper; or zero on failure.
     * @hide
     */
    @FlaggedApi(FLAG_LIVE_WALLPAPER_CONTENT_HANDLING)
    @SystemApi
    @RequiresPermission(android.Manifest.permission.SET_WALLPAPER)
    public int setStreamWithDescription(@NonNull InputStream bitmapData,
            @NonNull WallpaperDescription description, boolean allowBackup,
            @SetWallpaperFlags int which) throws IOException {
        if (sGlobals.mService == null) {
            Log.w(TAG, "WallpaperService not running");
            throw new RuntimeException(new DeadSystemException());
        }
        int size = cropHints.size();
        int[] screenOrientations = new int[size];
        List<Rect> crops = new ArrayList<>(size);
        for (int i = 0; i < size; i++) {
            screenOrientations[i] = cropHints.keyAt(i);
            Rect cropHint = cropHints.valueAt(i);
            validateRect(cropHint);
            crops.add(cropHint);
        for (int i = 0; i < description.getCropHints().size(); i++) {
            validateRect(description.getCropHints().valueAt(i));
        }
        final Bundle result = new Bundle();
        final WallpaperSetCompletion completion = new WallpaperSetCompletion();
        try {
            ParcelFileDescriptor fd = sGlobals.mService.setWallpaper(null,
                    mContext.getOpPackageName(), screenOrientations, crops, allowBackup,
                    result, which, completion, mContext.getUserId());
                    mContext.getOpPackageName(), description, allowBackup, result, which,
                    completion, mContext.getUserId());
            if (fd != null) {
                FileOutputStream fos = null;
                try {
@@ -2700,28 +2722,6 @@ public class WallpaperManager {
        return result.getInt(EXTRA_NEW_WALLPAPER_ID, 0);
    }

    /**
     * Version of setStream that allows specification of wallpaper metadata including how the
     * wallpaper will be positioned for different display sizes.
     *
     * @param bitmapData  A stream containing the raw data to install as a wallpaper. This
     *                    data can be in any format handled by {@link BitmapRegionDecoder}.
     * @param description Wallpaper metadata including desired cropping
     * @param allowBackup {@code true} if the OS is permitted to back up this wallpaper
     *                    image for restore to a future device; {@code false} otherwise.
     * @param which       Flags indicating which wallpaper(s) to configure with the new imagery.
     * @return An integer ID assigned to the newly active wallpaper; or zero on failure.
     * @hide
     */
    @FlaggedApi(FLAG_LIVE_WALLPAPER_CONTENT_HANDLING)
    @SystemApi
    @RequiresPermission(android.Manifest.permission.SET_WALLPAPER)
    public int setStreamWithDescription(@NonNull InputStream bitmapData,
            @NonNull WallpaperDescription description, boolean allowBackup,
            @SetWallpaperFlags int which) throws IOException {
        return setStreamWithCrops(bitmapData, description.getCropHints(), allowBackup, which);
    }

    /**
     * Return whether any users are currently set to use the wallpaper
     * with the given resource ID.  That is, their wallpaper has been
+37 −18
Original line number Diff line number Diff line
@@ -3248,15 +3248,24 @@ public class WallpaperManagerService extends IWallpaperManager.Stub

    @Override
    public ParcelFileDescriptor setWallpaper(String name, String callingPackage,
            int[] screenOrientations, List<Rect> crops, boolean allowBackup,
            Bundle extras, int which, IWallpaperManagerCallback completion, int userId) {
            WallpaperDescription description, boolean allowBackup, Bundle extras, int which,
            IWallpaperManagerCallback completion, int userId) {

        Slog.v(TAG, "setWallpaper: name = " + name + ", which = " + which);
        if (DEBUG) {
            List<Integer> screenOrientations = null;
            List<Rect> crops = null;
            SparseArray<Rect> cropHints = description.getCropHints();
            if (cropHints.size() > 0) {
                screenOrientations = new ArrayList<>();
                crops = new ArrayList<>();
                for (int i = 0; i < cropHints.size(); i++) {
                    screenOrientations.add(cropHints.keyAt(i));
                    crops.add(cropHints.valueAt(i));
                }
            }
            Slog.d(TAG, "setWallpaper: callingPackage = " + callingPackage
                    + ", screenOrientations = "
                    + (screenOrientations == null ? null
                            : Arrays.stream(screenOrientations).boxed().toList())
                    + ", screenOrientations = " + screenOrientations
                    + ", crops = " + crops
                    + ", allowBackup = " + allowBackup);
        }
@@ -3275,8 +3284,10 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
            return null;
        }

        SparseArray<Rect> cropMap = !multiCrop() ? null : getCropMap(screenOrientations, crops);
        Rect cropHint = multiCrop() || crops == null || crops.isEmpty() ? new Rect() : crops.get(0);
        SparseArray<Rect> cropMap = !multiCrop() ? null : description.getCropHints();
        validateCrops(cropMap);
        Rect cropHint = (multiCrop() || description.getCropHints().size() == 0) ? new Rect()
                : description.getCropHints().valueAt(0);
        final boolean fromForegroundApp = !multiCrop() ? false
                : isFromForegroundApp(callingPackage);

@@ -3343,6 +3354,22 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
        }
    }

    private void validateCrops(SparseArray<Rect> cropMap) {
        if (cropMap == null) return;
        for (int i = 0; i < cropMap.size(); i++) {
            int orientation = cropMap.keyAt(i);
            Rect crop = cropMap.get(orientation);
            int width = crop.width(), height = crop.height();
            if (width < 0 || height < 0 || crop.left < 0 || crop.top < 0) {
                throw new IllegalArgumentException("Invalid crop rect supplied: " + crop);
            }
            if (orientation == ORIENTATION_UNKNOWN && cropMap.size() > 1) {
                throw new IllegalArgumentException("Invalid crops supplied: the UNKNOWN"
                        + "screen orientation should only be used in a singleton map");
            }
        }
    }

    private SparseArray<Rect> getCropMap(int[] screenOrientations, List<Rect> crops) {
        if ((crops == null ^ screenOrientations == null)
                || (crops != null && crops.size() != screenOrientations.length)) {
@@ -3352,19 +3379,11 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
        SparseArray<Rect> cropMap = new SparseArray<>();
        if (crops != null && !crops.isEmpty()) {
            for (int i = 0; i < crops.size(); i++) {
                Rect crop = crops.get(i);
                int width = crop.width(), height = crop.height();
                if (width < 0 || height < 0 || crop.left < 0 || crop.top < 0) {
                    throw new IllegalArgumentException("Invalid crop rect supplied: " + crop);
                }
                int orientation = screenOrientations[i];
                if (orientation == ORIENTATION_UNKNOWN && crops.size() > 1) {
                    throw new IllegalArgumentException("Invalid crops supplied: the UNKNOWN"
                            + "screen orientation should only be used in a singleton map");
                }
                cropMap.put(orientation, crop);
                cropMap.put(screenOrientations[i], crops.get(i));
            }
        }
        validateCrops(cropMap);

        return cropMap;
    }