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

Commit 1e476595 authored by Aurélien Pomini's avatar Aurélien Pomini
Browse files

Fix getBitmapCrops(..., originalBitmap = true) API

Previous computation would compute the crops for the cropped bitmap,
then rescale them for the original bitmap via some getOriginalCropHints
method. However this is not great, if the sample size is large (e.g. 2),
the rounding errors from the cropped bitmaps will be multiplied and can
exceed 1, resulting in 2px rounding error for some tests on TV.

WallpaperManager CTS expects an error of at most 1px.

In the worst cases, getBitmapCrops could return a crop larger than the
original bitmap, which shouldn't happen after this CL.

Flag: android.app.fix_get_bitmap_crops
Bug: 384502688
Test: manual with logs
Test: atest WallpaperManagerTest

Change-Id: I8c0ed5c2f6fc864fa8ad0adab5c240b195423b4f
parent 30f98626
Loading
Loading
Loading
Loading
+23 −7
Original line number Diff line number Diff line
@@ -369,18 +369,34 @@ public class WallpaperCropper {
    }

    /**
     * The crops stored in {@link WallpaperData#mCropHints} are relative to the original image.
     * This computes the crops relative to the sub-image that will actually be rendered on a window.
     * @see #getRelativeCropHints(WallpaperData, boolean)
     */
    static SparseArray<Rect> getRelativeCropHints(WallpaperData wallpaper) {
        return getRelativeCropHints(wallpaper, false);
    }

    /**
     * The crops stored in {@link WallpaperData#mCropHints} are relative to the original image
     * {@link WallpaperData#getWallpaperFile()}. Compute crops hints relative to the cropped image.
     *
     * @param ignoreSampleSize If true, do not divide crops by {@link WallpaperData#mSampleSize}.
     *                        The resulting crops will be relative to the global crop defined by
     *                        {@link WallpaperData#cropHint}.
     *                         If false, the resulting crops will be relative to the cropped image
     *                         {@link WallpaperData#getCropFile()}.
     */
    static SparseArray<Rect> getRelativeCropHints(WallpaperData wallpaper,
            boolean ignoreSampleSize) {
        SparseArray<Rect> result = new SparseArray<>();
        for (int i = 0; i < wallpaper.mCropHints.size(); i++) {
            Rect adjustedRect = new Rect(wallpaper.mCropHints.valueAt(i));
            adjustedRect.offset(-wallpaper.cropHint.left, -wallpaper.cropHint.top);
            if (!ignoreSampleSize) {
                adjustedRect.left = (int) (0.5f + adjustedRect.left / wallpaper.mSampleSize);
                adjustedRect.top = (int) (0.5f + adjustedRect.top / wallpaper.mSampleSize);
                adjustedRect.right = (int) Math.floor(adjustedRect.right / wallpaper.mSampleSize);
                adjustedRect.bottom = (int) Math.floor(adjustedRect.bottom / wallpaper.mSampleSize);
            }

            result.put(wallpaper.mCropHints.keyAt(i), adjustedRect);
        }
@@ -388,7 +404,7 @@ public class WallpaperCropper {
    }

    /**
     * Inverse operation of {@link #getRelativeCropHints}
     * Inverse operation of {@link #getRelativeCropHints(WallpaperData)}
     */
    static List<Rect> getOriginalCropHints(
            WallpaperData wallpaper, List<Rect> relativeCropHints) {
+21 −7
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL;
import static android.Manifest.permission.MANAGE_EXTERNAL_STORAGE;
import static android.Manifest.permission.READ_WALLPAPER_INTERNAL;
import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
import static android.app.Flags.fixGetBitmapCrops;
import static android.app.Flags.fixWallpaperChanged;
import static android.app.Flags.liveWallpaperContentHandling;
import static android.app.Flags.notifyKeyguardEvents;
@@ -2519,9 +2520,12 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
            if (wallpaper == null || !mImageWallpaper.equals(wallpaper.getComponent())) {
                return null;
            }
            SparseArray<Rect> relativeCropHints =
                    WallpaperCropper.getRelativeCropHints(wallpaper);
            Point relativeCropSize = new Point(

            SparseArray<Rect> relativeCropHints = WallpaperCropper.getRelativeCropHints(
                    wallpaper, fixGetBitmapCrops() && originalBitmap);
            Point relativeCropSize = (fixGetBitmapCrops() && originalBitmap)
                    ? new Point(wallpaper.cropHint.width(), wallpaper.cropHint.height())
                    : new Point(
                            (int) Math.ceil(wallpaper.cropHint.width() / wallpaper.mSampleSize),
                            (int) Math.ceil(wallpaper.cropHint.height() / wallpaper.mSampleSize));
            if (relativeCropSize.equals(0, 0)) {
@@ -2544,11 +2548,21 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
                    == View.LAYOUT_DIRECTION_RTL;
            WallpaperDefaultDisplayInfo defaultDisplayInfo =
                    mWallpaperDisplayHelper.getDefaultDisplayInfo();
            SparseArray<Rect> cropHints = fixGetBitmapCrops()
                    ? relativeCropHints
                    : adjustedRelativeSuggestedCrops;
            for (Point displaySize : displaySizes) {
                result.add(WallpaperCropper.getCrop(displaySize, defaultDisplayInfo,
                        relativeCropSize, adjustedRelativeSuggestedCrops, rtl));
                        relativeCropSize, cropHints, rtl));
            }
            if (originalBitmap) {
                if (fixGetBitmapCrops()) {
                    result.forEach(crop ->
                            crop.offset(wallpaper.cropHint.left, wallpaper.cropHint.top));
                } else {
                    result = WallpaperCropper.getOriginalCropHints(wallpaper, result);
                }
            }
            if (originalBitmap) result = WallpaperCropper.getOriginalCropHints(wallpaper, result);
            return result;
        }
    }