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

Commit 46c60177 authored by jainrachit's avatar jainrachit
Browse files

[3/n] Add safe region bounds in WindowContainer

- Set the safe region bounds on a WindowContainer.
- The safe region bounds can be inherited from the closest ancestor
  WindowContainer.

Bug: 380132497
Flag: com.android.window.flags.safe_region_letterboxing
Test: atest WindowContainerTests
Change-Id: I24b7494d9df8c7d6a6ccfbaae6b9e5f699543c08
parent ea43a07a
Loading
Loading
Loading
Loading
+43 −0
Original line number Diff line number Diff line
@@ -97,6 +97,7 @@ import com.android.server.wm.SurfaceAnimator.Animatable;
import com.android.server.wm.SurfaceAnimator.AnimationType;
import com.android.server.wm.SurfaceAnimator.OnAnimationFinishedCallback;
import com.android.server.wm.utils.AlwaysTruePredicate;
import com.android.window.flags.Flags;

import java.io.PrintWriter;
import java.lang.ref.WeakReference;
@@ -161,6 +162,15 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
    protected @InsetsType int mMergedExcludeInsetsTypes = 0;
    private @InsetsType int mExcludeInsetsTypes = 0;

    /**
     * Bounds for the safe region for this window container which control the
     * {@link AppCompatSafeRegionPolicy}. These bounds can be passed on to the subtree if the
     * subtree has no other bounds for the safe region. The value will be null if there are no safe
     * region bounds for the window container.
     */
    @Nullable
    private Rect mSafeRegionBounds;

    @Nullable
    private ArrayMap<IBinder, DeathRecipient> mInsetsOwnerDeathRecipientMap;

