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

Commit 711ba268 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Fix letterbox in fixed rotation transform" into rvc-dev

parents 2e22c0e8 23e18a94
Loading
Loading
Loading
Loading
+56 −30
Original line number Original line Diff line number Diff line
@@ -1351,11 +1351,16 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
                mLetterbox.attachInput(w);
                mLetterbox.attachInput(w);
            }
            }
            getPosition(mTmpPoint);
            getPosition(mTmpPoint);
            // Get the bounds of the "space-to-fill". In multi-window mode, the task-level
            // Get the bounds of the "space-to-fill". The transformed bounds have the highest
            // represents this. In fullscreen-mode, the stack does (since the orientation letterbox
            // priority because the activity is launched in a rotated environment. In multi-window
            // is also applied to the task).
            // mode, the task-level represents this. In fullscreen-mode, the task container does
            Rect spaceToFill = (inMultiWindowMode() || getStack() == null)
            // (since the orientation letterbox is also applied to the task).
                    ? task.getDisplayedBounds() : getStack().getDisplayedBounds();
            final Rect transformedBounds = getFixedRotationTransformDisplayBounds();
            final Rect spaceToFill = transformedBounds != null
                    ? transformedBounds
                    : inMultiWindowMode()
                            ? task.getDisplayedBounds()
                            : getRootTask().getParent().getDisplayedBounds();
            mLetterbox.layout(spaceToFill, w.getFrameLw(), mTmpPoint);
            mLetterbox.layout(spaceToFill, w.getFrameLw(), mTmpPoint);
        } else if (mLetterbox != null) {
        } else if (mLetterbox != null) {
            mLetterbox.hide();
            mLetterbox.hide();
@@ -6362,43 +6367,64 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
        if (mCompatDisplayInsets != null) {
        if (mCompatDisplayInsets != null) {
            resolveSizeCompatModeConfiguration(newParentConfiguration);
            resolveSizeCompatModeConfiguration(newParentConfiguration);
        } else {
        } else {
            if (inMultiWindowMode()) {
                // We ignore activities' requested orientation in multi-window modes. Task level may
                // We ignore activities' requested orientation in multi-window modes. Task level may
                // take them into consideration when calculating bounds.
                // take them into consideration when calculating bounds.
            if (inMultiWindowMode()) {
                resolvedConfig.orientation = Configuration.ORIENTATION_UNDEFINED;
                resolvedConfig.orientation = Configuration.ORIENTATION_UNDEFINED;
                // If the activity has requested override bounds, the configuration needs to be
                // computed accordingly.
                if (!matchParentBounds()) {
                    task.computeConfigResourceOverrides(resolvedConfig, newParentConfiguration);
                }
            } else {
                resolveFullscreenConfiguration(newParentConfiguration);
            }
        }
        }

        // Assign configuration sequence number into hierarchy because there is a different way than
        // ensureActivityConfiguration() in this class that uses configuration in WindowState during
        // layout traversals.
        mConfigurationSeq = Math.max(++mConfigurationSeq, 1);
        getResolvedOverrideConfiguration().seq = mConfigurationSeq;
    }

    /**
     * Resolves the configuration of activity in fullscreen mode. If the bounds are restricted by
     * aspect ratio, the position will be centered horizontally in parent's app bounds to balance
     * the visual appearance. The policy of aspect ratio has higher priority than the requested
     * override bounds.
     */
    private void resolveFullscreenConfiguration(Configuration newParentConfiguration) {
        final Configuration resolvedConfig = getResolvedOverrideConfiguration();
        final Rect parentAppBounds = newParentConfiguration.windowConfiguration.getAppBounds();
        final Rect parentAppBounds = newParentConfiguration.windowConfiguration.getAppBounds();
        final Rect parentBounds = newParentConfiguration.windowConfiguration.getBounds();
        final Rect parentBounds = newParentConfiguration.windowConfiguration.getBounds();
            // Use tmp bounds to calculate aspect ratio so we can know whether the activity should
        final Rect resolvedBounds = resolvedConfig.windowConfiguration.getBounds();
            // use restricted size (resolvedBounds may be the requested override bounds).
        // Use tmp bounds to calculate aspect ratio so we can know whether the activity should use
        // restricted size (resolved bounds may be the requested override bounds).
        mTmpBounds.setEmpty();
        mTmpBounds.setEmpty();
        applyAspectRatio(mTmpBounds, parentAppBounds, parentBounds);
        applyAspectRatio(mTmpBounds, parentAppBounds, parentBounds);
            // If the out bounds is not empty, it means the activity cannot fill parent's app
        // If the out bounds is not empty, it means the activity cannot fill parent's app bounds,
            // bounds, then the relative configuration (e.g. screen size, layout) needs to be
        // then there is space to be centered.
            // resolved according to the bounds.
        final boolean needToBeCentered = !mTmpBounds.isEmpty();
            if (!mTmpBounds.isEmpty()) {
        if (needToBeCentered) {
                final Rect resolvedBounds = resolvedConfig.windowConfiguration.getBounds();
            resolvedBounds.set(mTmpBounds);
            resolvedBounds.set(mTmpBounds);
                // Exclude the horizontal decor area because the activity will be centered
            // Exclude the horizontal decor area.
                // horizontally in parent's app bounds to balance the visual appearance.
            resolvedBounds.left = parentAppBounds.left;
            resolvedBounds.left = parentAppBounds.left;
        }
        if (!resolvedBounds.isEmpty() && !resolvedBounds.equals(parentBounds)) {
            // Compute the configuration based on the resolved bounds. If aspect ratio doesn't
            // restrict, the bounds should be the requested override bounds.
            task.computeConfigResourceOverrides(resolvedConfig, newParentConfiguration,
            task.computeConfigResourceOverrides(resolvedConfig, newParentConfiguration,
                    getFixedRotationTransformDisplayInfo());
                    getFixedRotationTransformDisplayInfo());
        }
        if (needToBeCentered) {
            // Offset to center relative to parent's app bounds.
            final int offsetX = getHorizontalCenterOffset(
            final int offsetX = getHorizontalCenterOffset(
                    parentAppBounds.width(), resolvedBounds.width());
                    parentAppBounds.width(), resolvedBounds.width());
                if (offsetX > 0) {
            offsetBounds(resolvedConfig, offsetX, 0 /* offsetY */);
                    offsetBounds(resolvedConfig, offsetX - resolvedBounds.left, 0 /* offsetY */);
                }
        }
        }
    }
    }


        // Assign configuration sequence number into hierarchy because there is a different way than
        // ensureActivityConfiguration() in this class that uses configuration in WindowState during
        // layout traversals.
        mConfigurationSeq = Math.max(++mConfigurationSeq, 1);
        getResolvedOverrideConfiguration().seq = mConfigurationSeq;
    }

    /**
    /**
     * Resolves consistent screen configuration for orientation and rotation changes without
     * Resolves consistent screen configuration for orientation and rotation changes without
     * inheriting the parent bounds.
     * inheriting the parent bounds.
@@ -6507,7 +6533,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
        // Above coordinates are in "@" space, now place "*" and "#" to screen space.
        // Above coordinates are in "@" space, now place "*" and "#" to screen space.
        final int screenPosX = parentAppBounds.left + offsetX;
        final int screenPosX = parentAppBounds.left + offsetX;
        final int screenPosY = parentBounds.top;
        final int screenPosY = parentBounds.top;
        if (screenPosX > 0 || screenPosY > 0) {
        if (screenPosX != 0 || screenPosY != 0) {
            if (mSizeCompatBounds != null) {
            if (mSizeCompatBounds != null) {
                mSizeCompatBounds.offset(screenPosX, screenPosY);
                mSizeCompatBounds.offset(screenPosX, screenPosY);
            }
            }
+19 −3
Original line number Original line Diff line number Diff line
@@ -2127,14 +2127,26 @@ class Task extends WindowContainer<WindowContainer> {
        intersectWithInsetsIfFits(outStableBounds, mTmpBounds, mTmpInsets);
        intersectWithInsetsIfFits(outStableBounds, mTmpBounds, mTmpInsets);
    }
    }


    /**
     * Forces the app bounds related configuration can be computed by
     * {@link #computeConfigResourceOverrides(Configuration, Configuration, DisplayInfo,
     * ActivityRecord.CompatDisplayInsets)}.
     */
    private static void invalidateAppBoundsConfig(@NonNull Configuration inOutConfig) {
        final Rect appBounds = inOutConfig.windowConfiguration.getAppBounds();
        if (appBounds != null) {
            appBounds.setEmpty();
        }
        inOutConfig.screenWidthDp = Configuration.SCREEN_WIDTH_DP_UNDEFINED;
        inOutConfig.screenHeightDp = Configuration.SCREEN_HEIGHT_DP_UNDEFINED;
    }

    void computeConfigResourceOverrides(@NonNull Configuration inOutConfig,
    void computeConfigResourceOverrides(@NonNull Configuration inOutConfig,
            @NonNull Configuration parentConfig, @Nullable DisplayInfo overrideDisplayInfo) {
            @NonNull Configuration parentConfig, @Nullable DisplayInfo overrideDisplayInfo) {
        if (overrideDisplayInfo != null) {
        if (overrideDisplayInfo != null) {
            // Make sure the screen related configs can be computed by the provided display info.
            // Make sure the screen related configs can be computed by the provided display info.
            inOutConfig.windowConfiguration.setAppBounds(null);
            inOutConfig.screenLayout = Configuration.SCREENLAYOUT_UNDEFINED;
            inOutConfig.screenLayout = Configuration.SCREENLAYOUT_UNDEFINED;
            inOutConfig.screenWidthDp = Configuration.SCREEN_WIDTH_DP_UNDEFINED;
            invalidateAppBoundsConfig(inOutConfig);
            inOutConfig.screenHeightDp = Configuration.SCREEN_HEIGHT_DP_UNDEFINED;
        }
        }
        computeConfigResourceOverrides(inOutConfig, parentConfig, overrideDisplayInfo,
        computeConfigResourceOverrides(inOutConfig, parentConfig, overrideDisplayInfo,
                null /* compatInsets */);
                null /* compatInsets */);
@@ -2149,6 +2161,10 @@ class Task extends WindowContainer<WindowContainer> {
    void computeConfigResourceOverrides(@NonNull Configuration inOutConfig,
    void computeConfigResourceOverrides(@NonNull Configuration inOutConfig,
            @NonNull Configuration parentConfig,
            @NonNull Configuration parentConfig,
            @Nullable ActivityRecord.CompatDisplayInsets compatInsets) {
            @Nullable ActivityRecord.CompatDisplayInsets compatInsets) {
        if (compatInsets != null) {
            // Make sure the app bounds can be computed by the compat insets.
            invalidateAppBoundsConfig(inOutConfig);
        }
        computeConfigResourceOverrides(inOutConfig, parentConfig, null /* overrideDisplayInfo */,
        computeConfigResourceOverrides(inOutConfig, parentConfig, null /* overrideDisplayInfo */,
                compatInsets);
                compatInsets);
    }
    }
+28 −7
Original line number Original line Diff line number Diff line
@@ -107,10 +107,16 @@ public class SizeCompatTests extends ActivityTestsBase {
        setUpApp(display);
        setUpApp(display);


        // Put app window into freeform and then make it a compat app.
        // Put app window into freeform and then make it a compat app.
        mTask.setBounds(100, 100, 400, 600);
        final Rect bounds = new Rect(100, 100, 400, 600);
        mTask.setBounds(bounds);
        prepareUnresizable(-1.f /* maxAspect */, SCREEN_ORIENTATION_PORTRAIT);
        prepareUnresizable(-1.f /* maxAspect */, SCREEN_ORIENTATION_PORTRAIT);
        assertEquals(bounds, mActivity.getBounds());

        // The activity should be able to accept negative x position [-150, 100 - 150, 600].
        final int dx = bounds.left + bounds.width() / 2;
        mTask.setBounds(bounds.left - dx, bounds.top, bounds.right - dx, bounds.bottom);
        assertEquals(mTask.getBounds(), mActivity.getBounds());


        final Rect bounds = new Rect(mActivity.getBounds());
        final int density = mActivity.getConfiguration().densityDpi;
        final int density = mActivity.getConfiguration().densityDpi;


        // change display configuration to fullscreen
        // change display configuration to fullscreen
@@ -231,11 +237,7 @@ public class SizeCompatTests extends ActivityTestsBase {
        // The position should be horizontal centered.
        // The position should be horizontal centered.
        assertEquals((displayWidth - bounds.width()) / 2, bounds.left);
        assertEquals((displayWidth - bounds.width()) / 2, bounds.left);


        final WindowTestUtils.TestWindowState w = new WindowTestUtils.TestWindowState(
        mActivity.mDisplayContent.mInputMethodTarget = addWindowToActivity(mActivity);
                mService.mWindowManager, mock(Session.class), new TestIWindow(),
                new WindowManager.LayoutParams(), mActivity);
        mActivity.addWindow(w);
        mActivity.mDisplayContent.mInputMethodTarget = w;
        // Make sure IME cannot attach to the app, otherwise IME window will also be shifted.
        // Make sure IME cannot attach to the app, otherwise IME window will also be shifted.
        assertFalse(mActivity.mDisplayContent.isImeAttachedToApp());
        assertFalse(mActivity.mDisplayContent.isImeAttachedToApp());
    }
    }
@@ -475,6 +477,25 @@ public class SizeCompatTests extends ActivityTestsBase {
        assertEquals((int) (dw * maxAspect), mActivity.getBounds().width());
        assertEquals((int) (dw * maxAspect), mActivity.getBounds().width());
        // The bounds should be horizontal centered: (2500-1900)/2=350.
        // The bounds should be horizontal centered: (2500-1900)/2=350.
        assertEquals((dh - mActivity.getBounds().width()) / 2, mActivity.getBounds().left);
        assertEquals((dh - mActivity.getBounds().width()) / 2, mActivity.getBounds().left);

        // The letterbox needs a main window to layout.
        addWindowToActivity(mActivity);
        // Compute the frames of the window and invoke {@link ActivityRecord#layoutLetterbox}.
        mActivity.mRootWindowContainer.performSurfacePlacement(false /* recoveringMemory */);
        // The letterbox insets should be [350, 0 - 350, 0].
        assertEquals(new Rect(mActivity.getBounds().left, 0, dh - mActivity.getBounds().right, 0),
                mActivity.getLetterboxInsets());
    }

    private WindowState addWindowToActivity(ActivityRecord activity) {
        final WindowManager.LayoutParams params = new WindowManager.LayoutParams();
        params.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
        final WindowTestUtils.TestWindowState w = new WindowTestUtils.TestWindowState(
                mService.mWindowManager, mock(Session.class), new TestIWindow(), params, mActivity);
        WindowTestsBase.makeWindowVisible(w);
        w.mWinAnimator.mDrawState = WindowStateAnimator.HAS_DRAWN;
        mActivity.addWindow(w);
        return w;
    }
    }


    /**
    /**