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

Commit a2073989 authored by Yunfan Chen's avatar Yunfan Chen Committed by Android (Google) Code Review
Browse files

Merge changes from topic "decouple_config" into main

* changes:
  Override app bounds related configuration fields for legacy app
  Decouple the insets from configuration
parents 79258c44 c9981489
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -1518,6 +1518,16 @@ public class ActivityInfo extends ComponentInfo implements Parcelable {
    @EnabledSince(targetSdkVersion = Build.VERSION_CODES.S)
    private static final long CHECK_MIN_WIDTH_HEIGHT_FOR_MULTI_WINDOW = 197654537L;

    /**
     * The activity is targeting a SDK version that should receive the changed behavior of
     * configuration insets decouple.
     *
     * @hide
     */
    @ChangeId
    @EnabledSince(targetSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM)
    public static final long INSETS_DECOUPLED_CONFIGURATION_ENFORCED = 151861875L;

    /**
     * Optional set of a certificates identifying apps that are allowed to embed this activity. From
     * the "knownActivityEmbeddingCerts" attribute.
+94 −1
Original line number Diff line number Diff line
@@ -50,6 +50,7 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.app.WindowConfiguration.activityTypeToString;
import static android.app.WindowConfiguration.isFloating;
import static android.app.admin.DevicePolicyResources.Drawables.Source.PROFILE_SWITCH_ANIMATION;
import static android.app.admin.DevicePolicyResources.Drawables.Style.OUTLINE;
import static android.app.admin.DevicePolicyResources.Drawables.WORK_PROFILE_ICON;
@@ -75,6 +76,7 @@ import static android.content.pm.ActivityInfo.FLAG_NO_HISTORY;
import static android.content.pm.ActivityInfo.FLAG_SHOW_FOR_ALL_USERS;
import static android.content.pm.ActivityInfo.FLAG_STATE_NOT_NEEDED;
import static android.content.pm.ActivityInfo.FLAG_TURN_SCREEN_ON;
import static android.content.pm.ActivityInfo.INSETS_DECOUPLED_CONFIGURATION_ENFORCED;
import static android.content.pm.ActivityInfo.LAUNCH_MULTIPLE;
import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_INSTANCE;
import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TASK;
@@ -332,6 +334,7 @@ import android.service.contentcapture.ActivityEvent;
import android.service.dreams.DreamActivity;
import android.service.voice.IVoiceInteractionSession;
import android.util.ArraySet;
import android.util.DisplayMetrics;
import android.util.EventLog;
import android.util.Log;
import android.util.MergedConfiguration;
@@ -8481,6 +8484,9 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
        // and back which can cause visible issues (see b/184078928).
        final int parentWindowingMode =
                newParentConfiguration.windowConfiguration.getWindowingMode();

        applySizeOverrideIfNeeded(newParentConfiguration, parentWindowingMode, resolvedConfig);

        final boolean isFixedOrientationLetterboxAllowed =
                parentWindowingMode == WINDOWING_MODE_MULTI_WINDOW
                        || parentWindowingMode == WINDOWING_MODE_FULLSCREEN
@@ -8579,6 +8585,87 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
        logAppCompatState();
    }

    /**
     * If necessary, override configuration fields related to app bounds.
     * This will happen when the app is targeting SDK earlier than 35.
     * The insets and configuration has decoupled since SDK level 35, to make the system
     * compatible to existing apps, override the configuration with legacy metrics. In legacy
     * metrics, fields such as appBounds will exclude some of the system bar areas.
     * The override contains all potentially affected fields in Configuration, including
     * screenWidthDp, screenHeightDp, smallestScreenWidthDp, and orientation.
     * All overrides to those fields should be in this method.
     */
    private void applySizeOverrideIfNeeded(Configuration newParentConfiguration,
            int parentWindowingMode, Configuration inOutConfig) {
        if (mDisplayContent == null) {
            return;
        }
        final Rect fullBounds = newParentConfiguration.windowConfiguration.getAppBounds();
        int rotation = newParentConfiguration.windowConfiguration.getRotation();
        if (rotation == ROTATION_UNDEFINED && !isFixedRotationTransforming()) {
            rotation = mDisplayContent.getRotation();
        }
        if (!mWmService.mFlags.mInsetsDecoupledConfiguration
                || info.isChangeEnabled(INSETS_DECOUPLED_CONFIGURATION_ENFORCED)
                || getCompatDisplayInsets() != null
                || isFloating(parentWindowingMode) || fullBounds == null
                || fullBounds.isEmpty() || rotation == ROTATION_UNDEFINED) {
            // If the insets configuration decoupled logic is not enabled for the app, or the app
            // already has a compat override, or the context doesn't contain enough info to
            // calculate the override, skip the override.
            return;
        }

        // Override starts here.
        final Rect stableInsets = mDisplayContent.getDisplayPolicy().getDecorInsetsInfo(
                rotation, fullBounds.width(), fullBounds.height()).mLegacyConfigInsets;
        // This should be the only place override the configuration for ActivityRecord. Override
        // the value if not calculated yet.
        Rect outAppBounds = inOutConfig.windowConfiguration.getAppBounds();
        if (outAppBounds == null || outAppBounds.isEmpty()) {
            inOutConfig.windowConfiguration.setAppBounds(fullBounds);
            outAppBounds = inOutConfig.windowConfiguration.getAppBounds();
            outAppBounds.inset(stableInsets);
        }
        float density = inOutConfig.densityDpi;
        if (density == Configuration.DENSITY_DPI_UNDEFINED) {
            density = newParentConfiguration.densityDpi;
        }
        density *= DisplayMetrics.DENSITY_DEFAULT_SCALE;
        if (inOutConfig.screenWidthDp == Configuration.SCREEN_WIDTH_DP_UNDEFINED) {
            final int overrideScreenWidthDp = (int) (outAppBounds.width() / density + 0.5f);
            inOutConfig.screenWidthDp =
                    Math.min(overrideScreenWidthDp, newParentConfiguration.screenWidthDp);
        }
        if (inOutConfig.screenHeightDp == Configuration.SCREEN_HEIGHT_DP_UNDEFINED) {
            final int overrideScreenHeightDp =
                    (int) (outAppBounds.height() / density + 0.5f);
            inOutConfig.screenHeightDp =
                    Math.min(overrideScreenHeightDp, newParentConfiguration.screenHeightDp);
        }
        if (inOutConfig.smallestScreenWidthDp
                == Configuration.SMALLEST_SCREEN_WIDTH_DP_UNDEFINED
                && parentWindowingMode == WINDOWING_MODE_FULLSCREEN) {
            // For the case of PIP transition and multi-window environment, the
            // smallestScreenWidthDp is handled already. Override only if the app is in
            // fullscreen.
            final boolean rotated = (rotation == ROTATION_90 || rotation == ROTATION_270);
            DisplayInfo info = new DisplayInfo();
            mDisplayContent.getDisplay().getDisplayInfo(info);
            mDisplayContent.computeSizeRanges(info, rotated, info.logicalWidth,
                    info.logicalHeight, mDisplayContent.getDisplayMetrics().density,
                    inOutConfig, true /* legacyConfig */);
        }

        // It's possible that screen size will be considered in different orientation with or
        // without considering the system bar insets. Override orientation as well.
        if (inOutConfig.orientation == ORIENTATION_UNDEFINED) {
            inOutConfig.orientation =
                    (inOutConfig.screenWidthDp <= inOutConfig.screenHeightDp)
                            ? ORIENTATION_PORTRAIT : ORIENTATION_LANDSCAPE;
        }
    }

    /**
     * @return The orientation to use to understand if reachability is enabled.
     */
@@ -8832,6 +8919,11 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
        if (mDisplayContent == null) {
            return true;
        }
        if (mWmService.mFlags.mInsetsDecoupledConfiguration
                && info.isChangeEnabled(INSETS_DECOUPLED_CONFIGURATION_ENFORCED)) {
            // No insets should be considered any more.
            return true;
        }
        // Only need to make changes if activity sets an orientation
        final int requestedOrientation = getRequestedConfigurationOrientation();
        if (requestedOrientation == ORIENTATION_UNDEFINED) {
@@ -8846,7 +8938,8 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
                : mDisplayContent.getDisplayInfo();
        final Task task = getTask();
        task.calculateInsetFrames(mTmpBounds /* outNonDecorBounds */,
                outStableBounds /* outStableBounds */, parentBounds /* bounds */, di);
                outStableBounds /* outStableBounds */, parentBounds /* bounds */, di,
                true /* useLegacyInsetsForStableBounds */);
        final int orientationWithInsets = outStableBounds.height() >= outStableBounds.width()
                ? ORIENTATION_PORTRAIT : ORIENTATION_LANDSCAPE;
        // If orientation does not match the orientation with insets applied, then a
+34 −11
Original line number Diff line number Diff line
@@ -2302,7 +2302,8 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
            mDisplayInfo.flags &= ~Display.FLAG_SCALING_DISABLED;
        }

        computeSizeRanges(mDisplayInfo, rotated, dw, dh, mDisplayMetrics.density, outConfig);
        computeSizeRanges(mDisplayInfo, rotated, dw, dh, mDisplayMetrics.density, outConfig,
                false /* legacyConfig */);

        setDisplayInfoOverride();

