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

Commit a1b4489f authored by Ahan Wu's avatar Ahan Wu
Browse files

DO NOT MERGE Fix ImageWallpaper memory regression

Scale bitmap to fit display size leads to memory regression, this cl
removes the sacling logic and also disable wallpaper transitions when
the bitmap size is smaller than display size to avoid broken visual.
We backport the solution to Q.

Bug: 147379974
Bug: 145897588
Bug: 124838911
Test: Manually
Test: atest com.android.systemui
Test: adb shell dumpsys SurfaceFlinger, then check layer size of ImageWallpaper
Merged-In: I243274af54538fc89268c448aa2c5a95f63c7ae3
Change-Id: If348748ec453f2b35b25576181c8a144496e258c
parent 79f35238
Loading
Loading
Loading
Loading
+43 −14
Original line number Original line Diff line number Diff line
@@ -18,12 +18,14 @@ package com.android.systemui;


import android.app.ActivityManager;
import android.app.ActivityManager;
import android.content.Context;
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Rect;
import android.graphics.Rect;
import android.os.HandlerThread;
import android.os.HandlerThread;
import android.os.Trace;
import android.os.Trace;
import android.service.wallpaper.WallpaperService;
import android.service.wallpaper.WallpaperService;
import android.util.Log;
import android.util.Log;
import android.util.Size;
import android.util.Size;
import android.view.DisplayInfo;
import android.view.SurfaceHolder;
import android.view.SurfaceHolder;


