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

Commit de531310 authored by Massimo Carli's avatar Massimo Carli
Browse files

Fix Letterboxing for Transparent Activities

We want a not resizable transparent activity to inherits
the constraints from the activity below. This allows the
transparent activity to be letterboxed.
The specific logic for transparent activities is enabled
when the config_letterboxIsEnabledForTranslucentActivities
flag is true.

Fixes: 220703089
Test: Run `atest SizeCompatTests` with the following tests:
  testApplyStrategyToTranslucentActivities
  testTranslucentActivitiesDontGoInSizeCompactMode
  testNotApplyStrategyToTranslucentActivitiesWithDifferentUid
  testApplyStrategyToMultipleTranslucentActivities

Change-Id: I6b5e8517ae8286f7543c3f57c158276aab6cfbfc
parent 1b89cdbd
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -5300,6 +5300,10 @@
    <!-- Whether using split screen aspect ratio as a default aspect ratio for unresizable apps. -->
    <bool name="config_letterboxIsSplitScreenAspectRatioForUnresizableAppsEnabled">false</bool>

    <!-- Whether the specific behaviour for translucent activities letterboxing is enabled.
         TODO(b/255532890) Enable when ignoreOrientationRequest is set -->
    <bool name="config_letterboxIsEnabledForTranslucentActivities">false</bool>

    <!-- Whether a camera compat controller is enabled to allow the user to apply or revert
         treatment for stretched issues in camera viewfinder. -->
    <bool name="config_isCameraCompatControlForStretchedIssuesEnabled">false</bool>
+3 −0
Original line number Diff line number Diff line
@@ -4401,6 +4401,9 @@
  <!-- Set to true to make assistant show in front of the dream/screensaver. -->
  <java-symbol type="bool" name="config_assistantOnTopOfDream"/>

  <!-- Set to true to enable letterboxing on translucent activities. -->
  <java-symbol type="bool" name="config_letterboxIsEnabledForTranslucentActivities" />

  <java-symbol type="string" name="config_overrideComponentUiPackage" />

  <java-symbol type="string" name="notification_channel_network_status" />
