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

Commit 6a5370a0 authored by Riddle Hsu's avatar Riddle Hsu
Browse files

Simplify finding wallpapers

Because mWallpaperTokens already contains all wallpaper windows,
it is unnecessary to traverse all windows. Then it can be 10x faster.

By making mWallpaperTokens follow z-order, that also improves the
correctness of getTopVisibleWallpaper.

Remove startWallpaperAnimation by the way as it is dead code for years.

Bug: 163976519
Test: WallpaperControllerTests#testShowWhenLockedWallpaperTarget

Change-Id: Ifa3bf54ebeee049ccc1952884d4a213a2ee9f39d
parent ce8d4a38
Loading
Loading
Loading
Loading
+1 −6
Original line number Diff line number Diff line
@@ -691,12 +691,7 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener {
        recordDisplay(wc.getDisplayContent());
        if (info.mShowWallpaper) {
            // Collect the wallpaper token (for isWallpaper(wc)) so it is part of the sync set.
            final List<WindowState> wallpapers =
                    wc.getDisplayContent().mWallpaperController.getAllTopWallpapers();
            for (int i = wallpapers.size() - 1; i >= 0; i--) {
                WindowState wallpaper = wallpapers.get(i);
                collect(wallpaper.mToken);
            }
            wc.mDisplayContent.mWallpaperController.collectTopWallpapers(this);
        }
    }

+31 −32
Original line number Diff line number Diff line
@@ -23,7 +23,6 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_WITH_WALLPAPER;

import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_WALLPAPER;
@@ -55,7 +54,6 @@ import android.view.Display;
import android.view.DisplayInfo;
import android.view.SurfaceControl;
import android.view.WindowManager;
import android.view.animation.Animation;
import android.window.ScreenCapture;

