Merge "Pass LetterboxDetails to SysUI" into tm-qpr-dev

This commit is contained in:
Vali Calinescu
2022-08-02 10:50:22 +00:00
committed by Android (Google) Code Review
4 changed files with 171 additions and 2 deletions

View File

@@ -318,12 +318,19 @@ public class DisplayPolicy {
*/ */
private final ArrayList<WindowState> mStatusBarBackgroundWindows = new ArrayList<>(); 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 String mFocusedApp;
private int mLastDisableFlags; private int mLastDisableFlags;
private int mLastAppearance; private int mLastAppearance;
private int mLastBehavior; private int mLastBehavior;
private InsetsVisibilities mRequestedVisibilities = new InsetsVisibilities(); private InsetsVisibilities mRequestedVisibilities = new InsetsVisibilities();
private AppearanceRegion[] mLastStatusBarAppearanceRegions; private AppearanceRegion[] mLastStatusBarAppearanceRegions;
private LetterboxDetails[] mLastLetterboxDetails;
/** The union of checked bounds while building {@link #mStatusBarAppearanceRegionList}. */ /** The union of checked bounds while building {@link #mStatusBarAppearanceRegionList}. */
private final Rect mStatusBarColorCheckedBounds = new Rect(); private final Rect mStatusBarColorCheckedBounds = new Rect();
@@ -1638,6 +1645,7 @@ public class DisplayPolicy {
mNavBarColorWindowCandidate = null; mNavBarColorWindowCandidate = null;
mNavBarBackgroundWindow = null; mNavBarBackgroundWindow = null;
mStatusBarAppearanceRegionList.clear(); mStatusBarAppearanceRegionList.clear();
mLetterboxDetails.clear();
mStatusBarBackgroundWindows.clear(); mStatusBarBackgroundWindows.clear();
mStatusBarColorCheckedBounds.setEmpty(); mStatusBarColorCheckedBounds.setEmpty();
mStatusBarBackgroundCheckedBounds.setEmpty(); mStatusBarBackgroundCheckedBounds.setEmpty();
@@ -1717,6 +1725,16 @@ public class DisplayPolicy {
win.mAttrs.insetsFlags.appearance & APPEARANCE_LIGHT_STATUS_BARS, win.mAttrs.insetsFlags.appearance & APPEARANCE_LIGHT_STATUS_BARS,
new Rect(win.getFrame()))); new Rect(win.getFrame())));
mStatusBarColorCheckedBounds.union(sTmpRect); 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, callStatusBarSafely(statusBar -> statusBar.setDisableFlags(displayId, disableFlags,
cause)); cause));
} }
final LetterboxDetails[] letterboxDetails = new LetterboxDetails[mLetterboxDetails.size()];
mLetterboxDetails.toArray(letterboxDetails);
if (mLastAppearance == appearance if (mLastAppearance == appearance
&& mLastBehavior == behavior && mLastBehavior == behavior
&& mRequestedVisibilities.equals(win.getRequestedVisibilities()) && mRequestedVisibilities.equals(win.getRequestedVisibilities())
&& Objects.equals(mFocusedApp, focusedApp) && Objects.equals(mFocusedApp, focusedApp)
&& mLastFocusIsFullscreen == isFullscreen && mLastFocusIsFullscreen == isFullscreen
&& Arrays.equals(mLastStatusBarAppearanceRegions, statusBarAppearanceRegions)) { && Arrays.equals(mLastStatusBarAppearanceRegions, statusBarAppearanceRegions)
&& Arrays.equals(mLastLetterboxDetails, letterboxDetails)) {
return; return;
} }
if (mDisplayContent.isDefaultDisplay && mLastFocusIsFullscreen != isFullscreen if (mDisplayContent.isDefaultDisplay && mLastFocusIsFullscreen != isFullscreen
@@ -2425,9 +2446,10 @@ public class DisplayPolicy {
mFocusedApp = focusedApp; mFocusedApp = focusedApp;
mLastFocusIsFullscreen = isFullscreen; mLastFocusIsFullscreen = isFullscreen;
mLastStatusBarAppearanceRegions = statusBarAppearanceRegions; mLastStatusBarAppearanceRegions = statusBarAppearanceRegions;
mLastLetterboxDetails = letterboxDetails;
callStatusBarSafely(statusBar -> statusBar.onSystemBarAttributesChanged(displayId, callStatusBarSafely(statusBar -> statusBar.onSystemBarAttributesChanged(displayId,
appearance, statusBarAppearanceRegions, isNavbarColorManagedByIme, behavior, appearance, statusBarAppearanceRegions, isNavbarColorManagedByIme, behavior,
requestedVisibilities, focusedApp, new LetterboxDetails[]{})); requestedVisibilities, focusedApp, letterboxDetails));
} }
private void callStatusBarSafely(Consumer<StatusBarManagerInternal> consumer) { private void callStatusBarSafely(Consumer<StatusBarManagerInternal> consumer) {
@@ -2841,6 +2863,12 @@ public class DisplayPolicy {
pw.print(prefixInner); pw.println(mLastStatusBarAppearanceRegions[i]); 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()) { if (!mStatusBarBackgroundWindows.isEmpty()) {
pw.print(prefix); pw.println("mStatusBarBackgroundWindows="); pw.print(prefix); pw.println("mStatusBarBackgroundWindows=");
for (int i = mStatusBarBackgroundWindows.size() - 1; i >= 0; i--) { for (int i = mStatusBarBackgroundWindows.size() - 1; i >= 0; i--) {

View File

@@ -138,6 +138,11 @@ public class Letterbox {
return mInner; 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 * Returns {@code true} if the letterbox does not overlap with the bar, or the letterbox can
* fully cover the window frame. * fully cover the window frame.

View File

@@ -68,6 +68,7 @@ import android.view.WindowManager;
import com.android.internal.R; import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting; import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.statusbar.LetterboxDetails;
import com.android.server.wm.LetterboxConfiguration.LetterboxBackgroundType; import com.android.server.wm.LetterboxConfiguration.LetterboxBackgroundType;
import java.io.PrintWriter; 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 * @return {@code true} if bar shown within a given rectangle is allowed to be fully transparent
* when the current activity is displayed. * when the current activity is displayed.
@@ -683,4 +693,26 @@ final class LetterboxUiController {
mActivityRecord.mTaskSupervisor.getActivityMetricsLogger() mActivityRecord.mTaskSupervisor.getActivityMetricsLogger()
.logLetterboxPositionChange(mActivityRecord, letterboxPositionChange); .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
);
}
} }

View File

@@ -61,8 +61,10 @@ import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.argThat; import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.ArgumentMatchers.isNull;
import static org.mockito.ArgumentMatchers.same; import static org.mockito.ArgumentMatchers.same;
import static org.mockito.Mockito.atLeastOnce; import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.clearInvocations; import static org.mockito.Mockito.clearInvocations;
@@ -82,11 +84,14 @@ import android.os.UserHandle;
import android.platform.test.annotations.Presubmit; import android.platform.test.annotations.Presubmit;
import android.provider.DeviceConfig; import android.provider.DeviceConfig;
import android.provider.DeviceConfig.Properties; import android.provider.DeviceConfig.Properties;
import android.view.InsetsVisibilities;
import android.view.WindowManager; import android.view.WindowManager;
import androidx.test.filters.MediumTest; import androidx.test.filters.MediumTest;
import com.android.internal.policy.SystemBarUtils; 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.DisableCompatChanges;
import libcore.junit.util.compat.CoreCompatChangeRule.EnableCompatChanges; import libcore.junit.util.compat.CoreCompatChangeRule.EnableCompatChanges;
@@ -97,6 +102,7 @@ import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import org.junit.rules.TestRule; import org.junit.rules.TestRule;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.mockito.Mockito;
/** /**
* Tests for Size Compatibility mode. * Tests for Size Compatibility mode.
@@ -2113,6 +2119,104 @@ public class SizeCompatTests extends WindowTestsBase {
assertLetterboxSurfacesDrawnBetweenActivityAndParentBounds(organizer.mPrimary.getBounds()); 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() { private void recomputeNaturalConfigurationOfUnresizableActivity() {
// Recompute the natural configuration of the non-resizable activity and the split screen. // Recompute the natural configuration of the non-resizable activity and the split screen.
mActivity.clearSizeCompatMode(); mActivity.clearSizeCompatMode();