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

Commit 3b93fd58 authored by Vali Calinescu's avatar Vali Calinescu Committed by Automerger Merge Worker
Browse files

Merge "Pass LetterboxDetails to SysUI" into tm-qpr-dev am: 95a0aa96

parents 3459f452 95a0aa96
Loading
Loading
Loading
Loading
+30 −2
Original line number Diff line number Diff line
@@ -318,12 +318,19 @@ public class DisplayPolicy {
     */
    private final ArrayList<WindowState> mStatusBarBackgroundWindows = new ArrayList<>();

    /**
     * A collection of {@link LetterboxDetails} of all visible activities to be sent to SysUI in
     * order to determine status bar appearance
     */
    private final ArrayList<LetterboxDetails> mLetterboxDetails = new ArrayList<>();

    private String mFocusedApp;
    private int mLastDisableFlags;
    private int mLastAppearance;
    private int mLastBehavior;
    private InsetsVisibilities mRequestedVisibilities = new InsetsVisibilities();
    private AppearanceRegion[] mLastStatusBarAppearanceRegions;
    private LetterboxDetails[] mLastLetterboxDetails;

    /** The union of checked bounds while building {@link #mStatusBarAppearanceRegionList}. */
    private final Rect mStatusBarColorCheckedBounds = new Rect();
@@ -1638,6 +1645,7 @@ public class DisplayPolicy {
        mNavBarColorWindowCandidate = null;
        mNavBarBackgroundWindow = null;
        mStatusBarAppearanceRegionList.clear();
        mLetterboxDetails.clear();
        mStatusBarBackgroundWindows.clear();
        mStatusBarColorCheckedBounds.setEmpty();
        mStatusBarBackgroundCheckedBounds.setEmpty();
@@ -1717,6 +1725,16 @@ public class DisplayPolicy {
                            win.mAttrs.insetsFlags.appearance & APPEARANCE_LIGHT_STATUS_BARS,
                            new Rect(win.getFrame())));
                    mStatusBarColorCheckedBounds.union(sTmpRect);
                    // Check if current activity is letterboxed in order create a LetterboxDetails
                    // component to be passed to SysUI for status bar treatment
                    final ActivityRecord currentActivity = win.getActivityRecord();
                    if (currentActivity != null) {
                        final LetterboxDetails currentLetterboxDetails = currentActivity
                                .mLetterboxUiController.getLetterboxDetails();
                        if (currentLetterboxDetails != null) {
                            mLetterboxDetails.add(currentLetterboxDetails);
                        }
                    }
                }
            }

