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

Commit a9adefbb authored by jainrachit's avatar jainrachit
Browse files

[4/n] Apply AppCompatSafeRegionPolicy during activity launch

- Apply the safe region policy when an activity needs to be within the
  safe region and a safe region is set on the closest ancestor window.
- If the letterboxing logic is applied due to existing conditions and if
  a safe region is needed and exists, the activity will be sandboxed
within the safe region bounds.
-  If the letterboxing logic is applied due to a safe region only which is needed and exists, the safe region bounds will be used as the resolved bounds.

Bug: 380132497
Flag: com.android.window.flags.safe_region_letterboxing
Test: atest SizeCompatTests AppCompatUtilsTest AppCompatLetterboxPolicyTest
Change-Id: Ic2ee32e521b30fc4f1b07f972b172b284c01e8fa
parent 46c60177
Loading
Loading
Loading
Loading
+20 −3
Original line number Diff line number Diff line
@@ -5590,6 +5590,14 @@ final class ActivityRecord extends WindowToken {
        commitVisibility(visible, performLayout, false /* fromTransition */);
    }

    /**
     * Sets whether safe region bounds are needed for the Activity. This is called from
     * {@link ActivityStarter} after the source record is created.
     */
    void setNeedsSafeRegionBounds(boolean needsSafeRegionBounds) {
        mAppCompatController.getSafeRegionPolicy().setNeedsSafeRegionBounds(needsSafeRegionBounds);
    }

    /** Updates draw state and shows drawn windows. */
    void commitFinishDrawing(SurfaceControl.Transaction t) {
        boolean committed = false;
@@ -7753,9 +7761,11 @@ final class ActivityRecord extends WindowToken {
        final AppCompatAspectRatioPolicy aspectRatioPolicy =
                mAppCompatController.getAspectRatioPolicy();
        aspectRatioPolicy.reset();
        final AppCompatSafeRegionPolicy safeRegionPolicy =
                mAppCompatController.getSafeRegionPolicy();
        mAppCompatController.getLetterboxPolicy().resetFixedOrientationLetterboxEligibility();
        mResolveConfigHint.resolveTmpOverrides(mDisplayContent, newParentConfiguration,
                isFixedRotationTransforming());
                isFixedRotationTransforming(), safeRegionPolicy.getLatestSafeRegionBounds());

        // Can't use resolvedConfig.windowConfiguration.getWindowingMode() because it can be
        // different from windowing mode of the task (PiP) during transition from fullscreen to PiP
@@ -7801,6 +7811,13 @@ final class ActivityRecord extends WindowToken {
            }
        }

        // If activity can be letterboxed due to a safe region only, use the safe region bounds
        // as the resolved bounds. We ignore cases where the letterboxing can happen due to other
        // app compat conditions and a safe region since the safe region app compat is sandboxed
        // earlier in TaskFragment.ConfigOverrideHint.resolveTmpOverrides.
        mAppCompatController.getSafeRegionPolicy().resolveSafeRegionBoundsConfigurationIfNeeded(
                resolvedConfig, newParentConfiguration);

        if (isFixedOrientationLetterboxAllowed
                || scmPolicy.hasAppCompatDisplayInsetsWithoutInheritance()
                // In fullscreen, can be letterboxed for aspect ratio.
@@ -7980,7 +7997,7 @@ final class ActivityRecord extends WindowToken {
                mAppCompatController.getSizeCompatModePolicy();
        final Rect screenResolvedBounds = scmPolicy.replaceResolvedBoundsIfNeeded(resolvedBounds);
        final Rect parentAppBounds = mResolveConfigHint.mParentAppBoundsOverride;
        final Rect parentBounds = newParentConfiguration.windowConfiguration.getBounds();
        final Rect parentBounds = mResolveConfigHint.mParentBoundsOverride;
        final float screenResolvedBoundsWidth = screenResolvedBounds.width();
        final float parentAppBoundsWidth = parentAppBounds.width();
        final boolean isImmersiveMode = isImmersiveMode(parentBounds);
@@ -8167,7 +8184,7 @@ final class ActivityRecord extends WindowToken {
     * in this method.
     */
    private void resolveFixedOrientationConfiguration(@NonNull Configuration newParentConfig) {
        final Rect parentBounds = newParentConfig.windowConfiguration.getBounds();
        final Rect parentBounds = mResolveConfigHint.mParentBoundsOverride;
        final Rect stableBounds = new Rect();
        final Rect outNonDecorBounds = mTmpBounds;
        // If orientation is respected when insets are applied, then stableBounds will be empty.
+1 −1
Original line number Diff line number Diff line
@@ -240,7 +240,7 @@ class AppCompatAspectRatioPolicy {
        final Configuration resolvedConfig = mActivityRecord.getResolvedOverrideConfiguration();
        final Rect parentAppBounds =
                mActivityRecord.mResolveConfigHint.mParentAppBoundsOverride;
        final Rect parentBounds = newParentConfiguration.windowConfiguration.getBounds();
        final Rect parentBounds = mActivityRecord.mResolveConfigHint.mParentBoundsOverride;
        final Rect resolvedBounds = resolvedConfig.windowConfiguration.getBounds();
        // 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).
+12 −2
Original line number Diff line number Diff line
@@ -58,18 +58,28 @@ class AppCompatSafeRegionPolicy {
    }

    /**
     * Computes bounds when letterboxing is required only for the safe region bounds.
     * Computes bounds when letterboxing is required only for the safe region bounds if needed.
     */
    public void resolveSafeRegionBoundsConfiguration(@NonNull Configuration resolvedConfig,
    public void resolveSafeRegionBoundsConfigurationIfNeeded(@NonNull Configuration resolvedConfig,
            @NonNull Configuration newParentConfig) {
        if (mLatestSafeRegionBounds.isEmpty()) {
            return;
        }
        // If activity can not be letterboxed for a safe region only or it has not been attached
        // to a WindowContainer yet.
        if (!isLetterboxedForSafeRegionOnly() || mActivityRecord.getParent() == null) {
            return;
        }
        resolvedConfig.windowConfiguration.setBounds(mLatestSafeRegionBounds);
        mActivityRecord.computeConfigByResolveHint(resolvedConfig, newParentConfig);
    }

    /**
     * Safe region bounds can either be applied along with size compat, fixed orientation or
     * aspect ratio conditions by sandboxing them to the safe region bounds. Or it can be applied
     * independently when no other letterboxing condition is triggered. This method helps detecting
     * the latter case.
     *
     * @return {@code true} if the activity is letterboxed only due to the safe region being set on
     * the current or ancestor window container.
     */
+4 −0
Original line number Diff line number Diff line
@@ -242,6 +242,10 @@ final class AppCompatUtils {
        if (aspectRatioPolicy.isLetterboxedForAspectRatioOnly()) {
            return "ASPECT_RATIO";
        }
        if (activityRecord.mAppCompatController.getSafeRegionPolicy()
                .isLetterboxedForSafeRegionOnly()) {
            return "SAFE_REGION";
        }
        return "UNKNOWN_REASON";
    }

+14 −7
Original line number Diff line number Diff line
@@ -2333,15 +2333,24 @@ class TaskFragment extends WindowContainer<WindowContainer> {
        @Nullable DisplayInfo mTmpOverrideDisplayInfo;
        @Nullable AppCompatDisplayInsets mTmpCompatInsets;
        @Nullable Rect mParentAppBoundsOverride;
        @Nullable Rect mParentBoundsOverride;
        int mTmpOverrideConfigOrientation;
        boolean mUseOverrideInsetsForConfig;

        void resolveTmpOverrides(DisplayContent dc, Configuration parentConfig,
                boolean isFixedRotationTransforming) {
            mParentAppBoundsOverride = new Rect(parentConfig.windowConfiguration.getAppBounds());
                boolean isFixedRotationTransforming, @Nullable Rect safeRegionBounds) {
            mParentAppBoundsOverride = safeRegionBounds != null ? safeRegionBounds : new Rect(
                    parentConfig.windowConfiguration.getAppBounds());
            mParentBoundsOverride = safeRegionBounds != null ? safeRegionBounds : new Rect(
                    parentConfig.windowConfiguration.getBounds());
            mTmpOverrideConfigOrientation = parentConfig.orientation;
            final Insets insets;
            if (mUseOverrideInsetsForConfig && dc != null
            Insets insets = Insets.NONE;
            if (safeRegionBounds != null) {
                // Modify orientation based on the parent app bounds if safe region bounds are set.
                mTmpOverrideConfigOrientation =
                        mParentAppBoundsOverride.height() >= mParentAppBoundsOverride.width()
                                ? ORIENTATION_PORTRAIT : ORIENTATION_LANDSCAPE;
            } else if (mUseOverrideInsetsForConfig && dc != null
                    && !isFloating(parentConfig.windowConfiguration.getWindowingMode())) {
                // Insets are decoupled from configuration by default from V+, use legacy
                // compatibility behaviour for apps targeting SDK earlier than 35
@@ -2359,8 +2368,6 @@ class TaskFragment extends WindowContainer<WindowContainer> {
                mTmpOverrideConfigOrientation = stableBounds.width() > stableBounds.height()
                        ? ORIENTATION_LANDSCAPE : ORIENTATION_PORTRAIT;
                insets = Insets.of(decorInsets.mOverrideNonDecorInsets);
            } else {
                insets = Insets.NONE;
            }
            mParentAppBoundsOverride.inset(insets);
        }
Loading