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

Commit 5752b267 authored by Rachit Jain's avatar Rachit Jain Committed by Android (Google) Code Review
Browse files

Merge changes from topic "safe-region-letterboxing" into main

* changes:
  [7/n] Add application and activity property to allow safe region letterboxing
  [6/n] Apply the safe region bounds WCT
  [5/n] Integrate AppCompatSafeRegionPolicy in LaunchParams
  [4/n] Apply AppCompatSafeRegionPolicy during activity launch
  [3/n] Add safe region bounds in WindowContainer
  [2/n] Create AppCompatSafeRegionPolicy for letterboxing
  [1/n] Add WCT for setting safe region bounds for letterboxing
parents 280cfec4 4a11fde2
Loading
Loading
Loading
Loading
+38 −0
Original line number Diff line number Diff line
@@ -1513,6 +1513,44 @@ public interface WindowManager extends ViewManager {
    String PROPERTY_COMPAT_ALLOW_RESTRICTED_RESIZABILITY =
            "android.window.PROPERTY_COMPAT_ALLOW_RESTRICTED_RESIZABILITY";

    /**
     * Application or Activity level
     * {@link android.content.pm.PackageManager.Property PackageManager.Property} that specifies
     * whether this package or activity wants to allow safe region letterboxing. A safe
     * region policy may be applied by the system to improve the user experience by ensuring that
     * the activity does not have any content that is occluded and has the correct current
     * window metrics.
     *
     * <p>Not setting the property at all defaults it to {@code true}. In such a case, the activity
     * will be letterboxed in the safe region.
     *
     * <p>To not allow the safe region letterboxing, add this property to your app
     * manifest and set the value to {@code false}. An app should ignore safe region
     * letterboxing if it can handle bounds and insets from all four directions correctly when a
     * request to go immersive is denied by the system. If the application does not allow safe
     * region letterboxing, the system will not override this behavior.
     *
     * <p><b>Syntax:</b>
     * <pre>
     * &lt;application&gt;
     *   &lt;property
     *     android:name="android.window.PROPERTY_COMPAT_ALLOW_SAFE_REGION_LETTERBOXING"
     *     android:value="false"/&gt;
     * &lt;/application&gt;
     * </pre>or
     * <pre>
     * &lt;activity&gt;
     *   &lt;property
     *     android:name="android.window.PROPERTY_COMPAT_ALLOW_SAFE_REGION_LETTERBOXING"
     *     android:value="false"/&gt;
     * &lt;/activity&gt;
     * </pre>
     * @hide
     */
    @FlaggedApi(Flags.FLAG_SAFE_REGION_LETTERBOXING)
    String PROPERTY_COMPAT_ALLOW_SAFE_REGION_LETTERBOXING =
            "android.window.PROPERTY_COMPAT_ALLOW_SAFE_REGION_LETTERBOXING";

    /**
     * @hide
     */
+61 −1
Original line number Diff line number Diff line
@@ -445,6 +445,27 @@ public final class WindowContainerTransaction implements Parcelable {
        return this;
    }

    /**
     * Sets a given safe region {@code Rect} on the {@code container}. Set {@code null} to reset
     * safe region bounds. When a safe region is set on a WindowContainer, the activities which
     * need to be within a safe region will be letterboxed within the set safe region bounds.
     * <p>Note that if the position of the WindowContainer changes, the caller needs to update the
     * safe region bounds.
     *
     * @param container        The window container that the safe region bounds are set on
     * @param safeRegionBounds The rect for the safe region bounds which are absolute in nature.
     * @hide
     */
    @NonNull
    @FlaggedApi(Flags.FLAG_SAFE_REGION_LETTERBOXING)
    public WindowContainerTransaction setSafeRegionBounds(
            @NonNull WindowContainerToken container,
            @Nullable Rect safeRegionBounds) {
        mHierarchyOps.add(
                HierarchyOp.createForSetSafeRegionBounds(container.asBinder(), safeRegionBounds));
        return this;
    }

    /*
     * ===========================================================================================
     * Hierarchy updates (create/destroy/reorder/reparent containers)
@@ -1597,6 +1618,7 @@ public final class WindowContainerTransaction implements Parcelable {
        public static final int HIERARCHY_OP_TYPE_SET_DISABLE_LAUNCH_ADJACENT = 23;
        public static final int HIERARCHY_OP_TYPE_REMOVE_ROOT_TASK = 24;
        public static final int HIERARCHY_OP_TYPE_APP_COMPAT_REACHABILITY = 25;
        public static final int HIERARCHY_OP_TYPE_SET_SAFE_REGION_BOUNDS = 26;

        @IntDef(prefix = {"HIERARCHY_OP_TYPE_"}, value = {
                HIERARCHY_OP_TYPE_REPARENT,
@@ -1625,6 +1647,7 @@ public final class WindowContainerTransaction implements Parcelable {
                HIERARCHY_OP_TYPE_SET_DISABLE_LAUNCH_ADJACENT,
                HIERARCHY_OP_TYPE_REMOVE_ROOT_TASK,
                HIERARCHY_OP_TYPE_APP_COMPAT_REACHABILITY,
                HIERARCHY_OP_TYPE_SET_SAFE_REGION_BOUNDS,
        })
        @Retention(RetentionPolicy.SOURCE)
        public @interface HierarchyOpType {
@@ -1710,6 +1733,9 @@ public final class WindowContainerTransaction implements Parcelable {

        private boolean mLaunchAdjacentDisabled;

        @Nullable
        private Rect mSafeRegionBounds;

        /** Creates a hierarchy operation for reparenting a container within the hierarchy. */
        @NonNull
        public static HierarchyOp createForReparent(
@@ -1873,6 +1899,17 @@ public final class WindowContainerTransaction implements Parcelable {
                    .build();
        }

        /** Creates a hierarchy op for setting the safe region bounds. */
        @NonNull
        @FlaggedApi(Flags.FLAG_SAFE_REGION_LETTERBOXING)
        public static HierarchyOp createForSetSafeRegionBounds(@NonNull IBinder container,
                @Nullable Rect safeRegionBounds) {
            return new Builder(HIERARCHY_OP_TYPE_SET_SAFE_REGION_BOUNDS)
                    .setContainer(container)
                    .setSafeRegionBounds(safeRegionBounds)
                    .build();
        }

        /** Only creates through {@link Builder}. */
        private HierarchyOp(@HierarchyOpType int type) {
            mType = type;
@@ -1903,6 +1940,7 @@ public final class WindowContainerTransaction implements Parcelable {
            mIsTrimmableFromRecents = copy.mIsTrimmableFromRecents;
            mExcludeInsetsTypes = copy.mExcludeInsetsTypes;
            mLaunchAdjacentDisabled = copy.mLaunchAdjacentDisabled;
            mSafeRegionBounds = copy.mSafeRegionBounds;
        }

        private HierarchyOp(@NonNull Parcel in) {
@@ -1930,6 +1968,7 @@ public final class WindowContainerTransaction implements Parcelable {
            mIsTrimmableFromRecents = in.readBoolean();
            mExcludeInsetsTypes = in.readInt();
            mLaunchAdjacentDisabled = in.readBoolean();
            mSafeRegionBounds = in.readTypedObject(Rect.CREATOR);
        }

        @HierarchyOpType
@@ -2051,6 +2090,12 @@ public final class WindowContainerTransaction implements Parcelable {
            return mLaunchAdjacentDisabled;
        }

        /** Denotes the safe region bounds */
        @Nullable
        public Rect getSafeRegionBounds() {
            return mSafeRegionBounds;
        }

        /** Gets a string representation of a hierarchy-op type. */
        public static String hopToString(@HierarchyOpType int type) {
            switch (type) {
@@ -2084,6 +2129,7 @@ public final class WindowContainerTransaction implements Parcelable {
                case HIERARCHY_OP_TYPE_RESTORE_BACK_NAVIGATION: return "restoreBackNav";
                case HIERARCHY_OP_TYPE_SET_EXCLUDE_INSETS_TYPES: return "setExcludeInsetsTypes";
                case HIERARCHY_OP_TYPE_SET_KEYGUARD_STATE: return "setKeyguardState";
                case HIERARCHY_OP_TYPE_SET_SAFE_REGION_BOUNDS: return "setSafeRegionBounds";
                default: return "HOP(" + type + ")";
            }
        }
@@ -2184,6 +2230,11 @@ public final class WindowContainerTransaction implements Parcelable {
                    sb.append("container= ").append(mContainer)
                            .append(" isTrimmable= ")
                            .append(mIsTrimmableFromRecents);
                    break;
                case HIERARCHY_OP_TYPE_SET_SAFE_REGION_BOUNDS:
                    sb.append("container= ").append(mContainer)
                            .append(" safeRegionBounds= ")
                            .append(mSafeRegionBounds);
                default:
                    sb.append("container=").append(mContainer)
                            .append(" reparent=").append(mReparent)
@@ -2220,6 +2271,7 @@ public final class WindowContainerTransaction implements Parcelable {
            dest.writeBoolean(mIsTrimmableFromRecents);
            dest.writeInt(mExcludeInsetsTypes);
            dest.writeBoolean(mLaunchAdjacentDisabled);
            dest.writeTypedObject(mSafeRegionBounds, flags);
        }

        @Override
@@ -2305,6 +2357,9 @@ public final class WindowContainerTransaction implements Parcelable {

            private boolean mLaunchAdjacentDisabled;

            @Nullable
            private Rect mSafeRegionBounds;

            Builder(@HierarchyOpType int type) {
                mType = type;
            }
@@ -2426,6 +2481,11 @@ public final class WindowContainerTransaction implements Parcelable {
                return this;
            }

            Builder setSafeRegionBounds(Rect safeRegionBounds) {
                mSafeRegionBounds = safeRegionBounds;
                return this;
            }

            @NonNull
            HierarchyOp build() {
                final HierarchyOp hierarchyOp = new HierarchyOp(mType);
@@ -2456,7 +2516,7 @@ public final class WindowContainerTransaction implements Parcelable {
                hierarchyOp.mIsTrimmableFromRecents = mIsTrimmableFromRecents;
                hierarchyOp.mExcludeInsetsTypes = mExcludeInsetsTypes;
                hierarchyOp.mLaunchAdjacentDisabled = mLaunchAdjacentDisabled;

                hierarchyOp.mSafeRegionBounds = mSafeRegionBounds;
                return hierarchyOp;
            }
        }
+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.
+3 −0
Original line number Diff line number Diff line
@@ -2203,6 +2203,9 @@ class ActivityStarter {
                ? mLaunchParams.mPreferredTaskDisplayArea
                : mRootWindowContainer.getDefaultTaskDisplayArea();
        mPreferredWindowingMode = mLaunchParams.mWindowingMode;
        if (mLaunchParams.mNeedsSafeRegionBounds != null) {
            r.setNeedsSafeRegionBounds(mLaunchParams.mNeedsSafeRegionBounds);
        }
    }

    private TaskDisplayArea computeSuggestedLaunchDisplayArea(
+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).
Loading