Merge changes from topic "max_bounds"

* changes:
  Verify DisplayArea bounds in WindowMetricsTests
  Add DisplayArea support for WM#getMaximumWindowMetrics
This commit is contained in:
TreeHugger Robot
2020-07-28 09:11:34 +00:00
committed by Android (Google) Code Review
12 changed files with 221 additions and 27 deletions

View File

@@ -553,11 +553,13 @@ package android.app {
method public int getActivityType();
method public android.graphics.Rect getAppBounds();
method public android.graphics.Rect getBounds();
method @NonNull public android.graphics.Rect getMaxBounds();
method public int getRotation();
method public int getWindowingMode();
method public void setActivityType(int);
method public void setAppBounds(android.graphics.Rect);
method public void setBounds(android.graphics.Rect);
method public void setMaxBounds(@Nullable android.graphics.Rect);
method public void setRotation(int);
method public void setTo(android.app.WindowConfiguration);
method public void setWindowingMode(int);

View File

@@ -310,7 +310,6 @@ public class WindowConfiguration implements Parcelable, Comparable<WindowConfigu
* Sets the maximum bounds to the provided {@link Rect}.
* @param rect the new bounds value.
* @see #getMaxBounds()
* @hide
*/
public void setMaxBounds(@Nullable Rect rect) {
if (rect == null) {
@@ -364,10 +363,8 @@ public class WindowConfiguration implements Parcelable, Comparable<WindowConfigu
return mBounds;
}
/**
* @see #setMaxBounds(Rect)
* @hide
*/
/** @see #setMaxBounds(Rect) */
@NonNull
public Rect getMaxBounds() {
return mMaxBounds;
}

View File

@@ -26,6 +26,7 @@ import android.annotation.SuppressLint;
import android.annotation.TestApi;
import android.app.KeyguardManager;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.CompatibilityInfo;
import android.content.res.Configuration;
import android.content.res.Resources;
@@ -1157,9 +1158,19 @@ public final class Display {
* </p><p>
* The real size may be smaller than the physical size of the screen when the
* window manager is emulating a smaller display (using adb shell wm size).
* </p>
* </p><p>
* In general, {@link #getRealSize(Point)} and {@link WindowManager#getMaximumWindowMetrics()}
* report the same bounds except that certain areas of the display may not be available to
* windows created in the {@link WindowManager}'s {@link Context}.
*
* For example, imagine a device which has a multi-task mode that limits windows to half of the
* screen. In this case, {@link WindowManager#getMaximumWindowMetrics()} reports the
* bounds of the screen half where the window is located, while {@link #getRealSize(Point)}
* still reports the bounds of the whole display.
*
* @param outSize Set to the real size of the display.
*
* @see WindowManager#getMaximumWindowMetrics()
*/
public void getRealSize(Point outSize) {
synchronized (this) {

View File

@@ -72,6 +72,7 @@ import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.graphics.PixelFormat;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.Region;
import android.os.IBinder;
@@ -473,9 +474,18 @@ public interface WindowManager extends ViewManager {
*
* Note that this might still be smaller than the size of the physical display if certain areas
* of the display are not available to windows created in this {@link Context}.
* <p>
* For example, given that there's a device which have a multi-task mode to limit activities
* to a half screen. In this case, {@link #getMaximumWindowMetrics()} reports the bounds of
* the half screen which the activity is located, while {@link Display#getRealSize(Point)} still
* reports the bounds of the whole physical display.
*
* @see #getMaximumWindowMetrics()
* Despite this, {@link #getMaximumWindowMetrics()} and {@link Display#getRealSize(Point)}
* reports the same bounds in general.
*
* @see #getCurrentWindowMetrics()
* @see WindowMetrics
* @see Display#getRealSize(Point)
*/
default @NonNull WindowMetrics getMaximumWindowMetrics() {
throw new UnsupportedOperationException();

View File

@@ -29,7 +29,6 @@ import android.app.ResourcesManager;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.graphics.Insets;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.Region;
import android.os.Bundle;
@@ -233,17 +232,16 @@ public final class WindowManagerImpl implements WindowManager {
@Override
public WindowMetrics getMaximumWindowMetrics() {
final Rect maxBounds = getMaximumBounds();
final Context context = mParentWindow != null ? mParentWindow.getContext() : mContext;
final Rect maxBounds = getMaximumBounds(context);
return new WindowMetrics(maxBounds, computeWindowInsets(maxBounds));
}
private Rect getMaximumBounds() {
// TODO(b/128338354): Current maximum bound is display size, but it should be displayArea
// bound after displayArea feature is finished.
final Display display = mContext.getDisplayNoVerify();
final Point displaySize = new Point();
display.getRealSize(displaySize);
return new Rect(0, 0, displaySize.x, displaySize.y);
private static Rect getMaximumBounds(Context context) {
synchronized (ResourcesManager.getInstance()) {
return context.getResources().getConfiguration().windowConfiguration.getMaxBounds();
}
}
// TODO(b/150095967): Set window type to LayoutParams

View File

@@ -204,6 +204,7 @@ message DisplayAreaProto {
optional WindowContainerProto window_container = 1;
optional string name = 2 [ (.android.privacy).dest = DEST_EXPLICIT ];
repeated DisplayAreaChildProto children = 3 [deprecated=true];
optional bool is_task_display_area = 4;
}
/* represents a generic child of a DisplayArea */

View File

@@ -93,9 +93,17 @@ public abstract class ConfigurationContainer<E extends ConfigurationContainer> {
private final Rect mTmpRect = new Rect();
static final int BOUNDS_CHANGE_NONE = 0;
// Return value from {@link setBounds} indicating the position of the override bounds changed.
/**
* Return value from {@link #setBounds(Rect)} indicating the position of the override bounds
* changed.
*/
static final int BOUNDS_CHANGE_POSITION = 1;
// Return value from {@link setBounds} indicating the size of the override bounds changed.
/**
* Return value from {@link #setBounds(Rect)} indicating the size of the override bounds
* changed.
*/
static final int BOUNDS_CHANGE_SIZE = 1 << 1;
/**
@@ -226,6 +234,11 @@ public abstract class ConfigurationContainer<E extends ConfigurationContainer> {
return equivalentBounds(getRequestedOverrideBounds(), bounds);
}
/** Similar to {@link #equivalentRequestedOverrideBounds(Rect)}, but compares max bounds. */
public boolean equivalentRequestedOverrideMaxBounds(Rect bounds) {
return equivalentBounds(getRequestedOverrideMaxBounds(), bounds);
}
/**
* Returns whether the two bounds are equal to each other or are a combination of null or empty.
*/
@@ -238,7 +251,6 @@ public abstract class ConfigurationContainer<E extends ConfigurationContainer> {
/**
* Returns the effective bounds of this container, inheriting the first non-empty bounds set in
* its ancestral hierarchy, including itself.
* @return
*/
public Rect getBounds() {
mReturnBounds.set(getConfiguration().windowConfiguration.getBounds());
@@ -249,6 +261,12 @@ public abstract class ConfigurationContainer<E extends ConfigurationContainer> {
outBounds.set(getBounds());
}
/** Similar to {@link #getBounds()}, but reports the max bounds. */
public Rect getMaxBounds() {
mReturnBounds.set(getConfiguration().windowConfiguration.getMaxBounds());
return mReturnBounds;
}
/**
* Sets {@code out} to the top-left corner of the bounds as returned by {@link #getBounds()}.
*/
@@ -273,6 +291,13 @@ public abstract class ConfigurationContainer<E extends ConfigurationContainer> {
return mReturnBounds;
}
/** Similar to {@link #getRequestedOverrideBounds()}, but returns the max bounds. */
public Rect getRequestedOverrideMaxBounds() {
mReturnBounds.set(getRequestedOverrideConfiguration().windowConfiguration.getMaxBounds());
return mReturnBounds;
}
/**
* Returns {@code true} if the {@link WindowConfiguration} in the requested override
* {@link Configuration} specifies bounds.
@@ -283,7 +308,7 @@ public abstract class ConfigurationContainer<E extends ConfigurationContainer> {
/**
* Sets the passed in {@link Rect} to the current bounds.
* @see {@link #getRequestedOverrideBounds()}.
* @see #getRequestedOverrideBounds()
*/
public void getRequestedOverrideBounds(Rect outBounds) {
outBounds.set(getRequestedOverrideBounds());
@@ -295,19 +320,25 @@ public abstract class ConfigurationContainer<E extends ConfigurationContainer> {
* {@link #getRequestedOverrideBounds()}. If
* an empty {@link Rect} or null is specified, this container will be considered to match its
* parent bounds {@see #matchParentBounds} and will inherit bounds from its parent.
*
* @param bounds The bounds defining the container size.
*
* @return a bitmask representing the types of changes made to the bounds.
*/
public int setBounds(Rect bounds) {
int boundsChange = diffRequestedOverrideBounds(bounds);
final boolean overrideMaxBounds = providesMaxBounds()
&& diffRequestedOverrideMaxBounds(bounds) != BOUNDS_CHANGE_NONE;
if (boundsChange == BOUNDS_CHANGE_NONE) {
if (boundsChange == BOUNDS_CHANGE_NONE && !overrideMaxBounds) {
return boundsChange;
}
mRequestsTmpConfig.setTo(getRequestedOverrideConfiguration());
mRequestsTmpConfig.windowConfiguration.setBounds(bounds);
if (overrideMaxBounds) {
mRequestsTmpConfig.windowConfiguration.setMaxBounds(bounds);
}
onRequestedOverrideConfigurationChanged(mRequestsTmpConfig);
return boundsChange;
@@ -318,6 +349,40 @@ public abstract class ConfigurationContainer<E extends ConfigurationContainer> {
return setBounds(mTmpRect);
}
/**
* Returns {@code true} if this {@link ConfigurationContainer} provides the maximum bounds to
* its child {@link ConfigurationContainer}s. Returns {@code false}, otherwise.
* <p>
* The maximum bounds is how large a window can be expanded. Currently only
* {@link DisplayContent} and {@link DisplayArea} effect this property.
* </p>
*/
protected boolean providesMaxBounds() {
return false;
}
int diffRequestedOverrideMaxBounds(Rect bounds) {
if (equivalentRequestedOverrideMaxBounds(bounds)) {
return BOUNDS_CHANGE_NONE;
}
int boundsChange = BOUNDS_CHANGE_NONE;
final Rect existingBounds = getRequestedOverrideMaxBounds();
if (bounds == null || existingBounds.left != bounds.left
|| existingBounds.top != bounds.top) {
boundsChange |= BOUNDS_CHANGE_POSITION;
}
if (bounds == null || existingBounds.width() != bounds.width()
|| existingBounds.height() != bounds.height()) {
boundsChange |= BOUNDS_CHANGE_SIZE;
}
return boundsChange;
}
int diffRequestedOverrideBounds(Rect bounds) {
if (equivalentRequestedOverrideBounds(bounds)) {
return BOUNDS_CHANGE_NONE;
@@ -340,10 +405,6 @@ public abstract class ConfigurationContainer<E extends ConfigurationContainer> {
return boundsChange;
}
boolean hasOverrideConfiguration() {
return mHasOverrideConfiguration;
}
public WindowConfiguration getWindowConfiguration() {
return mFullConfiguration.windowConfiguration;
}

View File

@@ -25,6 +25,7 @@ import static android.window.DisplayAreaOrganizer.FEATURE_UNDEFINED;
import static android.window.DisplayAreaOrganizer.FEATURE_WINDOW_TOKENS;
import static com.android.internal.util.Preconditions.checkState;
import static com.android.server.wm.DisplayAreaProto.IS_TASK_DISPLAY_AREA;
import static com.android.server.wm.DisplayAreaProto.NAME;
import static com.android.server.wm.DisplayAreaProto.WINDOW_CONTAINER;
import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ORIENTATION;
@@ -194,6 +195,7 @@ public class DisplayArea<T extends WindowContainer> extends WindowContainer<T> {
final long token = proto.start(fieldId);
super.dumpDebug(proto, WINDOW_CONTAINER, logLevel);
proto.write(NAME, mName);
proto.write(IS_TASK_DISPLAY_AREA, isTaskDisplayArea());
proto.end(token);
}
@@ -349,6 +351,15 @@ public class DisplayArea<T extends WindowContainer> extends WindowContainer<T> {
return info;
}
@Override
public boolean providesMaxBounds() {
return true;
}
protected boolean isTaskDisplayArea() {
return false;
}
/**
* DisplayArea that contains WindowTokens, and orders them according to their type.
*/

View File

@@ -1930,6 +1930,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
final DisplayInfo displayInfo = updateDisplayAndOrientation(config.uiMode, config);
calculateBounds(displayInfo, mTmpBounds);
config.windowConfiguration.setBounds(mTmpBounds);
config.windowConfiguration.setMaxBounds(mTmpBounds);
config.windowConfiguration.setWindowingMode(getWindowingMode());
config.windowConfiguration.setDisplayWindowingMode(getWindowingMode());
@@ -5389,6 +5390,11 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
});
}
@Override
public boolean providesMaxBounds() {
return true;
}
/** The entry for proceeding to handle {@link #mFixedRotationLaunchingApp}. */
class FixedRotationTransitionListener extends WindowManagerInternal.AppTransitionListener {

View File

@@ -1844,6 +1844,10 @@ final class TaskDisplayArea extends DisplayArea<Task> {
return lastReparentedStack;
}
@Override
protected boolean isTaskDisplayArea() {
return true;
}
@Override
void dump(PrintWriter pw, String prefix, boolean dumpAll) {

View File

@@ -33,6 +33,7 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import android.content.res.Configuration;
import android.graphics.Rect;
import android.platform.test.annotations.Presubmit;
import androidx.test.filters.SmallTest;
@@ -324,6 +325,47 @@ public class ConfigurationContainerTests {
assertEquals(100, listener.mOverrideConfiguration.smallestScreenWidthDp);
}
@Test
public void testSetMaxBoundsByHierarchy() {
final TestConfigurationContainer root =
new TestConfigurationContainer(true /* providesMaxBounds */);
final Rect bounds = new Rect(0, 0, 10, 10);
final TestConfigurationContainer child = new TestConfigurationContainer();
root.addChild(child);
root.setBounds(bounds);
assertEquals(bounds, root.getBounds());
assertEquals(bounds, root.getConfiguration().windowConfiguration.getBounds());
assertEquals(bounds, child.getBounds());
assertEquals(bounds, child.getConfiguration().windowConfiguration.getBounds());
assertEquals(bounds, root.getMaxBounds());
assertEquals(bounds, root.getConfiguration().windowConfiguration.getMaxBounds());
assertEquals(bounds, child.getMaxBounds());
assertEquals(bounds, child.getConfiguration().windowConfiguration.getMaxBounds());
}
@Test
public void testSetBoundsNotOverrideMaxBounds() {
final TestConfigurationContainer root = new TestConfigurationContainer();
final Rect bounds = new Rect(0, 0, 10, 10);
final TestConfigurationContainer child = new TestConfigurationContainer();
root.addChild(child);
root.setBounds(bounds);
assertEquals(bounds, root.getBounds());
assertEquals(bounds, root.getConfiguration().windowConfiguration.getBounds());
assertEquals(bounds, child.getBounds());
assertEquals(bounds, child.getConfiguration().windowConfiguration.getBounds());
assertTrue(root.getMaxBounds().isEmpty());
assertTrue(root.getConfiguration().windowConfiguration.getMaxBounds().isEmpty());
assertTrue(child.getMaxBounds().isEmpty());
assertTrue(child.getConfiguration().windowConfiguration.getMaxBounds().isEmpty());
}
/**
* Contains minimal implementation of {@link ConfigurationContainer}'s abstract behavior needed
* for testing.
@@ -333,6 +375,14 @@ public class ConfigurationContainerTests {
private List<TestConfigurationContainer> mChildren = new ArrayList<>();
private TestConfigurationContainer mParent;
private boolean mProvidesMaxBounds = false;
TestConfigurationContainer() {}
TestConfigurationContainer(boolean providesMaxBounds) {
mProvidesMaxBounds = providesMaxBounds;
}
TestConfigurationContainer addChild(TestConfigurationContainer childContainer) {
final ConfigurationContainer oldParent = childContainer.getParent();
childContainer.mParent = this;
@@ -369,6 +419,11 @@ public class ConfigurationContainerTests {
protected ConfigurationContainer getParent() {
return mParent;
}
@Override
public boolean providesMaxBounds() {
return mProvidesMaxBounds;
}
}
/**

View File

@@ -16,6 +16,7 @@
package com.android.server.wm;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
import static android.view.WindowManager.LayoutParams.TYPE_PRESENTATION;
import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
@@ -40,8 +41,10 @@ import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyZeroInteractions;
import android.graphics.Rect;
import android.os.Binder;
import android.platform.test.annotations.Presubmit;
import android.view.SurfaceControl;
import com.google.android.collect.Lists;
@@ -63,7 +66,6 @@ import java.util.function.Function;
*/
@Presubmit
public class DisplayAreaTest {
@Rule
public SystemServicesTestRule mWmsRule = new SystemServicesTestRule();
@@ -379,6 +381,42 @@ public class DisplayAreaTest {
assertThat(result).isEqualTo(tda1);
}
@Test
public void testSetMaxBounds() {
final Rect parentBounds = new Rect(0, 0, 100, 100);
final Rect childBounds1 = new Rect(parentBounds.left, parentBounds.top,
parentBounds.right / 2, parentBounds.bottom);
final Rect childBounds2 = new Rect(parentBounds.right / 2, parentBounds.top,
parentBounds.right, parentBounds.bottom);
TestDisplayArea parentDa = new TestDisplayArea(mWms, parentBounds);
TestDisplayArea childDa1 = new TestDisplayArea(mWms, childBounds1);
TestDisplayArea childDa2 = new TestDisplayArea(mWms, childBounds2);
parentDa.addChild(childDa1, 0);
parentDa.addChild(childDa2, 1);
assertEquals(parentBounds, parentDa.getMaxBounds());
assertEquals(childBounds1, childDa1.getMaxBounds());
assertEquals(childBounds2, childDa2.getMaxBounds());
final WindowToken windowToken = createWindowToken(TYPE_APPLICATION);
childDa1.addChild(windowToken, 0);
assertEquals("DisplayArea's children must have the same max bounds as itself",
childBounds1, windowToken.getMaxBounds());
}
private static class TestDisplayArea<T extends WindowContainer> extends DisplayArea<T> {
private TestDisplayArea(WindowManagerService wms, Rect bounds) {
super(wms, ANY, "half display area");
setBounds(bounds);
}
@Override
SurfaceControl.Builder makeChildSurface(WindowContainer child) {
return new MockSurfaceControlBuilder();
}
}
private WindowToken createWindowToken(int type) {
return new WindowToken(mWmsRule.getWindowManagerService(), new Binder(),
type, false /* persist */, null /* displayContent */,