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

Commit a8e5a2bc authored by Chet Haase's avatar Chet Haase
Browse files

Optimize handling of scrolled wallpapers

Swiping the home screen causes the WindowManagerService to do
a bunch of work to keep the wallpapers in sync. First, it lays out
and places all windows. Also, it notifies the SystemUI process that
the wallpaper position has changed.

The layout/place operation is too much work - we only need to set
the position values for the wallpaper, not relayout the whole system.

The notification mechanism must exist, but should be optional. Most
wallpapers don't care (especially static ImageWallpapers). So we'll
give them a new API (WallpaperService.Engine.setWantsOffsets()) to
allow wallpapers to opt out of this process and avoid the performance
overhead.

Change-Id: I66c38375438937f14f6f5550565b28eb204b1e06
parent 48ba4139
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -18669,6 +18669,7 @@ package android.service.wallpaper {
    method public void onSurfaceRedrawNeeded(android.view.SurfaceHolder);
    method public void onTouchEvent(android.view.MotionEvent);
    method public void onVisibilityChanged(boolean);
    method public void setOffsetNotificationsEnabled(boolean);
    method public void setTouchEventsEnabled(boolean);
  }
+28 −1
Original line number Diff line number Diff line
@@ -148,7 +148,10 @@ public abstract class WallpaperService extends Service {
        int mCurWidth;
        int mCurHeight;
        int mWindowFlags = WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
        int mWindowPrivateFlags =
                WindowManager.LayoutParams.PRIVATE_FLAG_WANTS_OFFSET_NOTIFICATIONS;
        int mCurWindowFlags = mWindowFlags;
        int mCurWindowPrivateFlags = mWindowPrivateFlags;
        final Rect mVisibleInsets = new Rect();
        final Rect mWinFrame = new Rect();
        final Rect mContentInsets = new Rect();
@@ -360,6 +363,25 @@ public abstract class WallpaperService extends Service {
            }
        }

        /**
         * Control whether this wallpaper will receive notifications when the wallpaper
         * has been scrolled. By default, wallpapers will receive notifications, although
         * the default static image wallpapers do not. It is a performance optimization to
         * set this to false.
         *
         * @param enabled whether the wallpaper wants to receive offset notifications
         */
        public void setOffsetNotificationsEnabled(boolean enabled) {
            mWindowPrivateFlags = enabled
                    ? (mWindowPrivateFlags |
                        WindowManager.LayoutParams.PRIVATE_FLAG_WANTS_OFFSET_NOTIFICATIONS)
                    : (mWindowPrivateFlags &
                        ~WindowManager.LayoutParams.PRIVATE_FLAG_WANTS_OFFSET_NOTIFICATIONS);
            if (mCreated) {
                updateSurface(false, false, false);
            }
        }
        
        /**
         * Called once to initialize the engine.  After returning, the
         * engine's surface will be created by the framework.
@@ -478,6 +500,8 @@ public abstract class WallpaperService extends Service {
            out.print(prefix); out.print("mType="); out.print(mType);
                    out.print(" mWindowFlags="); out.print(mWindowFlags);
                    out.print(" mCurWindowFlags="); out.println(mCurWindowFlags);
                    out.print(" mWindowPrivateFlags="); out.print(mWindowPrivateFlags);
                    out.print(" mCurWindowPrivateFlags="); out.println(mCurWindowPrivateFlags);
            out.print(prefix); out.print("mVisibleInsets=");
                    out.print(mVisibleInsets.toShortString());
                    out.print(" mWinFrame="); out.print(mWinFrame.toShortString());
@@ -528,7 +552,8 @@ public abstract class WallpaperService extends Service {
            final boolean formatChanged = mFormat != mSurfaceHolder.getRequestedFormat();
            boolean sizeChanged = mWidth != myWidth || mHeight != myHeight;
            final boolean typeChanged = mType != mSurfaceHolder.getRequestedType();
            final boolean flagsChanged = mCurWindowFlags != mWindowFlags;
            final boolean flagsChanged = mCurWindowFlags != mWindowFlags ||
                    mCurWindowPrivateFlags != mWindowPrivateFlags;
            if (forceRelayout || creating || surfaceCreating || formatChanged || sizeChanged
                    || typeChanged || flagsChanged || redrawNeeded) {

@@ -554,6 +579,8 @@ public abstract class WallpaperService extends Service {
                            | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
                            | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                            ;
                    mCurWindowPrivateFlags = mWindowPrivateFlags;
                    mLayout.privateFlags = mWindowPrivateFlags;

                    mLayout.memoryType = mType;
                    mLayout.token = mWindowToken;
+11 −0
Original line number Diff line number Diff line
@@ -812,6 +812,17 @@ public interface WindowManager extends ViewManager {
         */
        public static final int PRIVATE_FLAG_FORCE_HARDWARE_ACCELERATED = 0x00000002;

        /**
         * By default, wallpapers are sent new offsets when the wallpaper is scrolled. Wallpapers
         * may elect to skp these notifications if they are no doing anything productive with
         * them (they do not affect the wallpaper scrolling operation) by calling
         * {@link
         * android.service.wallpaper.WallpaperService.Engine#setOffsetNotificationsEnabled(boolean)}.
         *
         * @hide
         */
        public static final int PRIVATE_FLAG_WANTS_OFFSET_NOTIFICATIONS = 0x00000004;

        /**
         * Control flags that are private to the platform.
         * @hide
+2 −0
Original line number Diff line number Diff line
@@ -170,6 +170,8 @@ public class ImageWallpaper extends WallpaperService {
            //registerReceiver(mReceiver, filter, null, mHandler);

            updateSurfaceSize(surfaceHolder);

            setOffsetNotificationsEnabled(false);
        }

        @Override
+24 −10
Original line number Diff line number Diff line
@@ -1836,7 +1836,8 @@ public class WindowManagerService extends IWindowManager.Stub
            rawChanged = true;
        }

        if (rawChanged) {
        if (rawChanged && (wallpaperWin.getAttrs().privateFlags &
                    WindowManager.LayoutParams.PRIVATE_FLAG_WANTS_OFFSET_NOTIFICATIONS) != 0) {
            try {
                if (DEBUG_WALLPAPER) Slog.v(TAG, "Report new wp offset "
                        + wallpaperWin + " x=" + wallpaperWin.mWallpaperX
@@ -1886,12 +1887,10 @@ public class WindowManagerService extends IWindowManager.Stub
        }
    }

    boolean updateWallpaperOffsetLocked(WindowState changingTarget, boolean sync) {
    void updateWallpaperOffsetLocked(WindowState changingTarget, boolean sync) {
        final int dw = mAppDisplayWidth;
        final int dh = mAppDisplayHeight;

        boolean changed = false;

        WindowState target = mWallpaperTarget;
        if (target != null) {
            if (target.mWallpaperX >= 0) {
@@ -1916,14 +1915,31 @@ public class WindowManagerService extends IWindowManager.Stub
                WindowState wallpaper = token.windows.get(curWallpaperIndex);
                if (updateWallpaperOffsetLocked(wallpaper, dw, dh, sync)) {
                    wallpaper.computeShownFrameLocked();
                    changed = true;
                    // No need to lay out the windows - we can just set the wallpaper position
                    // directly.
                    if (wallpaper.mSurfaceX != wallpaper.mShownFrame.left
                            || wallpaper.mSurfaceY != wallpaper.mShownFrame.top) {
                        Surface.openTransaction();
                        try {
                            if (SHOW_TRANSACTIONS) logSurface(wallpaper,
                                    "POS " + wallpaper.mShownFrame.left
                                    + ", " + wallpaper.mShownFrame.top, null);
                            wallpaper.mSurfaceX = wallpaper.mShownFrame.left;
                            wallpaper.mSurfaceY = wallpaper.mShownFrame.top;
                            wallpaper.mSurface.setPosition(wallpaper.mShownFrame.left,
                                    wallpaper.mShownFrame.top);
                        } catch (RuntimeException e) {
                            Slog.w(TAG, "Error positioning surface of " + wallpaper
                                    + " pos=(" + wallpaper.mShownFrame.left
                                    + "," + wallpaper.mShownFrame.top + ")", e);
                        }
                        Surface.closeTransaction();
                    }
                    // We only want to be synchronous with one wallpaper.
                    sync = false;
                }
            }
        }

        return changed;
    }

    void updateWallpaperVisibilityLocked() {
@@ -2436,9 +2452,7 @@ public class WindowManagerService extends IWindowManager.Stub
            window.mWallpaperY = y;
            window.mWallpaperXStep = xStep;
            window.mWallpaperYStep = yStep;
            if (updateWallpaperOffsetLocked(window, true)) {
                performLayoutAndPlaceSurfacesLocked();
            }
            updateWallpaperOffsetLocked(window, true);
        }
    }