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

Commit 1f63b200 authored by Android Build Merger (Role)'s avatar Android Build Merger (Role) Committed by Android (Google) Code Review
Browse files

Merge "Ensure consistency of screenHeightDp for non-resizable activity am:...

Merge "Ensure consistency of screenHeightDp for non-resizable activity am: 61987bca am: dedbe4d4"
parents 79f26869 84b04fc5
Loading
Loading
Loading
Loading
+59 −3
Original line number Diff line number Diff line
@@ -88,6 +88,8 @@ import static android.os.Build.VERSION_CODES.HONEYCOMB;
import static android.os.Build.VERSION_CODES.O;
import static android.os.Process.SYSTEM_UID;
import static android.view.Display.INVALID_DISPLAY;
import static android.view.Surface.ROTATION_270;
import static android.view.Surface.ROTATION_90;

import static com.android.server.am.ActivityRecordProto.CONFIGURATION_CONTAINER;
import static com.android.server.am.ActivityRecordProto.FRONT_OF_TASK;
@@ -195,6 +197,7 @@ import android.util.Slog;
import android.util.TimeUtils;
import android.util.proto.ProtoOutputStream;
import android.view.AppTransitionAnimationSpec;
import android.view.DisplayCutout;
import android.view.IAppTransitionAnimationSpecsFuture;
import android.view.IApplicationToken;
import android.view.RemoteAnimationDefinition;
@@ -382,6 +385,12 @@ final class ActivityRecord extends ConfigurationContainer {
    private int[] mHorizontalSizeConfigurations;
    private int[] mSmallestSizeConfigurations;

    /**
     * The precomputed display insets for resolving configuration. It will be non-null if
     * {@link #shouldUseSizeCompatMode} returns {@code true}.
     */
    private CompatDisplayInsets mCompatDisplayInsets;

    boolean pendingVoiceInteractionStart;   // Waiting for activity-invoked voice session
    IVoiceInteractionSession voiceSession;  // Voice interaction session for this activity

@@ -2833,6 +2842,11 @@ final class ActivityRecord extends ConfigurationContainer {
                // The smallest screen width is the short side of screen bounds. Because the bounds
                // and density won't be changed, smallestScreenWidthDp is also fixed.
                overrideConfig.smallestScreenWidthDp = parentConfig.smallestScreenWidthDp;

                final ActivityDisplay display = getDisplay();
                if (display != null && display.mDisplayContent != null) {
                    mCompatDisplayInsets = new CompatDisplayInsets(display.mDisplayContent);
                }
            }
        }
        onRequestedOverrideConfigurationChanged(overrideConfig);
@@ -2849,7 +2863,7 @@ final class ActivityRecord extends ConfigurationContainer {
            super.resolveOverrideConfiguration(newParentConfiguration);
            if (hasOverrideBounds) {
                task.computeConfigResourceOverrides(getResolvedOverrideConfiguration(),
                        newParentConfiguration, true /* insideParentBounds */);
                        newParentConfiguration);
            }
        }