+56 −6
Original line number Diff line number Diff line
@@ -1239,8 +1239,8 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
                pw.println(prefix + "supportsEnterPipOnTaskSwitch: "
                        + supportsEnterPipOnTaskSwitch);
            }
            if (info.getMaxAspectRatio() != 0) {
                pw.println(prefix + "maxAspectRatio=" + info.getMaxAspectRatio());
            if (getMaxAspectRatio() != 0) {
                pw.println(prefix + "maxAspectRatio=" + getMaxAspectRatio());
            }
            final float minAspectRatio = getMinAspectRatio();
            if (minAspectRatio != 0) {
@@ -1590,6 +1590,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
                newParent.setResumedActivity(this, "onParentChanged");
                mImeInsetsFrozenUntilStartInput = false;
            }
            mLetterboxUiController.onActivityParentChanged(newParent);
        }

        if (rootTask != null && rootTask.topRunningActivity() == this) {
@@ -7676,6 +7677,15 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
    @Configuration.Orientation
    @Override
    int getRequestedConfigurationOrientation(boolean forDisplay) {
        if (mLetterboxUiController.hasInheritedOrientation()) {
            final RootDisplayArea root = getRootDisplayArea();
            if (forDisplay && root != null && root.isOrientationDifferentFromDisplay()) {
                return ActivityInfo.reverseOrientation(
                        mLetterboxUiController.getInheritedOrientation());
            } else {
                return mLetterboxUiController.getInheritedOrientation();
            }
        }
        if (mOrientation == SCREEN_ORIENTATION_BEHIND && task != null) {
            // We use Task here because we want to be consistent with what happens in
            // multi-window mode where other tasks orientations are ignored.
@@ -7803,6 +7813,9 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A

    @Nullable
    CompatDisplayInsets getCompatDisplayInsets() {
        if (mLetterboxUiController.hasInheritedLetterboxBehavior()) {
            return mLetterboxUiController.getInheritedCompatDisplayInsets();
        }
        return mCompatDisplayInsets;
    }

@@ -7885,6 +7898,10 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A

    // TODO(b/36505427): Consider moving this method and similar ones to ConfigurationContainer.
    private void updateCompatDisplayInsets() {
        if (mLetterboxUiController.hasInheritedLetterboxBehavior()) {
            mCompatDisplayInsets =  mLetterboxUiController.getInheritedCompatDisplayInsets();
            return;
        }
        if (mCompatDisplayInsets != null || !shouldCreateCompatDisplayInsets()) {
            // The override configuration is set only once in size compatibility mode.
            return;
@@ -7946,6 +7963,9 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A

    @Override
    float getCompatScale() {
        if (mLetterboxUiController.hasInheritedLetterboxBehavior()) {
            return mLetterboxUiController.getInheritedSizeCompatScale();
        }
        return hasSizeCompatBounds() ? mSizeCompatScale : super.getCompatScale();
    }

@@ -8054,6 +8074,16 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
        logAppCompatState();
    }

    /**
     * @return The orientation to use to understand if reachability is enabled.
     */
    @ActivityInfo.ScreenOrientation
    int getOrientationForReachability() {
        return mLetterboxUiController.hasInheritedLetterboxBehavior()
                ? mLetterboxUiController.getInheritedOrientation()
                : getRequestedConfigurationOrientation();
    }

    /**
     * Returns whether activity bounds are letterboxed.
     *
@@ -8094,6 +8124,10 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
        if (!ignoreVisibility && !mVisibleRequested) {
            return APP_COMPAT_STATE_CHANGED__STATE__NOT_VISIBLE;
        }
        // TODO(b/256564921): Investigate if we need new metrics for translucent activities
        if (mLetterboxUiController.hasInheritedLetterboxBehavior()) {
            return mLetterboxUiController.getInheritedAppCompatState();
        }
        if (mInSizeCompatModeForBounds) {
            return APP_COMPAT_STATE_CHANGED__STATE__LETTERBOXED_FOR_SIZE_COMPAT_MODE;
        }
@@ -8564,6 +8598,11 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
    }

    private boolean isInSizeCompatModeForBounds(final Rect appBounds, final Rect containerBounds) {
        if (mLetterboxUiController.hasInheritedLetterboxBehavior()) {
            // To avoid wrong app behaviour, we decided to disable SCM when a translucent activity
            // is letterboxed.
            return false;
        }
        final int appWidth = appBounds.width();
        final int appHeight = appBounds.height();
        final int containerAppWidth = containerBounds.width();
@@ -8584,10 +8623,11 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A

        // The rest of the condition is that only one side is smaller than the container, but it
        // still needs to exclude the cases where the size is limited by the fixed aspect ratio.
        if (info.getMaxAspectRatio() > 0) {
        final float maxAspectRatio = getMaxAspectRatio();
        if (maxAspectRatio > 0) {
            final float aspectRatio = (0.5f + Math.max(appWidth, appHeight))
                    / Math.min(appWidth, appHeight);
            if (aspectRatio >= info.getMaxAspectRatio()) {
            if (aspectRatio >= maxAspectRatio) {
                // The current size has reached the max aspect ratio.
                return false;
            }
@@ -8809,7 +8849,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
    // TODO(b/36505427): Consider moving this method and similar ones to ConfigurationContainer.
    private boolean applyAspectRatio(Rect outBounds, Rect containingAppBounds,
            Rect containingBounds, float desiredAspectRatio) {
        final float maxAspectRatio = info.getMaxAspectRatio();
        final float maxAspectRatio = getMaxAspectRatio();
        final Task rootTask = getRootTask();
        final float minAspectRatio = getMinAspectRatio();
        final TaskFragment organizedTf = getOrganizedTaskFragment();
@@ -8916,6 +8956,9 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
     * Returns the min aspect ratio of this activity.
     */
    float getMinAspectRatio() {
        if (mLetterboxUiController.hasInheritedLetterboxBehavior()) {
            return mLetterboxUiController.getInheritedMinAspectRatio();
        }
        if (info.applicationInfo == null) {
            return info.getMinAspectRatio();
        }
@@ -8960,11 +9003,18 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
                && parent.getWindowConfiguration().getWindowingMode() == WINDOWING_MODE_FULLSCREEN;
    }

    float getMaxAspectRatio() {
        if (mLetterboxUiController.hasInheritedLetterboxBehavior()) {
            return mLetterboxUiController.getInheritedMaxAspectRatio();
        }
        return info.getMaxAspectRatio();
    }

    /**
     * Returns true if the activity has maximum or minimum aspect ratio.
     */
    private boolean hasFixedAspectRatio() {
        return info.getMaxAspectRatio() != 0 || getMinAspectRatio() != 0;
        return getMaxAspectRatio() != 0 || getMinAspectRatio() != 0;
    }

    /**
+44 −3
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
import android.graphics.Color;
import android.provider.DeviceConfig;

import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
@@ -103,6 +104,10 @@ final class LetterboxConfiguration {

    final Context mContext;

    // Responsible for the persistence of letterbox[Horizontal|Vertical]PositionMultiplier
    @NonNull
    private final LetterboxConfigurationPersister mLetterboxConfigurationPersister;

    // Aspect ratio of letterbox for fixed orientation, values <=
    // MIN_FIXED_ORIENTATION_LETTERBOX_ASPECT_RATIO will be ignored.
    private float mFixedOrientationLetterboxAspectRatio;
@@ -165,9 +170,12 @@ final class LetterboxConfiguration {
    // Whether using split screen aspect ratio as a default aspect ratio for unresizable apps.
    private boolean mIsSplitScreenAspectRatioForUnresizableAppsEnabled;

    // Responsible for the persistence of letterbox[Horizontal|Vertical]PositionMultiplier
    @NonNull
    private final LetterboxConfigurationPersister mLetterboxConfigurationPersister;
    // Whether letterboxing strategy is enabled for translucent activities. If {@value false}
    // all the feature is disabled
    private boolean mTranslucentLetterboxingEnabled;

    // Allows to enable letterboxing strategy for translucent activities ignoring flags.
    private boolean mTranslucentLetterboxingOverrideEnabled;

    LetterboxConfiguration(Context systemUiContext) {
        this(systemUiContext, new LetterboxConfigurationPersister(systemUiContext,
@@ -206,6 +214,8 @@ final class LetterboxConfiguration {
                R.dimen.config_letterboxDefaultMinAspectRatioForUnresizableApps));
        mIsSplitScreenAspectRatioForUnresizableAppsEnabled = mContext.getResources().getBoolean(
                R.bool.config_letterboxIsSplitScreenAspectRatioForUnresizableAppsEnabled);
        mTranslucentLetterboxingEnabled = mContext.getResources().getBoolean(
                R.bool.config_letterboxIsEnabledForTranslucentActivities);
        mLetterboxConfigurationPersister = letterboxConfigurationPersister;
        mLetterboxConfigurationPersister.start();
    }
@@ -817,6 +827,32 @@ final class LetterboxConfiguration {
                R.bool.config_letterboxIsSplitScreenAspectRatioForUnresizableAppsEnabled);
    }

    boolean isTranslucentLetterboxingEnabled() {
        return mTranslucentLetterboxingOverrideEnabled || (mTranslucentLetterboxingEnabled
                && isTranslucentLetterboxingAllowed());
    }

    void setTranslucentLetterboxingEnabled(boolean translucentLetterboxingEnabled) {
        mTranslucentLetterboxingEnabled = translucentLetterboxingEnabled;
    }

    void setTranslucentLetterboxingOverrideEnabled(
            boolean translucentLetterboxingOverrideEnabled) {
        mTranslucentLetterboxingOverrideEnabled = translucentLetterboxingOverrideEnabled;
        setTranslucentLetterboxingEnabled(translucentLetterboxingOverrideEnabled);
    }

    /**
     * Resets whether we use the constraints override strategy for letterboxing when dealing
     * with translucent activities {@link R.bool.config_letterboxIsEnabledForTranslucentActivities}.
     */
    void resetTranslucentLetterboxingEnabled() {
        final boolean newValue = mContext.getResources().getBoolean(
                R.bool.config_letterboxIsEnabledForTranslucentActivities);
        setTranslucentLetterboxingEnabled(newValue);
        setTranslucentLetterboxingOverrideEnabled(false);
    }

    /** Calculates a new letterboxPositionForHorizontalReachability value and updates the store */
    private void updatePositionForHorizontalReachability(
            Function<Integer, Integer> newHorizonalPositionFun) {
@@ -839,4 +875,9 @@ final class LetterboxConfiguration {
                nextVerticalPosition);
    }

    // TODO(b/262378106): Cache runtime flag and implement DeviceConfig.OnPropertiesChangedListener
    static boolean isTranslucentLetterboxingAllowed() {
        return DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_WINDOW_MANAGER,
                "enable_translucent_activity_letterbox", false);
    }
}
+185 −8
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package com.android.server.wm;

import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
@@ -27,6 +28,7 @@ import static com.android.internal.util.FrameworkStatsLog.APP_COMPAT_STATE_CHANG
import static com.android.internal.util.FrameworkStatsLog.APP_COMPAT_STATE_CHANGED__LETTERBOX_POSITION__RIGHT;
import static com.android.internal.util.FrameworkStatsLog.APP_COMPAT_STATE_CHANGED__LETTERBOX_POSITION__TOP;
import static com.android.internal.util.FrameworkStatsLog.APP_COMPAT_STATE_CHANGED__LETTERBOX_POSITION__UNKNOWN_POSITION;
import static com.android.internal.util.FrameworkStatsLog.APP_COMPAT_STATE_CHANGED__STATE__UNKNOWN;
import static com.android.internal.util.FrameworkStatsLog.LETTERBOX_POSITION_CHANGED__POSITION_CHANGE__BOTTOM_TO_CENTER;
import static com.android.internal.util.FrameworkStatsLog.LETTERBOX_POSITION_CHANGED__POSITION_CHANGE__CENTER_TO_BOTTOM;
import static com.android.internal.util.FrameworkStatsLog.LETTERBOX_POSITION_CHANGED__POSITION_CHANGE__CENTER_TO_LEFT;
@@ -82,13 +84,44 @@ final class LetterboxUiController {

    private static final String TAG = TAG_WITH_CLASS_NAME ? "LetterboxUiController" : TAG_ATM;

    private static final float UNDEFINED_ASPECT_RATIO = 0f;

    private final Point mTmpPoint = new Point();

    private final LetterboxConfiguration mLetterboxConfiguration;

    private final ActivityRecord mActivityRecord;

    /*
     * WindowContainerListener responsible to make translucent activities inherit
     * constraints from the first opaque activity beneath them. It's null for not
     * translucent activities.
     */
    @Nullable
    private WindowContainerListener mLetterboxConfigListener;

    private boolean mShowWallpaperForLetterboxBackground;

    // In case of transparent activities we might need to access the aspectRatio of the
    // first opaque activity beneath.
    private float mInheritedMinAspectRatio = UNDEFINED_ASPECT_RATIO;
    private float mInheritedMaxAspectRatio = UNDEFINED_ASPECT_RATIO;

    @Configuration.Orientation
    private int mInheritedOrientation = Configuration.ORIENTATION_UNDEFINED;

    // The app compat state for the opaque activity if any
    private int mInheritedAppCompatState = APP_COMPAT_STATE_CHANGED__STATE__UNKNOWN;

    // If true it means that the opaque activity beneath a translucent one is in SizeCompatMode.
    private boolean mIsInheritedInSizeCompatMode;

    // This is the SizeCompatScale of the opaque activity beneath a translucent one
    private float mInheritedSizeCompatScale;

    // The CompatDisplayInsets of the opaque activity beneath the translucent one.
    private ActivityRecord.CompatDisplayInsets mInheritedCompatDisplayInsets;

    @Nullable
    private Letterbox mLetterbox;

@@ -220,7 +253,9 @@ final class LetterboxUiController {
                    : mActivityRecord.inMultiWindowMode()
                            ? mActivityRecord.getTask().getBounds()
                            : mActivityRecord.getRootTask().getParent().getBounds();
            mLetterbox.layout(spaceToFill, w.getFrame(), mTmpPoint);
            final Rect innerFrame = hasInheritedLetterboxBehavior()
                    ? mActivityRecord.getWindowConfiguration().getBounds() : w.getFrame();
            mLetterbox.layout(spaceToFill, innerFrame, mTmpPoint);
        } else if (mLetterbox != null) {
            mLetterbox.hide();
        }
@@ -305,7 +340,9 @@ final class LetterboxUiController {
    }

    private void handleHorizontalDoubleTap(int x) {
        if (!isHorizontalReachabilityEnabled() || mActivityRecord.isInTransition()) {
        // TODO(b/260857308): Investigate if enabling reachability for translucent activity
        if (hasInheritedLetterboxBehavior() || !isHorizontalReachabilityEnabled()
                || mActivityRecord.isInTransition()) {
            return;
        }

@@ -341,7 +378,9 @@ final class LetterboxUiController {
    }

    private void handleVerticalDoubleTap(int y) {
        if (!isVerticalReachabilityEnabled() || mActivityRecord.isInTransition()) {
        // TODO(b/260857308): Investigate if enabling reachability for translucent activity
        if (hasInheritedLetterboxBehavior() || !isVerticalReachabilityEnabled()
                || mActivityRecord.isInTransition()) {
            return;
        }

@@ -390,7 +429,7 @@ final class LetterboxUiController {
                && parentConfiguration.windowConfiguration.getWindowingMode()
                        == WINDOWING_MODE_FULLSCREEN
                && (parentConfiguration.orientation == ORIENTATION_LANDSCAPE
                && mActivityRecord.getRequestedConfigurationOrientation() == ORIENTATION_PORTRAIT);
                && mActivityRecord.getOrientationForReachability() == ORIENTATION_PORTRAIT);
    }

    private boolean isHorizontalReachabilityEnabled() {
@@ -412,7 +451,7 @@ final class LetterboxUiController {
                && parentConfiguration.windowConfiguration.getWindowingMode()
                        == WINDOWING_MODE_FULLSCREEN
                && (parentConfiguration.orientation == ORIENTATION_PORTRAIT
                && mActivityRecord.getRequestedConfigurationOrientation() == ORIENTATION_LANDSCAPE);
                && mActivityRecord.getOrientationForReachability() == ORIENTATION_LANDSCAPE);
    }

    private boolean isVerticalReachabilityEnabled() {
@@ -576,9 +615,7 @@ final class LetterboxUiController {
        // Rounded corners should be displayed above the taskbar.
        bounds.bottom =
                Math.min(bounds.bottom, getTaskbarInsetsSource(mainWindow).getFrame().top);
        if (mActivityRecord.inSizeCompatMode() && mActivityRecord.getCompatScale() < 1.0f) {
            bounds.scale(1.0f / mActivityRecord.getCompatScale());
        }
        scaleIfNeeded(bounds);
    }

    private int getInsetsStateCornerRadius(
@@ -788,4 +825,144 @@ final class LetterboxUiController {
                w.mAttrs.insetsFlags.appearance
        );
    }

    /**
     * Handles translucent activities letterboxing inheriting constraints from the
     * first opaque activity beneath.
     * @param parent The parent container.
     */
    void onActivityParentChanged(WindowContainer<?> parent) {
        if (!mLetterboxConfiguration.isTranslucentLetterboxingEnabled()) {
            return;
        }
        if (mLetterboxConfigListener != null) {
            mLetterboxConfigListener.onRemoved();
            clearInheritedConfig();
        }
        // In case mActivityRecord.getCompatDisplayInsets() is not null we don't apply the
        // opaque activity constraints because we're expecting the activity is already letterboxed.
        if (mActivityRecord.getTask() == null || mActivityRecord.getCompatDisplayInsets() != null
                || mActivityRecord.fillsParent()) {
            return;
        }
        final ActivityRecord firstOpaqueActivityBeneath = mActivityRecord.getTask().getActivity(
                ActivityRecord::fillsParent, mActivityRecord, false /* includeBoundary */,
                true /* traverseTopToBottom */);
        if (firstOpaqueActivityBeneath == null
                || mActivityRecord.launchedFromUid != firstOpaqueActivityBeneath.getUid()) {
            // We skip letterboxing if the translucent activity doesn't have any opaque
            // activities beneath of if it's launched from a different user (e.g. notification)
            return;
        }
        inheritConfiguration(firstOpaqueActivityBeneath);
        mLetterboxConfigListener = WindowContainer.overrideConfigurationPropagation(
                mActivityRecord, firstOpaqueActivityBeneath,
                (opaqueConfig, transparentConfig) -> {
                    final Configuration mutatedConfiguration = new Configuration();
                    final Rect parentBounds = parent.getWindowConfiguration().getBounds();
                    final Rect bounds = mutatedConfiguration.windowConfiguration.getBounds();
                    final Rect letterboxBounds = opaqueConfig.windowConfiguration.getBounds();
                    // We cannot use letterboxBounds directly here because the position relies on
                    // letterboxing. Using letterboxBounds directly, would produce a double offset.
                    bounds.set(parentBounds.left, parentBounds.top,
                            parentBounds.left + letterboxBounds.width(),
                            parentBounds.top + letterboxBounds.height());
                    // We need to initialize appBounds to avoid NPE. The actual value will
                    // be set ahead when resolving the Configuration for the activity.
                    mutatedConfiguration.windowConfiguration.setAppBounds(new Rect());
                    return mutatedConfiguration;
                });
    }

    /**
     * @return {@code true} if the current activity is translucent with an opaque activity
     * beneath. In this case it will inherit bounds, orientation and aspect ratios from
     * the first opaque activity beneath.
     */
    boolean hasInheritedLetterboxBehavior() {
        return mLetterboxConfigListener != null && !mActivityRecord.matchParentBounds();
    }

    /**
     * @return {@code true} if the current activity is translucent with an opaque activity
     * beneath and needs to inherit its orientation.
     */
    boolean hasInheritedOrientation() {
        // To force a different orientation, the transparent one needs to have an explicit one
        // otherwise the existing one is fine and the actual orientation will depend on the
        // bounds.
        // To avoid wrong behaviour, we're not forcing orientation for activities with not
        // fixed orientation (e.g. permission dialogs).
        return hasInheritedLetterboxBehavior()
                && mActivityRecord.mOrientation != SCREEN_ORIENTATION_UNSPECIFIED;
    }

    float getInheritedMinAspectRatio() {
        return mInheritedMinAspectRatio;
    }

    float getInheritedMaxAspectRatio() {
        return mInheritedMaxAspectRatio;
    }

    int getInheritedAppCompatState() {
        return mInheritedAppCompatState;
    }

    float getInheritedSizeCompatScale() {
        return mInheritedSizeCompatScale;
    }

    @Configuration.Orientation
    int getInheritedOrientation() {
        return mInheritedOrientation;
    }

    public ActivityRecord.CompatDisplayInsets getInheritedCompatDisplayInsets() {
        return mInheritedCompatDisplayInsets;
    }

    private void inheritConfiguration(ActivityRecord firstOpaque) {
        // To avoid wrong behaviour, we're not forcing a specific aspet ratio to activities
        // which are not already providing one (e.g. permission dialogs) and presumably also
        // not resizable.
        if (mActivityRecord.getMinAspectRatio() != UNDEFINED_ASPECT_RATIO) {
            mInheritedMinAspectRatio = firstOpaque.getMinAspectRatio();
        }
        if (mActivityRecord.getMaxAspectRatio() != UNDEFINED_ASPECT_RATIO) {
            mInheritedMaxAspectRatio = firstOpaque.getMaxAspectRatio();
        }
        mInheritedOrientation = firstOpaque.getRequestedConfigurationOrientation();
        mInheritedAppCompatState = firstOpaque.getAppCompatState();
        mIsInheritedInSizeCompatMode = firstOpaque.inSizeCompatMode();
        mInheritedSizeCompatScale = firstOpaque.getCompatScale();
        mInheritedCompatDisplayInsets = firstOpaque.getCompatDisplayInsets();
    }

    private void clearInheritedConfig() {
        mLetterboxConfigListener = null;
        mInheritedMinAspectRatio = UNDEFINED_ASPECT_RATIO;
        mInheritedMaxAspectRatio = UNDEFINED_ASPECT_RATIO;
        mInheritedOrientation = Configuration.ORIENTATION_UNDEFINED;
        mInheritedAppCompatState = APP_COMPAT_STATE_CHANGED__STATE__UNKNOWN;
        mIsInheritedInSizeCompatMode = false;
        mInheritedSizeCompatScale = 1f;
        mInheritedCompatDisplayInsets = null;
    }

    private void scaleIfNeeded(Rect bounds) {
        if (boundsNeedToScale()) {
            bounds.scale(1.0f / mActivityRecord.getCompatScale());
        }
    }

    private boolean boundsNeedToScale() {
        if (hasInheritedLetterboxBehavior()) {
            return mIsInheritedInSizeCompatMode
                    && mInheritedSizeCompatScale < 1.0f;
        } else {
            return mActivityRecord.inSizeCompatMode()
                    && mActivityRecord.getCompatScale() < 1.0f;
        }
    }
}
Loading