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

Commit 29f24a13 authored by Chris Li's avatar Chris Li
Browse files

DisplayContent rotateBounds not keeping same physical position for 180

Rotation_90 + rotation_90 is different from the result of rotation_180
with the current implementation. Should also take care of rotation_180.

Fix: 180751251
Bug: 173124775
Test: atest WmTests:DisplayContentTests
Test: atest WMShellUnitTests:DisplayLayoutTest
Test: atest FrameworksCoreTests:RotationUtilsTest
Change-Id: Ia1c87409b4c4cc412c3fd89e58d08b6ae2069fd0
parent e040263f
Loading
Loading
Loading
Loading
+55 −0
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ import static android.view.Surface.ROTATION_90;
import android.annotation.Dimension;
import android.graphics.Insets;
import android.graphics.Matrix;
import android.graphics.Rect;
import android.view.Surface.Rotation;

/**
@@ -72,6 +73,60 @@ public class RotationUtils {
        return rotated;
    }

    /**
     * Rotates bounds as if parentBounds and bounds are a group. The group is rotated from
     * oldRotation to newRotation. This assumes that parentBounds is at 0,0 and remains at 0,0 after
     * rotation. The bounds will be at the same physical position in parentBounds.
     *
     * Only 'inOutBounds' is mutated.
     */
    public static void rotateBounds(Rect inOutBounds, Rect parentBounds, @Rotation int oldRotation,
            @Rotation int newRotation) {
        rotateBounds(inOutBounds, parentBounds, deltaRotation(oldRotation, newRotation));
    }

    /**
     * Rotates bounds as if parentBounds and bounds are a group. The group is rotated by `delta`
     * 90-degree counter-clockwise increments. This assumes that parentBounds is at 0,0 and
     * remains at 0,0 after rotation. The bounds will be at the same physical position in
     * parentBounds.
     *
     * Only 'inOutBounds' is mutated.
     */
    public static void rotateBounds(Rect inOutBounds, Rect parentBounds, @Rotation int rotation) {
        final int origLeft = inOutBounds.left;
        final int origTop = inOutBounds.top;
        switch (rotation) {
            case ROTATION_0:
                return;
            case ROTATION_90:
                inOutBounds.left = inOutBounds.top;
                inOutBounds.top = parentBounds.right - inOutBounds.right;
                inOutBounds.right = inOutBounds.bottom;
                inOutBounds.bottom = parentBounds.right - origLeft;
                return;
            case ROTATION_180:
                inOutBounds.left = parentBounds.right - inOutBounds.right;
                inOutBounds.right = parentBounds.right - origLeft;
                inOutBounds.top = parentBounds.bottom - inOutBounds.bottom;
                inOutBounds.bottom = parentBounds.bottom - origTop;
                return;
            case ROTATION_270:
                inOutBounds.left = parentBounds.bottom - inOutBounds.bottom;
                inOutBounds.bottom = inOutBounds.right;
                inOutBounds.right = parentBounds.bottom - inOutBounds.top;
                inOutBounds.top = origLeft;
        }
    }

    /** @return the rotation needed to rotate from oldRotation to newRotation. */
    @Rotation
    public static int deltaRotation(int oldRotation, int newRotation) {
        int delta = newRotation - oldRotation;
        if (delta < 0) delta += 4;
        return delta;
    }

    /**
     * Sets a matrix such that given a rotation, it transforms physical display
     * coordinates to that rotation's logical coordinates.
+61 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2021 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.util;

import static android.util.RotationUtils.rotateBounds;
import static android.view.Surface.ROTATION_180;
import static android.view.Surface.ROTATION_270;
import static android.view.Surface.ROTATION_90;

import static org.junit.Assert.assertEquals;

import android.graphics.Rect;

import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;

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

/**
 * Tests for {@link RotationUtils}.
 *
 * Build/Install/Run:
 *  atest FrameworksCoreTests:RotationUtilsTest
 */
@SmallTest
@RunWith(AndroidJUnit4.class)
public class RotationUtilsTest {