import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.annotations.VisibleForTesting;
@@ -84,14 +86,19 @@ public class ImageWallpaper extends WallpaperService {
        private StatusBarStateController mController;
        private StatusBarStateController mController;
        private final Runnable mFinishRenderingTask = this::finishRendering;
        private final Runnable mFinishRenderingTask = this::finishRendering;
        private final boolean mNeedTransition;
        private final boolean mNeedTransition;
        private boolean mShouldStopTransition;
        private final boolean mIsHighEndGfx;
        private final boolean mDisplayNeedsBlanking;
        private final DisplayInfo mDisplayInfo = new DisplayInfo();
        private final Object mMonitor = new Object();
        private final Object mMonitor = new Object();
        private boolean mNeedRedraw;
        private boolean mNeedRedraw;
        // This variable can only be accessed in synchronized block.
        // This variable can only be accessed in synchronized block.
        private boolean mWaitingForRendering;
        private boolean mWaitingForRendering;


        GLEngine(Context context) {
        GLEngine(Context context) {
            mNeedTransition = ActivityManager.isHighEndGfx()
            mIsHighEndGfx = ActivityManager.isHighEndGfx();
                    && !DozeParameters.getInstance(context).getDisplayNeedsBlanking();
            mDisplayNeedsBlanking = DozeParameters.getInstance(context).getDisplayNeedsBlanking();
            mNeedTransition = mIsHighEndGfx && !mDisplayNeedsBlanking;


            // We will preserve EGL context when we are in lock screen or aod
            // We will preserve EGL context when we are in lock screen or aod
            // to avoid janking in following transition, we need to release when back to home.
            // to avoid janking in following transition, we need to release when back to home.
@@ -99,12 +106,14 @@ public class ImageWallpaper extends WallpaperService {
            if (mController != null) {
            if (mController != null) {
                mController.addCallback(this /* StateListener */);
                mController.addCallback(this /* StateListener */);
            }
            }
            mEglHelper = new EglHelper();
            mRenderer = new ImageWallpaperRenderer(context, this /* SurfaceProxy */);
        }
        }


        @Override
        @Override
        public void onCreate(SurfaceHolder surfaceHolder) {
        public void onCreate(SurfaceHolder surfaceHolder) {
            mEglHelper = new EglHelper();
            // Deferred init renderer because we need to get wallpaper by display context.
            mRenderer = new ImageWallpaperRenderer(getDisplayContext(), this /* SurfaceProxy */);
            getDisplayContext().getDisplay().getDisplayInfo(mDisplayInfo);
            setFixedSizeAllowed(true);
            setFixedSizeAllowed(true);
            setOffsetNotificationsEnabled(true);
            setOffsetNotificationsEnabled(true);
            updateSurfaceSize();
            updateSurfaceSize();
@@ -118,6 +127,26 @@ public class ImageWallpaper extends WallpaperService {
            holder.setFixedSize(width, height);
            holder.setFixedSize(width, height);
        }
        }


        /**
         * Check if necessary to stop transition with current wallpaper on this device. <br/>
         * This should only be invoked after {@link #onSurfaceCreated(SurfaceHolder)}}
         * is invoked since it needs display context and surface frame size.
         *
         * @return true if need to stop transition
         */
        @VisibleForTesting
        boolean checkIfShouldStopTransition() {
            int orientation = getDisplayContext().getResources().getConfiguration().orientation;
            boolean portrait = orientation == Configuration.ORIENTATION_PORTRAIT;
            Rect frame = getSurfaceHolder().getSurfaceFrame();
            int frameWidth = frame.width();
            int frameHeight = frame.height();
            int displayWidth = portrait ? mDisplayInfo.logicalWidth : mDisplayInfo.logicalHeight;
            int displayHeight = portrait ? mDisplayInfo.logicalHeight : mDisplayInfo.logicalWidth;
            return mNeedTransition
                    && (frameWidth < displayWidth || frameHeight < displayHeight);
        }

        @Override
        @Override
        public void onOffsetsChanged(float xOffset, float yOffset, float xOffsetStep,
        public void onOffsetsChanged(float xOffset, float yOffset, float xOffsetStep,
                float yOffsetStep, int xPixelOffset, int yPixelOffset) {
                float yOffsetStep, int xPixelOffset, int yPixelOffset) {
@@ -128,12 +157,14 @@ public class ImageWallpaper extends WallpaperService {
        @Override
        @Override
        public void onAmbientModeChanged(boolean inAmbientMode, long animationDuration) {
        public void onAmbientModeChanged(boolean inAmbientMode, long animationDuration) {
            if (mWorker == null || !mNeedTransition) return;
            if (mWorker == null || !mNeedTransition) return;
            final long duration = mShouldStopTransition ? 0 : animationDuration;
            if (DEBUG) {
            if (DEBUG) {
                Log.d(TAG, "onAmbientModeChanged: inAmbient=" + inAmbientMode
                Log.d(TAG, "onAmbientModeChanged: inAmbient=" + inAmbientMode
                        + ", duration=" + animationDuration);
                        + ", duration=" + duration
                        + ", mShouldStopTransition=" + mShouldStopTransition);
            }
            }
            mWorker.getThreadHandler().post(
            mWorker.getThreadHandler().post(
                    () -> mRenderer.updateAmbientMode(inAmbientMode, animationDuration));
                    () -> mRenderer.updateAmbientMode(inAmbientMode, duration));
            if (inAmbientMode && animationDuration == 0) {
            if (inAmbientMode && animationDuration == 0) {
                // This means that we are transiting from home to aod, to avoid
                // This means that we are transiting from home to aod, to avoid
                // race condition between window visibility and transition,
                // race condition between window visibility and transition,
@@ -169,13 +200,13 @@ public class ImageWallpaper extends WallpaperService {
                mRenderer = null;
                mRenderer = null;
                mEglHelper.finish();
                mEglHelper.finish();
                mEglHelper = null;
                mEglHelper = null;
                getSurfaceHolder().getSurface().hwuiDestroy();
            });
            });
        }
        }


        @Override
        @Override
        public void onSurfaceCreated(SurfaceHolder holder) {
        public void onSurfaceCreated(SurfaceHolder holder) {
            if (mWorker == null) return;
            if (mWorker == null) return;
            mShouldStopTransition = checkIfShouldStopTransition();
            mWorker.getThreadHandler().post(() -> {
            mWorker.getThreadHandler().post(() -> {
                mEglHelper.init(holder);
                mEglHelper.init(holder);
                mRenderer.onSurfaceCreated();
                mRenderer.onSurfaceCreated();
@@ -365,15 +396,13 @@ public class ImageWallpaper extends WallpaperService {
        protected void dump(String prefix, FileDescriptor fd, PrintWriter out, String[] args) {
        protected void dump(String prefix, FileDescriptor fd, PrintWriter out, String[] args) {
            super.dump(prefix, fd, out, args);
            super.dump(prefix, fd, out, args);
            out.print(prefix); out.print("Engine="); out.println(this);
            out.print(prefix); out.print("Engine="); out.println(this);

            out.print(prefix); out.print("isHighEndGfx="); out.println(mIsHighEndGfx);
            boolean isHighEndGfx = ActivityManager.isHighEndGfx();
            out.print(prefix); out.print("isHighEndGfx="); out.println(isHighEndGfx);

            DozeParameters dozeParameters = DozeParameters.getInstance(getApplicationContext());
            out.print(prefix); out.print("displayNeedsBlanking=");
            out.print(prefix); out.print("displayNeedsBlanking=");
            out.println(dozeParameters != null ? dozeParameters.getDisplayNeedsBlanking() : "null");
            out.println(mDisplayNeedsBlanking);

            out.print(prefix); out.print("displayInfo="); out.print(mDisplayInfo);
            out.print(prefix); out.print("mNeedTransition="); out.println(mNeedTransition);
            out.print(prefix); out.print("mNeedTransition="); out.println(mNeedTransition);
            out.print(prefix); out.print("mShouldStopTransition=");
            out.println(mShouldStopTransition);
            out.print(prefix); out.print("StatusBarState=");
            out.print(prefix); out.print("StatusBarState=");
            out.println(mController != null ? mController.getState() : "null");
            out.println(mController != null ? mController.getState() : "null");


+2 −9
Original line number Original line Diff line number Diff line
@@ -31,7 +31,6 @@ import android.util.Log;
import android.util.MathUtils;
import android.util.MathUtils;
import android.util.Size;
import android.util.Size;
import android.view.DisplayInfo;
import android.view.DisplayInfo;
import android.view.WindowManager;


import com.android.systemui.R;
import com.android.systemui.R;


@@ -70,8 +69,7 @@ public class ImageWallpaperRenderer implements GLWallpaperRenderer,
        }
        }


        DisplayInfo displayInfo = new DisplayInfo();
        DisplayInfo displayInfo = new DisplayInfo();
        WindowManager wm = context.getSystemService(WindowManager.class);
        context.getDisplay().getDisplayInfo(displayInfo);
        wm.getDefaultDisplay().getDisplayInfo(displayInfo);


        // We only do transition in portrait currently, b/137962047.
        // We only do transition in portrait currently, b/137962047.
        int orientation = context.getResources().getConfiguration().orientation;
        int orientation = context.getResources().getConfiguration().orientation;
@@ -115,12 +113,7 @@ public class ImageWallpaperRenderer implements GLWallpaperRenderer,
            mBitmap = mWallpaperManager.getBitmap();
            mBitmap = mWallpaperManager.getBitmap();
            mWallpaperManager.forgetLoadedWallpaper();
            mWallpaperManager.forgetLoadedWallpaper();
            if (mBitmap != null) {
            if (mBitmap != null) {
                float scale = (float) mScissor.height() / mBitmap.getHeight();
                mSurfaceSize.set(0, 0, mBitmap.getWidth(), mBitmap.getHeight());
                int surfaceHeight = Math.max(mScissor.height(), mBitmap.getHeight());
                int surfaceWidth = scale > 1f
                        ? Math.round(mBitmap.getWidth() * scale)
                        : mBitmap.getWidth();
                mSurfaceSize.set(0, 0, surfaceWidth, surfaceHeight);
            }
            }
        }
        }
        if (DEBUG) {
        if (DEBUG) {