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

Commit a8f0672b authored by shawnlin's avatar shawnlin
Browse files

Updating the display bounds when it changes

In previous design, we only get the display bounds once when the first
time the hide cutout is enabled. But if user selects "Hide" first and
then switch to "Render apps below cutout area", the display bounds we
get will be incorrect.

Add a listener to monitor and update the display size.

Bug: 191273507
Test: atest HideDisplayCutoutTest
Test: manual - 1. select "Hide"
               2. select "Render apps below cutout area"
	       3. observe the result
Change-Id: I0ff1c4b822615d6bd43adb2e9e9d17d6bd9b91a8
parent 5d422575
Loading
Loading
Loading
Loading
+49 −29
Original line number Diff line number Diff line
@@ -19,8 +19,8 @@ package com.android.wm.shell.hidedisplaycutout;
import static android.view.Display.DEFAULT_DISPLAY;

import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Insets;
import android.graphics.Point;
import android.graphics.Rect;
import android.util.ArrayMap;
import android.util.Log;
@@ -40,13 +40,12 @@ import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;

import com.android.internal.R;
import com.android.wm.shell.common.DisplayChangeController;
import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.DisplayLayout;
import com.android.wm.shell.common.ShellExecutor;

import java.io.PrintWriter;
import java.util.List;
import java.util.concurrent.Executor;