import com.android.internal.R;
@@ -80,6 +78,7 @@ class WallpaperController {
    private WallpaperCropUtils mWallpaperCropUtils = null;
    private DisplayContent mDisplayContent;

    // Larger index has higher z-order.
    private final ArrayList<WallpaperWindowToken> mWallpaperTokens = new ArrayList<>();

    // If non-null, this is the currently visible window that is associated
@@ -126,18 +125,6 @@ class WallpaperController {
     */
    private volatile boolean mIsWallpaperNotifiedOnDisplaySwitch;

    private final Consumer<WindowState> mFindWallpapers = w -> {
        if (w.mAttrs.type == TYPE_WALLPAPER) {
            WallpaperWindowToken token = w.mToken.asWallpaperToken();
            if (token.canShowWhenLocked() && !mFindResults.hasTopShowWhenLockedWallpaper()) {
                mFindResults.setTopShowWhenLockedWallpaper(w);
            } else if (!token.canShowWhenLocked()
                    && !mFindResults.hasTopHideWhenLockedWallpaper()) {
                mFindResults.setTopHideWhenLockedWallpaper(w);
            }
        }
    };

    private final ToBooleanFunction<WindowState> mFindWallpaperTargetFunction = w -> {
        final boolean useShellTransition = w.mTransitionController.isShellTransitionsEnabled();
        if (!useShellTransition) {
@@ -321,16 +308,6 @@ class WallpaperController {
        return false;
    }

    /**
     * Starts {@param a} on all wallpaper windows.
     */
    void startWallpaperAnimation(Animation a) {
        for (int curTokenNdx = mWallpaperTokens.size() - 1; curTokenNdx >= 0; curTokenNdx--) {
            final WallpaperWindowToken token = mWallpaperTokens.get(curTokenNdx);
            token.startAnimation(a);
        }
    }

    boolean isWallpaperTargetAnimating() {
        return mWallpaperTarget != null && mWallpaperTarget.isAnimating(TRANSITION | PARENTS)
                && (mWallpaperTarget.mActivityRecord == null
@@ -621,7 +598,8 @@ class WallpaperController {
        if (Float.compare(window.mWallpaperZoomOut, zoom) != 0) {
            window.mWallpaperZoomOut = zoom;
            computeLastWallpaperZoomOut();
            for (WallpaperWindowToken token : mWallpaperTokens) {
            for (int i = mWallpaperTokens.size() - 1; i >= 0; i--) {
                final WallpaperWindowToken token = mWallpaperTokens.get(i);
                token.updateWallpaperOffset(false);
            }
        }
@@ -744,7 +722,7 @@ class WallpaperController {
            mFindResults.setUseTopWallpaperAsTarget(true);
        }

        mDisplayContent.forAllWindows(mFindWallpapers, true /* traverseTopToBottom */);
        findWallpapers();
        mDisplayContent.forAllWindows(mFindWallpaperTargetFunction, true /* traverseTopToBottom */);
        if (mFindResults.mNeedsShowWhenLockedWallpaper) {
            // Keep wallpaper visible if the show-when-locked activities doesn't fill screen.
@@ -757,15 +735,29 @@ class WallpaperController {
        }
    }

    List<WindowState> getAllTopWallpapers() {
        ArrayList<WindowState> wallpapers = new ArrayList<>(2);
    private void findWallpapers() {
        for (int i = mWallpaperTokens.size() - 1; i >= 0; i--) {
            final WallpaperWindowToken token = mWallpaperTokens.get(i);
            final boolean canShowWhenLocked = token.canShowWhenLocked();
            for (int j = token.getChildCount() - 1; j >= 0; j--) {
                final WindowState w = token.getChildAt(j);
                if (!w.mIsWallpaper) continue;
                if (canShowWhenLocked && !mFindResults.hasTopShowWhenLockedWallpaper()) {
                    mFindResults.setTopShowWhenLockedWallpaper(w);
                } else if (!canShowWhenLocked && !mFindResults.hasTopHideWhenLockedWallpaper()) {
                    mFindResults.setTopHideWhenLockedWallpaper(w);
                }
            }
        }
    }

    void collectTopWallpapers(Transition transition) {
        if (mFindResults.hasTopShowWhenLockedWallpaper()) {
            wallpapers.add(mFindResults.mTopWallpaper.mTopShowWhenLockedWallpaper);
            transition.collect(mFindResults.mTopWallpaper.mTopShowWhenLockedWallpaper);
        }
        if (mFindResults.hasTopHideWhenLockedWallpaper()) {
            wallpapers.add(mFindResults.mTopWallpaper.mTopHideWhenLockedWallpaper);
            transition.collect(mFindResults.mTopWallpaper.mTopHideWhenLockedWallpaper);
        }
        return wallpapers;
    }

    private boolean isFullscreen(WindowManager.LayoutParams attrs) {
@@ -1016,6 +1008,12 @@ class WallpaperController {
        mWallpaperTokens.remove(token);
    }

    void onWallpaperTokenReordered() {
        if (mWallpaperTokens.size() > 1) {
            mWallpaperTokens.sort(null /* by WindowContainer#compareTo */);
        }
    }

    @VisibleForTesting
    boolean canScreenshotWallpaper() {
        return canScreenshotWallpaper(getTopVisibleWallpaper());
@@ -1160,7 +1158,8 @@ class WallpaperController {
            pw.print(prefix); pw.print("mPrevWallpaperTarget="); pw.println(mPrevWallpaperTarget);
        }

        for (WallpaperWindowToken t : mWallpaperTokens) {
        for (int i = mWallpaperTokens.size() - 1; i >= 0; i--) {
            final WallpaperWindowToken t = mWallpaperTokens.get(i);
            pw.print(prefix); pw.println("token " + t + ":");
            pw.print(prefix); pw.print("  canShowWhenLocked="); pw.println(t.canShowWhenLocked());
            dumpValue(pw, prefix, "mWallpaperX", t.mWallpaperX);
+5 −18
Original line number Diff line number Diff line
@@ -30,7 +30,6 @@ import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.SparseArray;
import android.view.animation.Animation;

import com.android.internal.protolog.common.ProtoLog;

@@ -90,16 +89,14 @@ class WallpaperWindowToken extends WindowToken {
            return;
        }
        mShowWhenLocked = showWhenLocked;
        // Move the window token to the front (private) or back (showWhenLocked). This is
        // possible
        // because the DisplayArea underneath TaskDisplayArea only contains TYPE_WALLPAPER
        // windows.
        // Move the window token to the front (private) or back (showWhenLocked). This is possible
        // because the DisplayArea underneath TaskDisplayArea only contains TYPE_WALLPAPER windows.
        final int position = showWhenLocked ? POSITION_BOTTOM : POSITION_TOP;

        // Note: Moving all the way to the front or back breaks ordering based on addition
        // times.
        // We should never have more than one non-animating token of each type.
        // Note: Moving all the way to the front or back breaks ordering based on addition times.
        // There should never have more than one non-animating token of each type.
        getParent().positionChildAt(position, this /* child */, false /*includingParents */);
        mDisplayContent.mWallpaperController.onWallpaperTokenReordered();
    }

    boolean canShowWhenLocked() {
@@ -139,16 +136,6 @@ class WallpaperWindowToken extends WindowToken {
        }
    }

    /**
     * Starts {@param anim} on all children.
     */
    void startAnimation(Animation anim) {
        for (int ndx = mChildren.size() - 1; ndx >= 0; ndx--) {
            final WindowState windowState = mChildren.get(ndx);
            windowState.startAnimation(anim);
        }
    }

    void updateWallpaperWindows(boolean visible) {
        if (mVisibleRequested != visible) {
            ProtoLog.d(WM_DEBUG_WALLPAPER, "Wallpaper token %s visible=%b",
+23 −9
Original line number Diff line number Diff line
@@ -88,8 +88,6 @@ public class WallpaperControllerTests extends WindowTestsBase {

    @Test
    public void testWallpaperScreenshot() {
        WindowSurfaceController windowSurfaceController = mock(WindowSurfaceController.class);

        // No wallpaper
        final DisplayContent dc = createNewDisplay();
        assertFalse(dc.mWallpaperController.canScreenshotWallpaper());
@@ -99,11 +97,9 @@ public class WallpaperControllerTests extends WindowTestsBase {
        assertFalse(dc.mWallpaperController.canScreenshotWallpaper());

        // Wallpaper with not visible WSA surface.
        wallpaperWindow.mWinAnimator.mSurfaceController = windowSurfaceController;
        wallpaperWindow.mWinAnimator.mLastAlpha = 1;
        assertFalse(dc.mWallpaperController.canScreenshotWallpaper());

        when(windowSurfaceController.getShown()).thenReturn(true);
        makeWallpaperWindowShown(wallpaperWindow);

        // Wallpaper with WSA alpha set to 0.
        wallpaperWindow.mWinAnimator.mLastAlpha = 0;
@@ -306,14 +302,25 @@ public class WallpaperControllerTests extends WindowTestsBase {
        spyOn(mWm.mPolicy);
        doReturn(true).when(mWm.mPolicy).isKeyguardLocked();
        doReturn(true).when(mWm.mPolicy).isKeyguardOccluded();
        mDisplayContent.mWallpaperController.adjustWallpaperWindows();
        final WallpaperController wallpaperController = mDisplayContent.mWallpaperController;
        wallpaperController.adjustWallpaperWindows();
        // Wallpaper is visible because the show-when-locked activity is translucent.
        assertTrue(mDisplayContent.mWallpaperController.isWallpaperTarget(wallpaperWindow));
        assertTrue(wallpaperController.isWallpaperTarget(wallpaperWindow));

        behind.mActivityRecord.setShowWhenLocked(true);
        mDisplayContent.mWallpaperController.adjustWallpaperWindows();
        wallpaperController.adjustWallpaperWindows();
        // Wallpaper is invisible because the lowest show-when-locked activity is opaque.
        assertTrue(mDisplayContent.mWallpaperController.isWallpaperTarget(null));
        assertTrue(wallpaperController.isWallpaperTarget(null));

        // A show-when-locked wallpaper is used for lockscreen. So the top wallpaper should
        // be the one that is not show-when-locked.
        final WindowState wallpaperWindow2 = createWallpaperWindow(mDisplayContent);
        makeWallpaperWindowShown(wallpaperWindow2);
        makeWallpaperWindowShown(wallpaperWindow);
        assertEquals(wallpaperWindow2, wallpaperController.getTopVisibleWallpaper());
        wallpaperWindow2.mToken.asWallpaperToken().setShowWhenLocked(true);
        wallpaperWindow.mToken.asWallpaperToken().setShowWhenLocked(false);
        assertEquals(wallpaperWindow, wallpaperController.getTopVisibleWallpaper());
    }

    /**
@@ -527,6 +534,13 @@ public class WallpaperControllerTests extends WindowTestsBase {
        assertThat(wallpaperWindow.mYOffset).isEqualTo(0);
    }

    private static void makeWallpaperWindowShown(WindowState w) {
        final WindowSurfaceController windowSurfaceController = mock(WindowSurfaceController.class);
        w.mWinAnimator.mSurfaceController = windowSurfaceController;
        w.mWinAnimator.mLastAlpha = 1;
        when(windowSurfaceController.getShown()).thenReturn(true);
    }

    private WindowState createWallpaperWindow(DisplayContent dc, int width, int height) {
        final WindowState wallpaperWindow = createWallpaperWindow(dc);
        // Wallpaper is cropped to match first display.