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

Commit b46f9233 authored by Vadim Caen's avatar Vadim Caen
Browse files

Compute Wallpaper scaling on the server

Image wallpaper uses DisplayInfo to compute the wallpaper scaling.
When the wallpaper has a fixed rotation transform, its DisplayInfo do
not correspond to its transformed bounds.

We can't use the Configuration's bounds either because the wallpaper
token is created on the server side and we do not have a way to
propagate the changed configuration to a token created from the server.

Bug: 148000485
Test: atest WallpaperControllerTests#testWallpaperSizeWithFixedTransform

Change-Id: Ie80592ae868c980faddece17b94cd34178b1de0e
(cherry picked from commit f79baeaa)
parent 4cbd3b7a
Loading
Loading
Loading
Loading
+2 −17
Original line number Diff line number Diff line
@@ -49,7 +49,6 @@ import android.util.Log;
import android.util.MergedConfiguration;
import android.view.Display;
import android.view.DisplayCutout;
import android.view.DisplayInfo;
import android.view.Gravity;
import android.view.IWindowSession;
import android.view.InputChannel;
@@ -833,22 +832,8 @@ public abstract class WallpaperService extends Service {
                    mLayout.x = 0;
                    mLayout.y = 0;

                    if (!fixedSize) {
                    mLayout.width = myWidth;
                    mLayout.height = myHeight;
                    } else {
                        // Force the wallpaper to cover the screen in both dimensions
                        // only internal implementations like ImageWallpaper
                        DisplayInfo displayInfo = new DisplayInfo();
                        mDisplay.getDisplayInfo(displayInfo);
                        final float layoutScale = Math.max(
                                (float) displayInfo.logicalHeight / (float) myHeight,
                                (float) displayInfo.logicalWidth / (float) myWidth);
                        mLayout.height = (int) (myHeight * layoutScale);
                        mLayout.width = (int) (myWidth * layoutScale);
                        mWindowFlags |= WindowManager.LayoutParams.FLAG_SCALED;
                    }

                    mLayout.format = mFormat;

                    mCurWindowFlags = mWindowFlags;
+19 −0
Original line number Diff line number Diff line
@@ -28,6 +28,8 @@ import android.os.IBinder;
import android.os.RemoteException;
import android.util.Slog;
import android.view.DisplayInfo;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.view.animation.Animation;

import java.util.function.Consumer;
@@ -168,6 +170,23 @@ class WallpaperWindowToken extends WindowToken {
        }
    }

    @Override
    void adjustWindowParams(WindowState win, WindowManager.LayoutParams attrs) {
        if (attrs.height == ViewGroup.LayoutParams.MATCH_PARENT
                || attrs.width == ViewGroup.LayoutParams.MATCH_PARENT) {
            return;
        }

        final DisplayInfo displayInfo = win.getDisplayInfo();

        final float layoutScale = Math.max(
                (float) displayInfo.logicalHeight / (float) attrs.height,
                (float) displayInfo.logicalWidth / (float) attrs.width);
        attrs.height = (int) (attrs.height * layoutScale);
        attrs.width = (int) (attrs.width * layoutScale);
        attrs.flags |= WindowManager.LayoutParams.FLAG_SCALED;
    }

    boolean hasVisibleNotDrawnWallpaper() {
        for (int j = mChildren.size() - 1; j >= 0; --j) {
            final WindowState wallpaper = mChildren.get(j);
+1 −0
Original line number Diff line number Diff line
@@ -2122,6 +2122,7 @@ public class WindowManagerService extends IWindowManager.Stub
            int privateFlagChanges = 0;
            if (attrs != null) {
                displayPolicy.adjustWindowParamsLw(win, attrs, pid, uid);
                win.mToken.adjustWindowParams(win, attrs);
                // if they don't have the permission, mask out the status bar bits
                if (seq == win.mSeq) {
                    int systemUiVisibility = attrs.systemUiVisibility
+9 −0
Original line number Diff line number Diff line
@@ -48,6 +48,7 @@ import android.util.proto.ProtoOutputStream;
import android.view.DisplayInfo;
import android.view.InsetsState;
import android.view.SurfaceControl;
import android.view.WindowManager;

import com.android.server.policy.WindowManagerPolicy;
import com.android.server.protolog.common.ProtoLog;
@@ -500,6 +501,14 @@ class WindowToken extends WindowContainer<WindowState> {
        rotator.unrotateInsets(outSurfaceInsets);
    }

    /**
     * Gives a chance to this {@link WindowToken} to adjust the {@link
     * android.view.WindowManager.LayoutParams} of its windows.
     */
    void adjustWindowParams(WindowState win, WindowManager.LayoutParams attrs) {
    }


    @CallSuper
    @Override
    public void dumpDebug(ProtoOutputStream proto, long fieldId,
+67 −0
Original line number Diff line number Diff line
@@ -16,19 +16,30 @@

package com.android.server.wm;

import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS;
import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;

import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.graphics.Rect;
import android.os.IBinder;
import android.platform.test.annotations.Presubmit;
import android.view.DisplayInfo;
import android.view.Gravity;
import android.view.Surface;
import android.view.WindowManager;

import androidx.test.filters.SmallTest;

import com.android.server.wm.utils.WmDisplayCutout;

import org.junit.Test;
import org.junit.runner.RunWith;

@@ -72,4 +83,60 @@ public class WallpaperControllerTests extends WindowTestsBase {
        wallpaperWindow.mWinAnimator.mLastAlpha = 1;
        assertTrue(dc.mWallpaperController.canScreenshotWallpaper());
    }

    @Test
    public void testWallpaperSizeWithFixedTransform() {
        // No wallpaper
        final DisplayContent dc = createNewDisplay();
        dc.mWmService.mIsFixedRotationTransformEnabled = true;

        // No wallpaper WSA Surface
        WindowToken wallpaperWindowToken = new WallpaperWindowToken(mWm, mock(IBinder.class),
                true, dc, true /* ownerCanManageAppTokens */);
        WindowState wallpaperWindow = createWindow(null /* parent */, TYPE_WALLPAPER,
                wallpaperWindowToken, "wallpaperWindow");

        WindowManager.LayoutParams attrs = wallpaperWindow.getAttrs();
        Rect bounds = dc.getBounds();
        int displayHeight = dc.getBounds().height();

        // Use a wallpaper with a different ratio than the display
        int wallpaperWidth = bounds.width() * 2;
        int wallpaperHeight = (int) (bounds.height() * 1.10);

        // Simulate what would be done on the client's side
        attrs.width = wallpaperWidth;
        attrs.height = wallpaperHeight;
        attrs.flags |= FLAG_LAYOUT_NO_LIMITS;
        attrs.gravity = Gravity.TOP | Gravity.LEFT;
        wallpaperWindow.getWindowFrames().mParentFrame.set(dc.getBounds());

        // Calling layoutWindowLw a first time, so adjustWindowParams gets the correct data
        dc.getDisplayPolicy().layoutWindowLw(wallpaperWindow, null, dc.mDisplayFrames);

        wallpaperWindowToken.adjustWindowParams(wallpaperWindow, attrs);
        dc.getDisplayPolicy().layoutWindowLw(wallpaperWindow, null, dc.mDisplayFrames);

        assertEquals(Configuration.ORIENTATION_PORTRAIT, dc.getConfiguration().orientation);
        int expectedWidth = (int) (wallpaperWidth * (displayHeight / (double) wallpaperHeight));

        // Check that the wallpaper is correctly scaled
        assertEquals(new Rect(0, 0, expectedWidth, displayHeight), wallpaperWindow.getFrameLw());
        Rect portraitFrame = wallpaperWindow.getFrameLw();

        // Rotate the display
        dc.getDisplayRotation().updateOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE, true);
        dc.sendNewConfiguration();

        // Apply the fixed transform
        Configuration config = new Configuration();
        final DisplayInfo info = dc.computeScreenConfiguration(config, Surface.ROTATION_0);
        final WmDisplayCutout cutout = dc.calculateDisplayCutoutForRotation(Surface.ROTATION_0);
        final DisplayFrames displayFrames = new DisplayFrames(dc.getDisplayId(), info, cutout);
        wallpaperWindowToken.applyFixedRotationTransform(info, displayFrames, config);

        // Check that the wallpaper has the same frame in landscape than in portrait
        assertEquals(Configuration.ORIENTATION_LANDSCAPE, dc.getConfiguration().orientation);
        assertEquals(portraitFrame, wallpaperWindow.getFrameLw());
    }
}