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

Commit 86c6d900 authored by Massimo Carli's avatar Massimo Carli Committed by Android (Google) Code Review
Browse files

Merge "Fix Letterboxing for Transparent Activities" into tm-qpr-dev

parents bb848b65 de531310
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) {
@@ -7682,6 +7683,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.
@@ -7809,6 +7819,9 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A

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

@@ -7891,6 +7904,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;
@@ -7952,6 +7969,9 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A

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

@@ -8060,6 +8080,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.
     *
@@ -8100,6 +8130,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;
        }
@@ -8570,6 +8604,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();
@@ -8590,10 +8629,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;
            }
@@ -8815,7 +8855,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();
@@ -8922,6 +8962,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();
        }
@@ -8966,11 +9009,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