@@ -2404,12 +2422,15 @@ public class DisplayPolicy {
            callStatusBarSafely(statusBar -> statusBar.setDisableFlags(displayId, disableFlags,
                    cause));
        }
        final LetterboxDetails[] letterboxDetails = new LetterboxDetails[mLetterboxDetails.size()];
        mLetterboxDetails.toArray(letterboxDetails);
        if (mLastAppearance == appearance
                && mLastBehavior == behavior
                && mRequestedVisibilities.equals(win.getRequestedVisibilities())
                && Objects.equals(mFocusedApp, focusedApp)
                && mLastFocusIsFullscreen == isFullscreen
                && Arrays.equals(mLastStatusBarAppearanceRegions, statusBarAppearanceRegions)) {
                && Arrays.equals(mLastStatusBarAppearanceRegions, statusBarAppearanceRegions)
                && Arrays.equals(mLastLetterboxDetails, letterboxDetails)) {
            return;
        }
        if (mDisplayContent.isDefaultDisplay && mLastFocusIsFullscreen != isFullscreen
@@ -2425,9 +2446,10 @@ public class DisplayPolicy {
        mFocusedApp = focusedApp;
        mLastFocusIsFullscreen = isFullscreen;
        mLastStatusBarAppearanceRegions = statusBarAppearanceRegions;
        mLastLetterboxDetails = letterboxDetails;
        callStatusBarSafely(statusBar -> statusBar.onSystemBarAttributesChanged(displayId,
                appearance, statusBarAppearanceRegions, isNavbarColorManagedByIme, behavior,
                requestedVisibilities, focusedApp, new LetterboxDetails[]{}));
                requestedVisibilities, focusedApp, letterboxDetails));
    }

    private void callStatusBarSafely(Consumer<StatusBarManagerInternal> consumer) {
@@ -2841,6 +2863,12 @@ public class DisplayPolicy {
                pw.print(prefixInner);  pw.println(mLastStatusBarAppearanceRegions[i]);
            }
        }
        if (mLastLetterboxDetails != null) {
            pw.print(prefix); pw.println("mLastLetterboxDetails=");
            for (int i = mLastLetterboxDetails.length - 1; i >= 0; i--) {
                pw.print(prefixInner);  pw.println(mLastLetterboxDetails[i]);
            }
        }
        if (!mStatusBarBackgroundWindows.isEmpty()) {
            pw.print(prefix); pw.println("mStatusBarBackgroundWindows=");
            for (int i = mStatusBarBackgroundWindows.size() - 1; i >= 0; i--) {
+5 −0
Original line number Diff line number Diff line
@@ -138,6 +138,11 @@ public class Letterbox {
        return mInner;
    }

    /** @return The frame that contains the inner frame and the insets. */
    Rect getOuterFrame() {
        return mOuter;
    }

    /**
     * Returns {@code true} if the letterbox does not overlap with the bar, or the letterbox can
     * fully cover the window frame.
+32 −0
Original line number Diff line number Diff line
@@ -68,6 +68,7 @@ import android.view.WindowManager;

import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.statusbar.LetterboxDetails;
import com.android.server.wm.LetterboxConfiguration.LetterboxBackgroundType;

import java.io.PrintWriter;
@@ -141,6 +142,15 @@ final class LetterboxUiController {
        }
    }

    /** Gets the outer bounds of letterbox. The bounds will be empty if there is no letterbox. */
    private void getLetterboxOuterBounds(Rect outBounds) {
        if (mLetterbox != null) {
            outBounds.set(mLetterbox.getOuterFrame());
        } else {
            outBounds.setEmpty();
        }
    }

    /**
     * @return {@code true} if bar shown within a given rectangle is allowed to be fully transparent
     *     when the current activity is displayed.
@@ -683,4 +693,26 @@ final class LetterboxUiController {
        mActivityRecord.mTaskSupervisor.getActivityMetricsLogger()
                .logLetterboxPositionChange(mActivityRecord, letterboxPositionChange);
    }

    @Nullable
    LetterboxDetails getLetterboxDetails() {
        final WindowState w = mActivityRecord.findMainWindow();
        if (mLetterbox == null || w == null || w.isLetterboxedForDisplayCutout()) {
            return null;
        }
        Rect letterboxInnerBounds = new Rect();
        Rect letterboxOuterBounds = new Rect();
        getLetterboxInnerBounds(letterboxInnerBounds);
        getLetterboxOuterBounds(letterboxOuterBounds);

        if (letterboxInnerBounds.isEmpty() || letterboxOuterBounds.isEmpty()) {
            return null;
        }

        return new LetterboxDetails(
                letterboxInnerBounds,
                letterboxOuterBounds,
                w.mAttrs.insetsFlags.appearance
        );
    }
}
+104 −0
Original line number Diff line number Diff line
@@ -61,8 +61,10 @@ import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.ArgumentMatchers.isNull;
import static org.mockito.ArgumentMatchers.same;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.clearInvocations;
@@ -82,11 +84,14 @@ import android.os.UserHandle;
import android.platform.test.annotations.Presubmit;
import android.provider.DeviceConfig;
import android.provider.DeviceConfig.Properties;
import android.view.InsetsVisibilities;
import android.view.WindowManager;

import androidx.test.filters.MediumTest;

import com.android.internal.policy.SystemBarUtils;
import com.android.internal.statusbar.LetterboxDetails;
import com.android.server.statusbar.StatusBarManagerInternal;

import libcore.junit.util.compat.CoreCompatChangeRule.DisableCompatChanges;
import libcore.junit.util.compat.CoreCompatChangeRule.EnableCompatChanges;
@@ -97,6 +102,7 @@ import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestRule;
import org.junit.runner.RunWith;
import org.mockito.Mockito;

/**
 * Tests for Size Compatibility mode.
@@ -2113,6 +2119,104 @@ public class SizeCompatTests extends WindowTestsBase {
        assertLetterboxSurfacesDrawnBetweenActivityAndParentBounds(organizer.mPrimary.getBounds());
    }

    @Test
    public void testLetterboxDetailsForStatusBar_noLetterbox() {
        setUpDisplaySizeWithApp(2800, 1000);
        addStatusBar(mActivity.mDisplayContent);
        addWindowToActivity(mActivity); // Add a window to the activity so that we can get an
        // appearance inside letterboxDetails

        DisplayPolicy displayPolicy = mActivity.getDisplayContent().getDisplayPolicy();
        StatusBarManagerInternal statusBar = displayPolicy.getStatusBarManagerInternal();
        // We should get a null LetterboxDetails object as there is no letterboxed activity, so
        // nothing will get passed to SysUI
        verify(statusBar, never()).onSystemBarAttributesChanged(anyInt(), anyInt(),
                any(), anyBoolean(), anyInt(),
                any(InsetsVisibilities.class), isNull(), isNull());

    }

    @Test
    public void testLetterboxDetailsForStatusBar_letterboxedForMaxAspectRatio() {
        setUpDisplaySizeWithApp(2800, 1000);
        addStatusBar(mActivity.mDisplayContent);
        addWindowToActivity(mActivity); // Add a window to the activity so that we can get an
        // appearance inside letterboxDetails
        // Prepare unresizable activity with max aspect ratio
        prepareUnresizable(mActivity, /* maxAspect */ 1.1f, SCREEN_ORIENTATION_UNSPECIFIED);
        // Refresh the letterbox
        mActivity.mRootWindowContainer.performSurfacePlacement();

        Rect mBounds = new Rect(mActivity.getWindowConfiguration().getBounds());
        assertEquals(mBounds, new Rect(850, 0, 1950, 1000));

        DisplayPolicy displayPolicy = mActivity.getDisplayContent().getDisplayPolicy();
        LetterboxDetails[] expectedLetterboxDetails = {new LetterboxDetails(
                mBounds,
                mActivity.getDisplayContent().getBounds(),
                mActivity.findMainWindow().mAttrs.insetsFlags.appearance
        )};

        // Check that letterboxDetails actually gets passed to SysUI
        StatusBarManagerInternal statusBar = displayPolicy.getStatusBarManagerInternal();
        verify(statusBar).onSystemBarAttributesChanged(anyInt(), anyInt(),
                any(), anyBoolean(), anyInt(),
                any(InsetsVisibilities.class), isNull(), eq(expectedLetterboxDetails));
    }

    @Test
    public void testSplitScreenLetterboxDetailsForStatusBar_twoLetterboxedApps() {
        mAtm.mDevEnableNonResizableMultiWindow = true;
        setUpDisplaySizeWithApp(2800, 1000);
        addStatusBar(mActivity.mDisplayContent);
        // Create another task for the second activity
        final Task newTask = new TaskBuilder(mSupervisor).setDisplay(mActivity.getDisplayContent())
                .setCreateActivity(true).build();
        ActivityRecord newActivity = newTask.getTopNonFinishingActivity();

        final TestSplitOrganizer organizer =
                new TestSplitOrganizer(mAtm, mActivity.getDisplayContent());

        // Move first activity to split screen which takes half of the screen.
        organizer.mPrimary.setBounds(0, 0, 1400, 1000);
        organizer.putTaskToPrimary(mTask, true);
        // Move second activity to split screen which takes half of the screen.
        organizer.mSecondary.setBounds(1400, 0, 2800, 1000);
        organizer.putTaskToSecondary(newTask, true);

        addWindowToActivity(mActivity); // Add a window to the activity so that we can get an
        // appearance inside letterboxDetails
        // Prepare unresizable activity with max aspect ratio
        prepareUnresizable(mActivity, /* maxAspect */ 1.1f, SCREEN_ORIENTATION_UNSPECIFIED);
        addWindowToActivity(newActivity);
        prepareUnresizable(newActivity, /* maxAspect */ 1.1f, SCREEN_ORIENTATION_UNSPECIFIED);

        // Refresh the letterboxes
        newActivity.mRootWindowContainer.performSurfacePlacement();

        Rect mBounds = new Rect(mActivity.getWindowConfiguration().getBounds());
        assertEquals(mBounds, new Rect(150, 0, 1250, 1000));
        final Rect newBounds = new Rect(newActivity.getWindowConfiguration().getBounds());
        assertEquals(newBounds, new Rect(1550, 0, 2650, 1000));

        DisplayPolicy displayPolicy = mActivity.getDisplayContent().getDisplayPolicy();
        LetterboxDetails[] expectedLetterboxDetails = { new LetterboxDetails(
                mBounds,
                organizer.mPrimary.getBounds(),
                mActivity.findMainWindow().mAttrs.insetsFlags.appearance
        ), new LetterboxDetails(
                newBounds,
                organizer.mSecondary.getBounds(),
                newActivity.findMainWindow().mAttrs.insetsFlags.appearance
        )};

        // Check that letterboxDetails actually gets passed to SysUI
        StatusBarManagerInternal statusBar = displayPolicy.getStatusBarManagerInternal();
        verify(statusBar).onSystemBarAttributesChanged(anyInt(), anyInt(),
                any(), anyBoolean(), anyInt(),
                any(InsetsVisibilities.class), isNull(), eq(expectedLetterboxDetails));
    }

    private void recomputeNaturalConfigurationOfUnresizableActivity() {
        // Recompute the natural configuration of the non-resizable activity and the split screen.
        mActivity.clearSizeCompatMode();