Merge "Pass LetterboxDetails to SysUI" into tm-qpr-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
95a0aa965f
@@ -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--) {
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
@@ -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
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
Reference in New Issue
Block a user