    @Test
    public void testRotateBounds() {
        Rect testParent = new Rect(0, 0, 1000, 600);
        Rect testInner = new Rect(40, 20, 120, 80);

        Rect testResult = new Rect(testInner);
        rotateBounds(testResult, testParent, ROTATION_90);
        assertEquals(new Rect(20, 880, 80, 960), testResult);

        testResult.set(testInner);
        rotateBounds(testResult, testParent, ROTATION_180);
        assertEquals(new Rect(880, 520, 960, 580), testResult);

        testResult.set(testInner);
        rotateBounds(testResult, testParent, ROTATION_270);
        assertEquals(new Rect(520, 40, 580, 120), testResult);
    }
}
+3 −35
Original line number Diff line number Diff line
@@ -22,6 +22,8 @@ import static android.content.res.Configuration.UI_MODE_TYPE_CAR;
import static android.content.res.Configuration.UI_MODE_TYPE_MASK;
import static android.os.Process.SYSTEM_UID;
import static android.provider.Settings.Global.DEVELOPMENT_FORCE_DESKTOP_MODE_ON_EXTERNAL_DISPLAYS;
import static android.util.RotationUtils.rotateBounds;
import static android.util.RotationUtils.rotateInsets;
import static android.view.Display.FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS;
import static android.view.Surface.ROTATION_0;
import static android.view.Surface.ROTATION_270;
@@ -37,7 +39,6 @@ import android.graphics.Rect;
import android.os.SystemProperties;
import android.provider.Settings;
import android.util.DisplayMetrics;
import android.util.RotationUtils;
import android.util.Size;
import android.view.Display;
import android.view.DisplayCutout;
@@ -240,38 +241,6 @@ public class DisplayLayout {
        return navigationBarPosition(res, mWidth, mHeight, mRotation);
    }

    /**
     * Rotates bounds as if parentBounds and bounds are a group. The group is rotated by `delta`
     * 90-degree counter-clockwise increments. This assumes that parentBounds is at 0,0 and
     * remains at 0,0 after rotation.
     *
     * Only 'bounds' is mutated.
     */
    public static void rotateBounds(Rect inOutBounds, Rect parentBounds, int delta) {
        int rdelta = ((delta % 4) + 4) % 4;
        int origLeft = inOutBounds.left;
        switch (rdelta) {
            case 0:
                return;
            case 1:
                inOutBounds.left = inOutBounds.top;
                inOutBounds.top = parentBounds.right - inOutBounds.right;
                inOutBounds.right = inOutBounds.bottom;
                inOutBounds.bottom = parentBounds.right - origLeft;
                return;
            case 2:
                inOutBounds.left = parentBounds.right - inOutBounds.right;
                inOutBounds.right = parentBounds.right - origLeft;
                return;
            case 3:
                inOutBounds.left = parentBounds.bottom - inOutBounds.bottom;
                inOutBounds.bottom = inOutBounds.right;
                inOutBounds.right = parentBounds.bottom - inOutBounds.top;
                inOutBounds.top = origLeft;
                return;
        }
    }

    /**
     * Calculates the stable insets if we already have the non-decor insets.
     */
@@ -359,8 +328,7 @@ public class DisplayLayout {
        if (rotation == ROTATION_0) {
            return computeSafeInsets(cutout, displayWidth, displayHeight);
        }
        final Insets waterfallInsets =
                RotationUtils.rotateInsets(cutout.getWaterfallInsets(), rotation);
        final Insets waterfallInsets = rotateInsets(cutout.getWaterfallInsets(), rotation);
        final boolean rotated = (rotation == ROTATION_90 || rotation == ROTATION_270);
        Rect[] cutoutRects = cutout.getBoundingRectsAll();
        final Rect[] newBounds = new Rect[cutoutRects.length];
+2 −1
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ package com.android.wm.shell.legacysplitscreen;

import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
import static android.util.RotationUtils.rotateBounds;
import static android.view.WindowManager.DOCKED_BOTTOM;
import static android.view.WindowManager.DOCKED_INVALID;
import static android.view.WindowManager.DOCKED_LEFT;
@@ -244,7 +245,7 @@ public class LegacySplitDisplayLayout {
            DividerSnapAlgorithm snap = initSnapAlgorithmForRotation(context, tmpDL, dividerSize);

            tmpRect.set(bounds);
            DisplayLayout.rotateBounds(tmpRect, displayRect, rotation - dl.rotation());
            rotateBounds(tmpRect, displayRect, dl.rotation(), rotation);
            rotatedDisplayRect.set(0, 0, tmpDL.width(), tmpDL.height());
            final int dockSide = getPrimarySplitSide(tmpRect, rotatedDisplayRect,
                    tmpDL.getOrientation());
+2 −2
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package com.android.wm.shell.pip;

import static android.util.RotationUtils.rotateBounds;
import static android.view.Surface.ROTATION_270;
import static android.view.Surface.ROTATION_90;

@@ -33,7 +34,6 @@ import android.view.SurfaceControl;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.graphics.SfVsyncFrameCallbackProvider;
import com.android.wm.shell.animation.Interpolators;
import com.android.wm.shell.common.DisplayLayout;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -448,7 +448,7 @@ public class PipAnimationController {
                // Rotate the end bounds according to the rotation delta because the display will
                // be rotated to the same orientation.
                rotatedEndRect = new Rect(endValue);
                DisplayLayout.rotateBounds(rotatedEndRect, endValue, rotationDelta);
                rotateBounds(rotatedEndRect, endValue, rotationDelta);
            } else {
                rotatedEndRect = null;
            }
Loading