@@ -556,6 +566,38 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
                mParent != null ? mParent.mMergedExcludeInsetsTypes : 0);
    }

    /**
     * Returns the safe region bounds on the window container. If the window container has no safe
     * region bounds set, the safe region bounds as set on the nearest ancestor is returned.
     */
    @Nullable
    Rect getSafeRegionBounds() {
        if (mSafeRegionBounds != null) {
            return mSafeRegionBounds;
        }
        if (mParent == null) {
            return null;
        }
        return mParent.getSafeRegionBounds();
    }

    /**
     * Sets the safe region bounds on the window container. Set bounds to {@code null} to reset.
     *
     * @param safeRegionBounds the safe region {@link Rect} that should be set on this
     *                         WindowContainer
     */
    void setSafeRegionBounds(@Nullable Rect safeRegionBounds) {
        if (!Flags.safeRegionLetterboxing()) {
            Slog.i(TAG, "Feature safe region letterboxing is not available");
            return;
        }
        mSafeRegionBounds = safeRegionBounds;
        // Trigger a config change whenever this method is called since the safe region bounds
        // can be modified (including a reset).
        onRequestedOverrideConfigurationChanged(getRequestedOverrideConfiguration());
    }

    private void mergeExcludeInsetsTypesAndNotifyInsetsChanged(
            @InsetsType int excludeInsetsTypesFromParent) {
        final ArraySet<WindowState> changedWindows = new ArraySet<>();
@@ -3230,6 +3272,7 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
                mLocalInsetsSources.valueAt(i).dump(childPrefix, pw);
            }
        }
        pw.println(prefix + mSafeRegionBounds + " SafeRegionBounds");
    }

    final void updateSurfacePositionNonOrganized() {
+87 −0
Original line number Diff line number Diff line
@@ -1430,6 +1430,93 @@ public class WindowContainerTests extends WindowTestsBase {
        assertFalse("The source must be removed.", hasLocalSource(task, provider.getId()));
    }

    @Test
    @EnableFlags(Flags.FLAG_SAFE_REGION_LETTERBOXING)
    public void testSetSafeRegionBounds_appliedOnNodeAndChildren() {
        final TestWindowContainerBuilder builder = new TestWindowContainerBuilder(mWm);
        final TestWindowContainer root = builder.setLayer(0).build();

        final TestWindowContainer child1 = root.addChildWindow();
        final TestWindowContainer child2 = root.addChildWindow();
        final TestWindowContainer child11 = child1.addChildWindow();
        final TestWindowContainer child12 = child1.addChildWindow();
        final TestWindowContainer child21 = child2.addChildWindow();

        assertNull(root.getSafeRegionBounds());
        assertNull(child1.getSafeRegionBounds());
        assertNull(child11.getSafeRegionBounds());
        assertNull(child12.getSafeRegionBounds());
        assertNull(child2.getSafeRegionBounds());
        assertNull(child21.getSafeRegionBounds());

        final Rect tempSafeRegionBounds1 = new Rect(50, 50, 200, 300);
        child1.setSafeRegionBounds(tempSafeRegionBounds1);

        assertNull(root.getSafeRegionBounds());
        assertEquals(tempSafeRegionBounds1, child1.getSafeRegionBounds());
        assertEquals(tempSafeRegionBounds1, child11.getSafeRegionBounds());
        assertEquals(tempSafeRegionBounds1, child12.getSafeRegionBounds());
        assertNull(child2.getSafeRegionBounds());
        assertNull(child21.getSafeRegionBounds());

        // Set different safe region bounds on child11
        final Rect tempSafeRegionBounds2 = new Rect(30, 30, 200, 200);
        child11.setSafeRegionBounds(tempSafeRegionBounds2);

        assertNull(root.getSafeRegionBounds());
        assertEquals(tempSafeRegionBounds1, child1.getSafeRegionBounds());
        assertEquals(tempSafeRegionBounds2, child11.getSafeRegionBounds());
        assertEquals(tempSafeRegionBounds1, child12.getSafeRegionBounds());
        assertNull(child2.getSafeRegionBounds());
        assertNull(child21.getSafeRegionBounds());
    }

    @Test
    @EnableFlags(Flags.FLAG_SAFE_REGION_LETTERBOXING)
    public void testSetSafeRegionBounds_resetSafeRegionBounds() {
        final TestWindowContainerBuilder builder = new TestWindowContainerBuilder(mWm);
        final TestWindowContainer root = builder.setLayer(0).build();

        final TestWindowContainer child1 = root.addChildWindow();
        final TestWindowContainer child2 = root.addChildWindow();
        final TestWindowContainer child11 = child1.addChildWindow();
        final TestWindowContainer child12 = child1.addChildWindow();
        final TestWindowContainer child21 = child2.addChildWindow();

        assertNull(root.getSafeRegionBounds());
        assertNull(child1.getSafeRegionBounds());
        assertNull(child11.getSafeRegionBounds());
        assertNull(child12.getSafeRegionBounds());
        assertNull(child2.getSafeRegionBounds());
        assertNull(child21.getSafeRegionBounds());

        final Rect tempSafeRegionBounds1 = new Rect(50, 50, 200, 300);
        child1.setSafeRegionBounds(tempSafeRegionBounds1);

        assertNull(root.getSafeRegionBounds());
        assertEquals(tempSafeRegionBounds1, child1.getSafeRegionBounds());
        assertEquals(tempSafeRegionBounds1, child11.getSafeRegionBounds());
        assertEquals(tempSafeRegionBounds1, child12.getSafeRegionBounds());
        assertNull(child2.getSafeRegionBounds());
        assertNull(child21.getSafeRegionBounds());

        // Set different safe region bounds on child11
        final Rect tempSafeRegionBounds2 = new Rect(30, 30, 200, 200);
        child11.setSafeRegionBounds(tempSafeRegionBounds2);

        assertEquals(tempSafeRegionBounds2, child11.getSafeRegionBounds());

        // Reset safe region bounds on child11. Now child11 will use child1 safe region bounds.
        child11.setSafeRegionBounds(/* safeRegionBounds */null);

        assertNull(root.getSafeRegionBounds());
        assertEquals(tempSafeRegionBounds1, child1.getSafeRegionBounds());
        assertEquals(tempSafeRegionBounds1, child11.getSafeRegionBounds());
        assertEquals(tempSafeRegionBounds1, child12.getSafeRegionBounds());
        assertNull(child2.getSafeRegionBounds());
        assertNull(child21.getSafeRegionBounds());
    }

    @Test
    public void testSetExcludeInsetsTypes_appliedOnNodeAndChildren() {
        final TestWindowContainerBuilder builder = new TestWindowContainerBuilder(mWm);