/**
 * Manages the display areas of hide display cutout feature.
@@ -76,18 +75,28 @@ class HideDisplayCutoutOrganizer extends DisplayAreaOrganizer {
    @VisibleForTesting
    int mRotation;

    /**
     * Handles rotation based on OnDisplayChangingListener callback.
     */
    private final DisplayChangeController.OnDisplayChangingListener mRotationController =
            (display, fromRotation, toRotation, wct) -> {
                mRotation = toRotation;
                updateBoundsAndOffsets(true /* enable */);
    private final DisplayController.OnDisplaysChangedListener mListener =
            new DisplayController.OnDisplaysChangedListener() {
                @Override
                public void onDisplayConfigurationChanged(int displayId, Configuration newConfig) {
                    if (displayId != DEFAULT_DISPLAY) {
                        return;
                    }
                    DisplayLayout displayLayout =
                            mDisplayController.getDisplayLayout(DEFAULT_DISPLAY);
                    if (displayLayout == null) {
                        return;
                    }
                    final boolean rotationChanged = mRotation != displayLayout.rotation();
                    mRotation = displayLayout.rotation();
                    if (rotationChanged || isDisplayBoundsChanged()) {
                        updateBoundsAndOffsets(true /* enabled */);
                        final WindowContainerTransaction wct = new WindowContainerTransaction();
                        final SurfaceControl.Transaction t = new SurfaceControl.Transaction();
                        applyAllBoundsAndOffsets(wct, t);
                // Only apply t here since the server will do the wct.apply when the method
                // finishes.
                t.apply();
                        applyTransaction(wct, t);
                    }
                }
    };

    HideDisplayCutoutOrganizer(Context context, DisplayController displayController,
@@ -154,10 +163,10 @@ class HideDisplayCutoutOrganizer extends DisplayAreaOrganizer {
     * Enables hide display cutout.
     */
    void enableHideDisplayCutout() {
        mDisplayController.addDisplayChangingController(mRotationController);
        final Display display = mDisplayController.getDisplay(DEFAULT_DISPLAY);
        if (display != null) {
            mRotation = display.getRotation();
        mDisplayController.addDisplayWindowListener(mListener);
        final DisplayLayout displayLayout = mDisplayController.getDisplayLayout(DEFAULT_DISPLAY);
        if (displayLayout != null) {
            mRotation = displayLayout.rotation();
        }
        final List<DisplayAreaAppearedInfo> displayAreaInfos =
                registerOrganizer(DisplayAreaOrganizer.FEATURE_HIDE_DISPLAY_CUTOUT);
@@ -174,7 +183,7 @@ class HideDisplayCutoutOrganizer extends DisplayAreaOrganizer {
     */
    void disableHideDisplayCutout() {
        updateBoundsAndOffsets(false /* enabled */);
        mDisplayController.removeDisplayChangingController(mRotationController);
        mDisplayController.removeDisplayWindowListener(mListener);
        unregisterOrganizer();
    }

@@ -193,23 +202,35 @@ class HideDisplayCutoutOrganizer extends DisplayAreaOrganizer {

    @VisibleForTesting
    Rect getDisplayBoundsOfNaturalOrientation() {
        Point realSize = new Point(0, 0);
        final Display display = mDisplayController.getDisplay(DEFAULT_DISPLAY);
        if (display != null) {
            display.getRealSize(realSize);
        final DisplayLayout displayLayout = mDisplayController.getDisplayLayout(DEFAULT_DISPLAY);
        if (displayLayout == null) {
            return new Rect();
        }
        final boolean isDisplaySizeFlipped = isDisplaySizeFlipped();
        return new Rect(
                0,
                0,
                isDisplaySizeFlipped ? realSize.y : realSize.x,
                isDisplaySizeFlipped ? realSize.x : realSize.y);
                isDisplaySizeFlipped ? displayLayout.height() : displayLayout.width(),
                isDisplaySizeFlipped ? displayLayout.width() : displayLayout.height());
    }

    private boolean isDisplaySizeFlipped() {
        return mRotation == Surface.ROTATION_90 || mRotation == Surface.ROTATION_270;
    }

    private boolean isDisplayBoundsChanged() {
        final DisplayLayout displayLayout = mDisplayController.getDisplayLayout(DEFAULT_DISPLAY);
        if (displayLayout == null) {
            return false;
        }
        final boolean isDisplaySizeFlipped = isDisplaySizeFlipped();
        final int width = isDisplaySizeFlipped ? displayLayout.height() : displayLayout.width();
        final int height = isDisplaySizeFlipped ? displayLayout.width() : displayLayout.height();
        return mDefaultDisplayBounds.isEmpty()
                || mDefaultDisplayBounds.width() != width
                || mDefaultDisplayBounds.height() != height;
    }

    /**
     * Updates bounds and offsets according to current state.
     *
@@ -237,7 +258,6 @@ class HideDisplayCutoutOrganizer extends DisplayAreaOrganizer {
                        mCurrentDisplayBounds.right);
            }
            mCurrentDisplayBounds.inset(mCurrentCutoutInsets);

            // Replace the top bound with the max(status bar height, cutout height) if there is
            // cutout on the top side.
            mStatusBarHeight = getStatusBarHeight();
@@ -256,7 +276,7 @@ class HideDisplayCutoutOrganizer extends DisplayAreaOrganizer {
    }

    private void initDefaultValuesIfNeeded() {
        if (!mDefaultDisplayBounds.isEmpty()) {
        if (!isDisplayBoundsChanged()) {
            return;
        }
        mDefaultDisplayBounds.set(getDisplayBoundsOfNaturalOrientation());
+25 −3
Original line number Diff line number Diff line
@@ -50,6 +50,7 @@ import androidx.test.filters.SmallTest;

import com.android.internal.R;
import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.DisplayLayout;
import com.android.wm.shell.common.ShellExecutor;

import org.junit.Before;
@@ -82,6 +83,8 @@ public class HideDisplayCutoutOrganizerTest {
    @Mock
    private Display mDisplay;
    @Mock
    private DisplayLayout mDisplayLayout;
    @Mock
    private IWindowContainerToken mMockRealToken;
    private WindowContainerToken mToken;

@@ -95,6 +98,7 @@ public class HideDisplayCutoutOrganizerTest {
        MockitoAnnotations.initMocks(this);

        when(mMockDisplayController.getDisplay(anyInt())).thenReturn(mDisplay);
        when(mMockDisplayController.getDisplayLayout(anyInt())).thenReturn(mDisplayLayout);

        HideDisplayCutoutOrganizer organizer = new HideDisplayCutoutOrganizer(
                mContext, mMockDisplayController, mMockMainExecutor);
@@ -152,7 +156,7 @@ public class HideDisplayCutoutOrganizerTest {
                .getDisplayCutoutInsetsOfNaturalOrientation();
        mContext.getOrCreateTestableResources().addOverride(
                R.dimen.status_bar_height_portrait, mFakeStatusBarHeightPortrait);
        doReturn(Surface.ROTATION_0).when(mDisplay).getRotation();
        doReturn(Surface.ROTATION_0).when(mDisplayLayout).rotation();
        mOrganizer.enableHideDisplayCutout();

        verify(mOrganizer).registerOrganizer(DisplayAreaOrganizer.FEATURE_HIDE_DISPLAY_CUTOUT);
@@ -171,7 +175,7 @@ public class HideDisplayCutoutOrganizerTest {
                .getDisplayCutoutInsetsOfNaturalOrientation();
        mContext.getOrCreateTestableResources().addOverride(
                R.dimen.status_bar_height_landscape, mFakeStatusBarHeightLandscape);
        doReturn(Surface.ROTATION_90).when(mDisplay).getRotation();
        doReturn(Surface.ROTATION_90).when(mDisplayLayout).rotation();
        mOrganizer.enableHideDisplayCutout();

        verify(mOrganizer).registerOrganizer(DisplayAreaOrganizer.FEATURE_HIDE_DISPLAY_CUTOUT);
@@ -190,7 +194,7 @@ public class HideDisplayCutoutOrganizerTest {
                .getDisplayCutoutInsetsOfNaturalOrientation();
        mContext.getOrCreateTestableResources().addOverride(
                R.dimen.status_bar_height_landscape, mFakeStatusBarHeightLandscape);
        doReturn(Surface.ROTATION_270).when(mDisplay).getRotation();
        doReturn(Surface.ROTATION_270).when(mDisplayLayout).rotation();
        mOrganizer.enableHideDisplayCutout();

        verify(mOrganizer).registerOrganizer(DisplayAreaOrganizer.FEATURE_HIDE_DISPLAY_CUTOUT);
@@ -219,4 +223,22 @@ public class HideDisplayCutoutOrganizerTest {
        assertThat(mOrganizer.mOffsetX).isEqualTo(0);
        assertThat(mOrganizer.mOffsetY).isEqualTo(0);
    }

    @Test
    public void testDisplaySizeChange() {
        doReturn(100).when(mDisplayLayout).width();
        doReturn(200).when(mDisplayLayout).height();
        doReturn(mFakeDefaultCutoutInsets).when(mOrganizer)
                .getDisplayCutoutInsetsOfNaturalOrientation();
        mContext.getOrCreateTestableResources().addOverride(
                R.dimen.status_bar_height_portrait, mFakeStatusBarHeightPortrait);
        doReturn(Surface.ROTATION_0).when(mDisplayLayout).rotation();
        mOrganizer.enableHideDisplayCutout();
        assertThat(mOrganizer.mCurrentDisplayBounds).isEqualTo(new Rect(0, 15, 100, 200));

        doReturn(200).when(mDisplayLayout).width();
        doReturn(400).when(mDisplayLayout).height();
        mOrganizer.updateBoundsAndOffsets(true);
        assertThat(mOrganizer.mCurrentDisplayBounds).isEqualTo(new Rect(0, 15, 200, 400));
    }
}