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

Commit 41f253e6 authored by Jay Aliomer's avatar Jay Aliomer Committed by Android (Google) Code Review
Browse files

Merge "Implment local color extraction for image wallpapers" into sc-dev

parents 56a4ea56 ef842426
Loading
Loading
Loading
Loading
+91 −4
Original line number Diff line number Diff line
@@ -25,9 +25,12 @@ import android.os.HandlerThread;
import android.os.SystemClock;
import android.os.Trace;
import android.service.wallpaper.WallpaperService;
import android.util.ArraySet;
import android.util.Log;
import android.util.MathUtils;
import android.util.Size;
import android.view.SurfaceHolder;
import android.view.WindowManager;

import androidx.annotation.NonNull;

@@ -54,7 +57,10 @@ public class ImageWallpaper extends WallpaperService {
    private static final @android.annotation.NonNull RectF LOCAL_COLOR_BOUNDS =
            new RectF(0, 0, 1, 1);
    private static final boolean DEBUG = false;
    private ArrayList<RectF> mLocalColorsToAdd = new ArrayList<>();
    private final ArrayList<RectF> mLocalColorsToAdd = new ArrayList<>();
    private final ArraySet<RectF> mColorAreas = new ArraySet<>();
    private float mShift;
    private volatile int mPages;
    private HandlerThread mWorker;
    // scaled down version
    private Bitmap mMiniBitmap;
@@ -96,6 +102,10 @@ public class ImageWallpaper extends WallpaperService {
        private EglHelper mEglHelper;
        private final Runnable mFinishRenderingTask = this::finishRendering;
        private boolean mNeedRedraw;
        private int mWidth = 1;
        private int mHeight = 1;
        private int mImgWidth = 1;
        private int mImgHeight = 1;

        GLEngine() {
        }
@@ -111,8 +121,13 @@ public class ImageWallpaper extends WallpaperService {
            // Deferred init renderer because we need to get wallpaper by display context.
            mRenderer = getRendererInstance();
            setFixedSizeAllowed(true);
            setOffsetNotificationsEnabled(false);
            updateSurfaceSize();
            Rect window = getDisplayContext()
                    .getSystemService(WindowManager.class)
                    .getCurrentWindowMetrics()
                    .getBounds();
            mHeight = window.height();
            mWidth = window.width();
            mMiniBitmap = null;
            if (mWorker != null && mWorker.getThreadHandler() != null) {
                mWorker.getThreadHandler().post(this::updateMiniBitmap);
@@ -127,6 +142,41 @@ public class ImageWallpaper extends WallpaperService {
            return new ImageWallpaperRenderer(getDisplayContext());
        }

        @Override
        public void onOffsetsChanged(float xOffset, float yOffset,
                float xOffsetStep, float yOffsetStep,
                int xPixelOffset, int yPixelOffset) {
            if (mMiniBitmap == null || mMiniBitmap.isRecycled()) return;
            final int pages;
            if (xOffsetStep > 0 && xOffsetStep <= 1) {
                pages = (int) (1 / xOffsetStep + 1);
            } else {
                pages = 1;
            }
            if (pages == mPages) return;
            mPages = pages;
            updateShift();
            mWorker.getThreadHandler().post(() ->
                    computeAndNotifyLocalColors(new ArrayList<>(mColorAreas), mMiniBitmap));
        }

        private void updateShift() {
            if (mImgHeight == 0) {
                mShift = 0;
                return;
            }
            // calculate shift
            float imgWidth = (float) mImgWidth / (float) mImgHeight;
            float displayWidth =
                    (float) mWidth / (float) mHeight;
            // if need to shift
            if (imgWidth > displayWidth) {
                mShift = imgWidth / imgWidth - displayWidth / imgWidth;
            } else {
                mShift = 0;
            }
        }

        private void updateMiniBitmap() {
            mRenderer.useBitmap(b -> {
                int size = Math.min(b.getWidth(), b.getHeight());
@@ -134,6 +184,8 @@ public class ImageWallpaper extends WallpaperService {
                if (size > MIN_SURFACE_WIDTH) {
                    scale = (float) MIN_SURFACE_WIDTH / (float) size;
                }
                mImgHeight = b.getHeight();
                mImgWidth = b.getWidth();
                mMiniBitmap = Bitmap.createScaledBitmap(b, Math.round(scale * b.getWidth()),
                        Math.round(scale * b.getHeight()), false);
                computeAndNotifyLocalColors(mLocalColorsToAdd, mMiniBitmap);
@@ -173,6 +225,9 @@ public class ImageWallpaper extends WallpaperService {
        @Override
        public void addLocalColorsAreas(@NonNull List<RectF> regions) {
            mWorker.getThreadHandler().post(() -> {
                if (mColorAreas.size() + mLocalColorsToAdd.size() == 0) {
                    setOffsetNotificationsEnabled(true);
                }
                Bitmap bitmap = mMiniBitmap;
                if (bitmap == null) {
                    mLocalColorsToAdd.addAll(regions);
@@ -184,6 +239,7 @@ public class ImageWallpaper extends WallpaperService {

        private void computeAndNotifyLocalColors(@NonNull List<RectF> regions, Bitmap b) {
            List<WallpaperColors> colors = getLocalWallpaperColors(regions, b);
            mColorAreas.addAll(regions);
            try {
                notifyLocalColorsChanged(regions, colors);
            } catch (RuntimeException e) {
@@ -193,14 +249,45 @@ public class ImageWallpaper extends WallpaperService {

        @Override
        public void removeLocalColorsAreas(@NonNull List<RectF> regions) {
            // No-OP
            mWorker.getThreadHandler().post(() -> {
                mColorAreas.removeAll(regions);
                mLocalColorsToAdd.removeAll(regions);
                if (mColorAreas.size() + mLocalColorsToAdd.size() == 0) {
                    setOffsetNotificationsEnabled(false);
                }
            });
        }

        private RectF pageToImgRect(RectF area) {
            float pageWidth = 1f / (float) mPages;
            if (pageWidth < 1 && pageWidth >= 0) pageWidth = 1;
            float imgWidth = (float) mImgWidth / (float) mImgHeight;
            float displayWidth =
                    (float) mWidth / (float) mHeight;
            float expansion = imgWidth > displayWidth ? displayWidth / imgWidth : 1;
            int page = (int) Math.floor(area.centerX() / pageWidth);
            float shiftWidth = mShift * page * pageWidth;
            RectF imgArea = new RectF();
            imgArea.bottom = area.bottom;
            imgArea.top = area.top;
            imgArea.left = MathUtils.constrain(area.left % pageWidth, 0, 1)
                    * expansion + shiftWidth;
            imgArea.right = MathUtils.constrain(area.right % pageWidth, 0, 1)
                    * expansion + shiftWidth;
            if (imgArea.left > imgArea.right) {
                // take full page
                imgArea.left = shiftWidth;
                imgArea.right = 1 - (mShift - shiftWidth);
            }
            return imgArea;
        }

        private List<WallpaperColors> getLocalWallpaperColors(@NonNull List<RectF> areas,
                Bitmap b) {
            List<WallpaperColors> colors = new ArrayList<>(areas.size());
            updateShift();
            for (int i = 0; i < areas.size(); i++) {
                RectF area = areas.get(i);
                RectF area = pageToImgRect(areas.get(i));
                if (area == null || !LOCAL_COLOR_BOUNDS.contains(area)) {
                    colors.add(null);
                    continue;