summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Vali Calinescu <vcalinescu@google.com> 2022-08-02 11:05:44 +0000
committer Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com> 2022-08-02 11:05:44 +0000
commit3b93fd5831313ff185b27950ca1080b8991eb3fc (patch)
treec9a8b0154c0d9e5e3f4d0304024f6962d0e56bd2
parent3459f452d80d02d5d1384e1694fdc58102876477 (diff)
parent95a0aa965f41f3d034d56c2111f9a09bd37941dd (diff)
Merge "Pass LetterboxDetails to SysUI" into tm-qpr-dev am: 95a0aa965f
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/19377725 Change-Id: Id26c6d726541d47ce5668a80e5e0ac8d862a582d Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
-rw-r--r--services/core/java/com/android/server/wm/DisplayPolicy.java32
-rw-r--r--services/core/java/com/android/server/wm/Letterbox.java5
-rw-r--r--services/core/java/com/android/server/wm/LetterboxUiController.java32
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java104
4 files changed, 171 insertions, 2 deletions
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index 693f9c460ee6..7aa05412ec88 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -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--) {
diff --git a/services/core/java/com/android/server/wm/Letterbox.java b/services/core/java/com/android/server/wm/Letterbox.java
index b5eff41d4f62..df3109ad33c7 100644
--- a/services/core/java/com/android/server/wm/Letterbox.java
+++ b/services/core/java/com/android/server/wm/Letterbox.java
@@ -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.
diff --git a/services/core/java/com/android/server/wm/LetterboxUiController.java b/services/core/java/com/android/server/wm/LetterboxUiController.java
index d65276793700..ec9ee29679a4 100644
--- a/services/core/java/com/android/server/wm/LetterboxUiController.java
+++ b/services/core/java/com/android/server/wm/LetterboxUiController.java
@@ -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
+ );
+ }
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
index 324e244c46f5..21839aac4ec5 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
@@ -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();