@@ -2922,9 +2936,8 @@ final class ActivityRecord extends ConfigurationContainer {
            resolvedBounds.right -= resolvedAppBounds.left;
        }

        // In size compatibility mode, activity is allowed to have larger bounds than its parent.
        task.computeConfigResourceOverrides(resolvedConfig, newParentConfiguration,
                false /* insideParentBounds */);
                mCompatDisplayInsets);
        // Use parent orientation if it cannot be decided by bounds, so the activity can fit inside
        // the parent bounds appropriately.
        if (resolvedConfig.screenWidthDp == resolvedConfig.screenHeightDp) {
@@ -3450,6 +3463,7 @@ final class ActivityRecord extends ConfigurationContainer {
        // configuration.
        getRequestedOverrideConfiguration().setToDefaults();
        getResolvedOverrideConfiguration().setToDefaults();
        mCompatDisplayInsets = null;
        if (visible) {
            // Configuration will be ensured when becoming visible, so if it is already visible,
            // then the manual update is needed.
@@ -3796,4 +3810,46 @@ final class ActivityRecord extends ConfigurationContainer {
        writeToProto(proto);
        proto.end(token);
    }

    /**
     * The precomputed insets of the display in each rotation. This is used to make the size
     * compatibility mode activity compute the configuration without relying on its current display.
     */
    static class CompatDisplayInsets {
        final int mDisplayWidth;
        final int mDisplayHeight;

        /** The nonDecorInsets for each rotation. Includes the navigation bar and cutout insets. */
        final Rect[] mNonDecorInsets = new Rect[4];
        /**
         * The stableInsets for each rotation. Includes the status bar inset and the
         * nonDecorInsets. It is used to compute {@link Configuration#screenWidthDp} and
         * {@link Configuration#screenHeightDp}.
         */
        final Rect[] mStableInsets = new Rect[4];

        CompatDisplayInsets(DisplayContent display) {
            mDisplayWidth = display.mBaseDisplayWidth;
            mDisplayHeight = display.mBaseDisplayHeight;
            final DisplayPolicy policy = display.getDisplayPolicy();
            final DisplayCutout cutout = display.getDisplayInfo().displayCutout;
            for (int rotation = 0; rotation < 4; rotation++) {
                mNonDecorInsets[rotation] = new Rect();
                mStableInsets[rotation] = new Rect();
                final boolean rotated = (rotation == ROTATION_90 || rotation == ROTATION_270);
                final int dw = rotated ? mDisplayHeight : mDisplayWidth;
                final int dh = rotated ? mDisplayWidth : mDisplayHeight;
                policy.getNonDecorInsetsLw(rotation, dw, dh, cutout, mNonDecorInsets[rotation]);
                mStableInsets[rotation].set(mNonDecorInsets[rotation]);
                policy.convertNonDecorInsetsToStableInsets(mStableInsets[rotation], rotation);
            }
        }

        void getDisplayBounds(Rect outBounds, int rotation) {
            final boolean rotated = (rotation == ROTATION_90 || rotation == ROTATION_270);
            final int dw = rotated ? mDisplayHeight : mDisplayWidth;
            final int dh = rotated ? mDisplayWidth : mDisplayHeight;
            outBounds.set(0, 0, dw, dh);
        }
    }
}
+11 −1
Original line number Diff line number Diff line
@@ -2774,6 +2774,16 @@ public class DisplayPolicy {
        return mShowingDream;
    }

    /**
     * Calculates the stable insets if we already have the non-decor insets.
     *
     * @param inOutInsets The known non-decor insets. It will be modified to stable insets.
     * @param rotation The current display rotation.
     */
    void convertNonDecorInsetsToStableInsets(Rect inOutInsets, int rotation) {
        inOutInsets.top = Math.max(inOutInsets.top, mStatusBarHeightForRotation[rotation]);
    }

    /**
     * Calculates the stable insets without running a layout.
     *
@@ -2789,7 +2799,7 @@ public class DisplayPolicy {

        // Navigation bar and status bar.
        getNonDecorInsetsLw(displayRotation, displayWidth, displayHeight, displayCutout, outInsets);
        outInsets.top = Math.max(outInsets.top, mStatusBarHeightForRotation[displayRotation]);
        convertNonDecorInsetsToStableInsets(outInsets, displayRotation);
    }

    /**
+23 −10
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@ import static android.app.ActivityTaskManager.RESIZE_MODE_FORCED;
import static android.app.ActivityTaskManager.RESIZE_MODE_SYSTEM;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
import static android.app.WindowConfiguration.ROTATION_UNDEFINED;
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
@@ -2048,15 +2049,12 @@ class TaskRecord extends ConfigurationContainer {
        }
        mTmpBounds.set(0, 0, displayInfo.logicalWidth, displayInfo.logicalHeight);

        policy.getStableInsetsLw(displayInfo.rotation,
                displayInfo.logicalWidth, displayInfo.logicalHeight, displayInfo.displayCutout,
                mTmpInsets);
        intersectWithInsetsIfFits(outStableBounds, mTmpBounds, mTmpInsets);

        policy.getNonDecorInsetsLw(displayInfo.rotation,
                displayInfo.logicalWidth, displayInfo.logicalHeight, displayInfo.displayCutout,
                mTmpInsets);
        policy.getNonDecorInsetsLw(displayInfo.rotation, displayInfo.logicalWidth,
                displayInfo.logicalHeight, displayInfo.displayCutout, mTmpInsets);
        intersectWithInsetsIfFits(outNonDecorBounds, mTmpBounds, mTmpInsets);

        policy.convertNonDecorInsetsToStableInsets(mTmpInsets, displayInfo.rotation);
        intersectWithInsetsIfFits(outStableBounds, mTmpBounds, mTmpInsets);
    }

    /**
@@ -2073,7 +2071,7 @@ class TaskRecord extends ConfigurationContainer {

    void computeConfigResourceOverrides(@NonNull Configuration inOutConfig,
            @NonNull Configuration parentConfig) {
        computeConfigResourceOverrides(inOutConfig, parentConfig, true /* insideParentBounds */);
        computeConfigResourceOverrides(inOutConfig, parentConfig, null /* compatInsets */);
    }

    /**
@@ -2085,7 +2083,8 @@ class TaskRecord extends ConfigurationContainer {
     * just be inherited from the parent configuration.
     **/
    void computeConfigResourceOverrides(@NonNull Configuration inOutConfig,
            @NonNull Configuration parentConfig, boolean insideParentBounds) {
            @NonNull Configuration parentConfig,
            @Nullable ActivityRecord.CompatDisplayInsets compatInsets) {
        int windowingMode = inOutConfig.windowConfiguration.getWindowingMode();
        if (windowingMode == WINDOWING_MODE_UNDEFINED) {
            windowingMode = parentConfig.windowConfiguration.getWindowingMode();
@@ -2103,6 +2102,9 @@ class TaskRecord extends ConfigurationContainer {
            inOutConfig.windowConfiguration.setAppBounds(bounds);
            outAppBounds = inOutConfig.windowConfiguration.getAppBounds();
        }
        // Non-null compatibility insets means the activity prefers to keep its original size, so
        // the out bounds doesn't need to be restricted by the parent.
        final boolean insideParentBounds = compatInsets == null;
        if (insideParentBounds && windowingMode != WINDOWING_MODE_FREEFORM) {
            final Rect parentAppBounds = parentConfig.windowConfiguration.getAppBounds();
            if (parentAppBounds != null && !parentAppBounds.isEmpty()) {
@@ -2125,6 +2127,17 @@ class TaskRecord extends ConfigurationContainer {
                // Set to app bounds because it excludes decor insets.
                mTmpNonDecorBounds.set(outAppBounds);
                mTmpStableBounds.set(outAppBounds);

                // Apply the given non-decor and stable insets to calculate the corresponding bounds
                // for screen size of configuration.
                final int rotation = parentConfig.windowConfiguration.getRotation();
                if (rotation != ROTATION_UNDEFINED && compatInsets != null) {
                    compatInsets.getDisplayBounds(mTmpBounds, rotation);
                    intersectWithInsetsIfFits(mTmpNonDecorBounds, mTmpBounds,
                            compatInsets.mNonDecorInsets[rotation]);
                    intersectWithInsetsIfFits(mTmpStableBounds, mTmpBounds,
                            compatInsets.mStableInsets[rotation]);
                }
            }

            if (inOutConfig.screenWidthDp == Configuration.SCREEN_WIDTH_DP_UNDEFINED) {
+5 −0
Original line number Diff line number Diff line
@@ -57,6 +57,7 @@ import android.graphics.Rect;
import android.platform.test.annotations.Presubmit;
import android.util.MergedConfiguration;
import android.util.MutableBoolean;
import android.view.DisplayInfo;

import androidx.test.filters.MediumTest;

@@ -87,6 +88,10 @@ public class ActivityRecordTests extends ActivityTestsBase {

        doReturn(false).when(mService).isBooting();
        doReturn(true).when(mService).isBooted();

        final DisplayContent displayContent = mStack.getDisplay().mDisplayContent;
        doReturn(mock(DisplayPolicy.class)).when(displayContent).getDisplayPolicy();
        doReturn(mock(DisplayInfo.class)).when(displayContent).getDisplayInfo();
    }

    @Test
+24 −3
Original line number Diff line number Diff line
@@ -25,7 +25,10 @@ import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
import static android.util.DisplayMetrics.DENSITY_DEFAULT;
import static android.view.Surface.ROTATION_0;

import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import static com.android.server.wm.WindowContainer.POSITION_TOP;

import static org.hamcrest.Matchers.not;
@@ -35,6 +38,8 @@ import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;

import android.app.ActivityManager;
@@ -357,6 +362,7 @@ public class TaskRecordTests extends ActivityTestsBase {
        parentConfig.densityDpi = 400;
        parentConfig.screenHeightDp = 200; // 200 * 400 / 160 = 500px
        parentConfig.screenWidthDp = 100; // 100 * 400 / 160 = 250px
        parentConfig.windowConfiguration.setRotation(ROTATION_0);

        // Portrait bounds.
        inOutConfig.windowConfiguration.getBounds().set(0, 0, shortSide, longSide);
@@ -370,12 +376,27 @@ public class TaskRecordTests extends ActivityTestsBase {
        inOutConfig.setToDefaults();
        // Landscape bounds.
        inOutConfig.windowConfiguration.getBounds().set(0, 0, longSide, shortSide);

        // Setup the display with a top stable inset. The later assertion will ensure the inset is
        // excluded from screenHeightDp.
        final int statusBarHeight = 100;
        final DisplayContent displayContent = mock(DisplayContent.class);
        final DisplayPolicy policy = mock(DisplayPolicy.class);
        doAnswer(invocationOnMock -> {
            final Rect insets = invocationOnMock.<Rect>getArgument(0);
            insets.top = statusBarHeight;
            return null;
        }).when(policy).convertNonDecorInsetsToStableInsets(any(), eq(ROTATION_0));
        doReturn(policy).when(displayContent).getDisplayPolicy();
        doReturn(mock(DisplayInfo.class)).when(displayContent).getDisplayInfo();

        // Without limiting to be inside the parent bounds, the out screen size should keep relative
        // to the input bounds.
        task.computeConfigResourceOverrides(inOutConfig, parentConfig,
                false /* insideParentBounds */);
        final ActivityRecord.CompatDisplayInsets compatIntsets =
                new ActivityRecord.CompatDisplayInsets(displayContent);
        task.computeConfigResourceOverrides(inOutConfig, parentConfig, compatIntsets);

        assertEquals(shortSide * DENSITY_DEFAULT / parentConfig.densityDpi,
        assertEquals((shortSide - statusBarHeight) * DENSITY_DEFAULT / parentConfig.densityDpi,
                inOutConfig.screenHeightDp);
        assertEquals(longSide * DENSITY_DEFAULT / parentConfig.densityDpi,
                inOutConfig.screenWidthDp);