@@ -2438,7 +2439,8 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
        displayInfo.appHeight = appBounds.height();
        final DisplayCutout displayCutout = calculateDisplayCutoutForRotation(rotation);
        displayInfo.displayCutout = displayCutout.isEmpty() ? null : displayCutout;
        computeSizeRanges(displayInfo, rotated, dw, dh, mDisplayMetrics.density, outConfig);
        computeSizeRanges(displayInfo, rotated, dw, dh, mDisplayMetrics.density, outConfig,
                false /* legacyConfig */);
        return displayInfo;
    }

@@ -2602,8 +2604,21 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
        return curSize;
    }

    private void computeSizeRanges(DisplayInfo displayInfo, boolean rotated,
            int dw, int dh, float density, Configuration outConfig) {
    /**
     * Compute size range related fields of DisplayInfo and Configuration based on provided info.
     * The fields usually contain word such as smallest or largest.
     *
     * @param displayInfo In-out display info to compute the result.
     * @param rotated Whether the display is rotated.
     * @param dw Display Width in current rotation.
     * @param dh Display Height in current rotation.
     * @param density Display density.
     * @param outConfig The output configuration to
     * @param legacyConfig Whether we need to report the legacy result, which is excluding system
     *                     decorations.
     */
    void computeSizeRanges(DisplayInfo displayInfo, boolean rotated,
            int dw, int dh, float density, Configuration outConfig, boolean legacyConfig) {

        // We need to determine the smallest width that will occur under normal
        // operation.  To this, start with the base screen size and compute the
@@ -2621,10 +2636,10 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
        displayInfo.smallestNominalAppHeight = 1<<30;
        displayInfo.largestNominalAppWidth = 0;
        displayInfo.largestNominalAppHeight = 0;
        adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_0, unrotDw, unrotDh);
        adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_90, unrotDh, unrotDw);
        adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_180, unrotDw, unrotDh);
        adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_270, unrotDh, unrotDw);
        adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_0, unrotDw, unrotDh, legacyConfig);
        adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_90, unrotDh, unrotDw, legacyConfig);
        adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_180, unrotDw, unrotDh, legacyConfig);
        adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_270, unrotDh, unrotDw, legacyConfig);

        if (outConfig == null) {
            return;
@@ -2633,11 +2648,19 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
                (int) (displayInfo.smallestNominalAppWidth / density + 0.5f);
    }

    private void adjustDisplaySizeRanges(DisplayInfo displayInfo, int rotation, int dw, int dh) {
    private void adjustDisplaySizeRanges(DisplayInfo displayInfo, int rotation, int dw, int dh,
            boolean legacyConfig) {
        final DisplayPolicy.DecorInsets.Info info = mDisplayPolicy.getDecorInsetsInfo(
                rotation, dw, dh);
        final int w = info.mConfigFrame.width();
        final int h = info.mConfigFrame.height();
        final int w;
        final int h;
        if (!legacyConfig) {
            w = info.mConfigFrame.width();
            h = info.mConfigFrame.height();
        } else {
            w = info.mLegacyConfigFrame.width();
            h = info.mLegacyConfigFrame.height();
        }
        if (w < displayInfo.smallestNominalAppWidth) {
            displayInfo.smallestNominalAppWidth = w;
        }
+27 −3
Original line number Diff line number Diff line
@@ -1917,6 +1917,11 @@ public class DisplayPolicy {
             */
            final Rect mConfigInsets = new Rect();

            /**
             * Legacy value of mConfigInsets for app compatibility purpose.
             */
            final Rect mLegacyConfigInsets = new Rect();

            /** The display frame available after excluding {@link #mNonDecorInsets}. */
            final Rect mNonDecorFrame = new Rect();

@@ -1927,6 +1932,11 @@ public class DisplayPolicy {
             */
            final Rect mConfigFrame = new Rect();

            /**
             * Legacy value of mConfigFrame for app compatibility purpose.
             */
            final Rect mLegacyConfigFrame = new Rect();

            private boolean mNeedUpdate = true;

            InsetsState update(DisplayContent dc, int rotation, int w, int h) {
@@ -1937,15 +1947,26 @@ public class DisplayPolicy {
                final Rect displayFrame = insetsState.getDisplayFrame();
                final Insets decor = insetsState.calculateInsets(displayFrame,
                        dc.mWmService.mDecorTypes, true /* ignoreVisibility */);
                final Insets configInsets = insetsState.calculateInsets(displayFrame,
                        dc.mWmService.mConfigTypes, true /* ignoreVisibility */);
                final Insets configInsets = dc.mWmService.mConfigTypes == dc.mWmService.mDecorTypes
                        ? decor
                        : insetsState.calculateInsets(displayFrame, dc.mWmService.mConfigTypes,
                                true /* ignoreVisibility */);
                final Insets legacyConfigInsets = dc.mWmService.mConfigTypes
                        == dc.mWmService.mLegacyConfigTypes
                        ? configInsets
                        : insetsState.calculateInsets(displayFrame,
                                dc.mWmService.mLegacyConfigTypes, true /* ignoreVisibility */);
                mNonDecorInsets.set(decor.left, decor.top, decor.right, decor.bottom);
                mConfigInsets.set(configInsets.left, configInsets.top, configInsets.right,
                        configInsets.bottom);
                mLegacyConfigInsets.set(legacyConfigInsets.left, legacyConfigInsets.top,
                        legacyConfigInsets.right, legacyConfigInsets.bottom);
                mNonDecorFrame.set(displayFrame);
                mNonDecorFrame.inset(mNonDecorInsets);
                mConfigFrame.set(displayFrame);
                mConfigFrame.inset(mConfigInsets);
                mLegacyConfigFrame.set(displayFrame);
                mLegacyConfigFrame.inset(mLegacyConfigInsets);
                mNeedUpdate = false;
                return insetsState;
            }
@@ -1953,8 +1974,10 @@ public class DisplayPolicy {
            void set(Info other) {
                mNonDecorInsets.set(other.mNonDecorInsets);
                mConfigInsets.set(other.mConfigInsets);
                mLegacyConfigInsets.set(other.mLegacyConfigInsets);
                mNonDecorFrame.set(other.mNonDecorFrame);
                mConfigFrame.set(other.mConfigFrame);
                mLegacyConfigFrame.set(other.mLegacyConfigFrame);
                mNeedUpdate = false;
            }

@@ -2066,7 +2089,8 @@ public class DisplayPolicy {
        final DecorInsets.Info newInfo = mDecorInsets.mTmpInfo;
        final InsetsState newInsetsState = newInfo.update(mDisplayContent, rotation, dw, dh);
        final DecorInsets.Info currentInfo = getDecorInsetsInfo(rotation, dw, dh);
        if (newInfo.mConfigFrame.equals(currentInfo.mConfigFrame)) {
        if (newInfo.mConfigFrame.equals(currentInfo.mConfigFrame)
                && newInfo.mLegacyConfigFrame.equals(currentInfo.mLegacyConfigFrame)) {
            // Even if the config frame is not changed in current rotation, it may change the
            // insets in other rotations if the frame of insets source is changed.
            final InsetsState currentInsetsState = mDisplayContent.mDisplayFrames.mInsetsState;
+10 −3
Original line number Diff line number Diff line
@@ -2307,7 +2307,8 @@ class TaskFragment extends WindowContainer<WindowContainer> {
                // area, i.e. the screen area without the system bars.
                // The non decor inset are areas that could never be removed in Honeycomb. See
                // {@link WindowManagerPolicy#getNonDecorInsetsLw}.
                calculateInsetFrames(mTmpNonDecorBounds, mTmpStableBounds, mTmpFullBounds, di);
                calculateInsetFrames(mTmpNonDecorBounds, mTmpStableBounds, mTmpFullBounds, di,
                        false /* useLegacyInsetsForStableBounds */);
            } else {
                // Apply the given non-decor and stable insets to calculate the corresponding bounds
                // for screen size of configuration.
@@ -2405,9 +2406,11 @@ class TaskFragment extends WindowContainer<WindowContainer> {
     * @param outNonDecorBounds where to place bounds with non-decor insets applied.
     * @param outStableBounds where to place bounds with stable insets applied.
     * @param bounds the bounds to inset.
     * @param useLegacyInsetsForStableBounds {@code true} if we need to use the legacy insets frame
     *                for apps targeting U or before when calculating stable bounds.
     */
    void calculateInsetFrames(Rect outNonDecorBounds, Rect outStableBounds, Rect bounds,
            DisplayInfo displayInfo) {
            DisplayInfo displayInfo, boolean useLegacyInsetsForStableBounds) {
        outNonDecorBounds.set(bounds);
        outStableBounds.set(bounds);
        if (mDisplayContent == null) {
@@ -2419,7 +2422,11 @@ class TaskFragment extends WindowContainer<WindowContainer> {
        final DisplayPolicy.DecorInsets.Info info = policy.getDecorInsetsInfo(
                displayInfo.rotation, displayInfo.logicalWidth, displayInfo.logicalHeight);
        intersectWithInsetsIfFits(outNonDecorBounds, mTmpBounds, info.mNonDecorInsets);
        if (!useLegacyInsetsForStableBounds) {
            intersectWithInsetsIfFits(outStableBounds, mTmpBounds, info.mConfigInsets);
        } else {
            intersectWithInsetsIfFits(outStableBounds, mTmpBounds, info.mLegacyConfigInsets);
        }
    }

    /**
Loading