Merge "Home tasks inherit split or fullscreen from parent." into rvc-dev am: 48c653a2c1

Change-Id: If7aafe435352b4ca63fcd36bcbb207d9f7f4fd95
This commit is contained in:
Evan Rosky
2020-04-21 11:13:11 +00:00
committed by Automerger Merge Worker
4 changed files with 77 additions and 52 deletions

View File

@@ -2225,14 +2225,16 @@ class Task extends WindowContainer<WindowContainer> {
} }
density *= DisplayMetrics.DENSITY_DEFAULT_SCALE; density *= DisplayMetrics.DENSITY_DEFAULT_SCALE;
// If bounds have been overridden at this level, restrict config resources to these bounds
// rather than the parent because the overridden bounds can be larger than the parent.
boolean hasOverrideBounds = false;
final Rect resolvedBounds = inOutConfig.windowConfiguration.getBounds(); final Rect resolvedBounds = inOutConfig.windowConfiguration.getBounds();
if (resolvedBounds == null) { if (resolvedBounds == null || resolvedBounds.isEmpty()) {
mTmpFullBounds.setEmpty(); mTmpFullBounds.set(parentConfig.windowConfiguration.getBounds());
} else { } else {
mTmpFullBounds.set(resolvedBounds); mTmpFullBounds.set(resolvedBounds);
} hasOverrideBounds = true;
if (mTmpFullBounds.isEmpty()) {
mTmpFullBounds.set(parentConfig.windowConfiguration.getBounds());
} }
Rect outAppBounds = inOutConfig.windowConfiguration.getAppBounds(); Rect outAppBounds = inOutConfig.windowConfiguration.getAppBounds();
@@ -2244,7 +2246,16 @@ class Task extends WindowContainer<WindowContainer> {
// the out bounds doesn't need to be restricted by the parent. // the out bounds doesn't need to be restricted by the parent.
final boolean insideParentBounds = compatInsets == null; final boolean insideParentBounds = compatInsets == null;
if (insideParentBounds && windowingMode != WINDOWING_MODE_FREEFORM) { if (insideParentBounds && windowingMode != WINDOWING_MODE_FREEFORM) {
final Rect parentAppBounds = parentConfig.windowConfiguration.getAppBounds(); Rect parentAppBounds;
if (hasOverrideBounds) {
// Since we overrode the bounds, restrict appBounds to display non-decor rather
// than parent. Otherwise, it won't match the overridden bounds.
final TaskDisplayArea displayArea = getDisplayArea();
parentAppBounds = displayArea != null
? displayArea.getConfiguration().windowConfiguration.getAppBounds() : null;
} else {
parentAppBounds = parentConfig.windowConfiguration.getAppBounds();
}
if (parentAppBounds != null && !parentAppBounds.isEmpty()) { if (parentAppBounds != null && !parentAppBounds.isEmpty()) {
outAppBounds.intersect(parentAppBounds); outAppBounds.intersect(parentAppBounds);
} }
@@ -2291,13 +2302,13 @@ class Task extends WindowContainer<WindowContainer> {
if (inOutConfig.screenWidthDp == Configuration.SCREEN_WIDTH_DP_UNDEFINED) { if (inOutConfig.screenWidthDp == Configuration.SCREEN_WIDTH_DP_UNDEFINED) {
final int overrideScreenWidthDp = (int) (mTmpStableBounds.width() / density); final int overrideScreenWidthDp = (int) (mTmpStableBounds.width() / density);
inOutConfig.screenWidthDp = insideParentBounds inOutConfig.screenWidthDp = (insideParentBounds && !hasOverrideBounds)
? Math.min(overrideScreenWidthDp, parentConfig.screenWidthDp) ? Math.min(overrideScreenWidthDp, parentConfig.screenWidthDp)
: overrideScreenWidthDp; : overrideScreenWidthDp;
} }
if (inOutConfig.screenHeightDp == Configuration.SCREEN_HEIGHT_DP_UNDEFINED) { if (inOutConfig.screenHeightDp == Configuration.SCREEN_HEIGHT_DP_UNDEFINED) {
final int overrideScreenHeightDp = (int) (mTmpStableBounds.height() / density); final int overrideScreenHeightDp = (int) (mTmpStableBounds.height() / density);
inOutConfig.screenHeightDp = insideParentBounds inOutConfig.screenHeightDp = (insideParentBounds && !hasOverrideBounds)
? Math.min(overrideScreenHeightDp, parentConfig.screenHeightDp) ? Math.min(overrideScreenHeightDp, parentConfig.screenHeightDp)
: overrideScreenHeightDp; : overrideScreenHeightDp;
} }
@@ -2344,27 +2355,27 @@ class Task extends WindowContainer<WindowContainer> {
mTmpBounds.set(getResolvedOverrideConfiguration().windowConfiguration.getBounds()); mTmpBounds.set(getResolvedOverrideConfiguration().windowConfiguration.getBounds());
super.resolveOverrideConfiguration(newParentConfig); super.resolveOverrideConfiguration(newParentConfig);
// Resolve override windowing mode to fullscreen for home task (even on freeform
// display), or split-screen-secondary if in split-screen mode.
int windowingMode = int windowingMode =
getResolvedOverrideConfiguration().windowConfiguration.getWindowingMode(); getResolvedOverrideConfiguration().windowConfiguration.getWindowingMode();
// Resolve override windowing mode to fullscreen for home task (even on freeform
// display), or split-screen if in split-screen mode.
if (getActivityType() == ACTIVITY_TYPE_HOME && windowingMode == WINDOWING_MODE_UNDEFINED) { if (getActivityType() == ACTIVITY_TYPE_HOME && windowingMode == WINDOWING_MODE_UNDEFINED) {
final int parentWindowingMode = newParentConfig.windowConfiguration.getWindowingMode(); final int parentWindowingMode = newParentConfig.windowConfiguration.getWindowingMode();
windowingMode = parentWindowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY windowingMode = WindowConfiguration.isSplitScreenWindowingMode(parentWindowingMode)
? WINDOWING_MODE_SPLIT_SCREEN_SECONDARY ? parentWindowingMode : WINDOWING_MODE_FULLSCREEN;
: WINDOWING_MODE_FULLSCREEN;
getResolvedOverrideConfiguration().windowConfiguration.setWindowingMode(windowingMode); getResolvedOverrideConfiguration().windowConfiguration.setWindowingMode(windowingMode);
} }
if (!isLeafTask()) { if (isLeafTask()) {
// Compute configuration overrides for tasks that created by organizer, so that resolveLeafOnlyOverrideConfigs(newParentConfig);
// organizer can get the correct configuration from those tasks. }
if (mCreatedByOrganizer) {
computeConfigResourceOverrides(getResolvedOverrideConfiguration(), newParentConfig); computeConfigResourceOverrides(getResolvedOverrideConfiguration(), newParentConfig);
} }
return;
}
void resolveLeafOnlyOverrideConfigs(Configuration newParentConfig) {
int windowingMode =
getResolvedOverrideConfiguration().windowConfiguration.getWindowingMode();
if (windowingMode == WINDOWING_MODE_UNDEFINED) { if (windowingMode == WINDOWING_MODE_UNDEFINED) {
windowingMode = newParentConfig.windowConfiguration.getWindowingMode(); windowingMode = newParentConfig.windowConfiguration.getWindowingMode();
} }
@@ -2404,7 +2415,6 @@ class Task extends WindowContainer<WindowContainer> {
outOverrideBounds.offset(0, offsetTop); outOverrideBounds.offset(0, offsetTop);
} }
} }
computeConfigResourceOverrides(getResolvedOverrideConfiguration(), newParentConfig);
} }
/** /**

View File

@@ -329,6 +329,7 @@ class ActivityTestsBase extends SystemServiceTestsBase {
private boolean mCreateStack = true; private boolean mCreateStack = true;
private ActivityStack mStack; private ActivityStack mStack;
private TaskDisplayArea mTaskDisplayArea;
TaskBuilder(ActivityStackSupervisor supervisor) { TaskBuilder(ActivityStackSupervisor supervisor) {
mSupervisor = supervisor; mSupervisor = supervisor;
@@ -378,9 +379,16 @@ class ActivityTestsBase extends SystemServiceTestsBase {
return this; return this;
} }
TaskBuilder setDisplay(DisplayContent display) {
mTaskDisplayArea = display.getDefaultTaskDisplayArea();
return this;
}
Task build() { Task build() {
if (mStack == null && mCreateStack) { if (mStack == null && mCreateStack) {
mStack = mSupervisor.mRootWindowContainer.getDefaultTaskDisplayArea().createStack( TaskDisplayArea displayArea = mTaskDisplayArea != null ? mTaskDisplayArea
: mSupervisor.mRootWindowContainer.getDefaultTaskDisplayArea();
mStack = displayArea.createStack(
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */); WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
spyOn(mStack); spyOn(mStack);
} }

View File

@@ -54,10 +54,7 @@ import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertThat; import static org.junit.Assert.assertThat;
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.anyInt;
import static org.mockito.ArgumentMatchers.same; import static org.mockito.ArgumentMatchers.same;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import android.app.ActivityManager; import android.app.ActivityManager;
import android.app.TaskInfo; import android.app.TaskInfo;
@@ -75,12 +72,10 @@ import android.util.DisplayMetrics;
import android.util.Xml; import android.util.Xml;
import android.view.DisplayInfo; import android.view.DisplayInfo;
import androidx.test.filters.FlakyTest;
import androidx.test.filters.MediumTest; import androidx.test.filters.MediumTest;
import com.android.internal.app.IVoiceInteractor; import com.android.internal.app.IVoiceInteractor;
import com.android.server.wm.Task.TaskFactory; import com.android.server.wm.Task.TaskFactory;
import com.android.server.wm.utils.WmDisplayCutout;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
@@ -368,25 +363,38 @@ public class TaskRecordTests extends ActivityTestsBase {
@Test @Test
public void testComputeConfigResourceOverrides() { public void testComputeConfigResourceOverrides() {
final Task task = new TaskBuilder(mSupervisor).build(); final Rect fullScreenBounds = new Rect(0, 0, 1080, 1920);
TestDisplayContent display = new TestDisplayContent.Builder(
mService, fullScreenBounds.width(), fullScreenBounds.height()).build();
final Task task = new TaskBuilder(mSupervisor).setDisplay(display).build();
final Configuration inOutConfig = new Configuration(); final Configuration inOutConfig = new Configuration();
final Configuration parentConfig = new Configuration(); final Configuration parentConfig = new Configuration();
final int longSide = 1200; final int longSide = 1200;
final int shortSide = 600; final int shortSide = 600;
final Rect parentBounds = new Rect(0, 0, 250, 500);
parentConfig.windowConfiguration.setBounds(parentBounds);
parentConfig.densityDpi = 400; parentConfig.densityDpi = 400;
parentConfig.screenHeightDp = 200; // 200 * 400 / 160 = 500px parentConfig.screenHeightDp = (parentBounds.bottom * 160) / parentConfig.densityDpi; // 200
parentConfig.screenWidthDp = 100; // 100 * 400 / 160 = 250px parentConfig.screenWidthDp = (parentBounds.right * 160) / parentConfig.densityDpi; // 100
parentConfig.windowConfiguration.setRotation(ROTATION_0); parentConfig.windowConfiguration.setRotation(ROTATION_0);
// Portrait bounds. // By default, the input bounds will fill parent.
inOutConfig.windowConfiguration.getBounds().set(0, 0, shortSide, longSide);
// By default, the parent bounds should limit the existing input bounds.
task.computeConfigResourceOverrides(inOutConfig, parentConfig); task.computeConfigResourceOverrides(inOutConfig, parentConfig);
assertEquals(parentConfig.screenHeightDp, inOutConfig.screenHeightDp); assertEquals(parentConfig.screenHeightDp, inOutConfig.screenHeightDp);
assertEquals(parentConfig.screenWidthDp, inOutConfig.screenWidthDp); assertEquals(parentConfig.screenWidthDp, inOutConfig.screenWidthDp);
assertEquals(Configuration.ORIENTATION_PORTRAIT, inOutConfig.orientation); assertEquals(Configuration.ORIENTATION_PORTRAIT, inOutConfig.orientation);
// If bounds are overridden, config properties should be made to match. Surface hierarchy
// will crop for policy.
inOutConfig.setToDefaults();
inOutConfig.windowConfiguration.getBounds().set(0, 0, shortSide, longSide);
// By default, the parent bounds should limit the existing input bounds.
task.computeConfigResourceOverrides(inOutConfig, parentConfig);
assertEquals(longSide, inOutConfig.screenHeightDp * parentConfig.densityDpi / 160);
assertEquals(shortSide, inOutConfig.screenWidthDp * parentConfig.densityDpi / 160);
inOutConfig.setToDefaults(); inOutConfig.setToDefaults();
// Landscape bounds. // Landscape bounds.
inOutConfig.windowConfiguration.getBounds().set(0, 0, longSide, shortSide); inOutConfig.windowConfiguration.getBounds().set(0, 0, longSide, shortSide);
@@ -394,21 +402,17 @@ public class TaskRecordTests extends ActivityTestsBase {
// Setup the display with a top stable inset. The later assertion will ensure the inset is // Setup the display with a top stable inset. The later assertion will ensure the inset is
// excluded from screenHeightDp. // excluded from screenHeightDp.
final int statusBarHeight = 100; final int statusBarHeight = 100;
final DisplayContent displayContent = task.mDisplayContent; final DisplayPolicy policy = display.getDisplayPolicy();
final DisplayPolicy policy = mock(DisplayPolicy.class);
doAnswer(invocationOnMock -> { doAnswer(invocationOnMock -> {
final Rect insets = invocationOnMock.<Rect>getArgument(0); final Rect insets = invocationOnMock.<Rect>getArgument(0);
insets.top = statusBarHeight; insets.top = statusBarHeight;
return null; return null;
}).when(policy).convertNonDecorInsetsToStableInsets(any(), eq(ROTATION_0)); }).when(policy).convertNonDecorInsetsToStableInsets(any(), eq(ROTATION_0));
doReturn(policy).when(displayContent).getDisplayPolicy();
doReturn(mock(WmDisplayCutout.class)).when(displayContent)
.calculateDisplayCutoutForRotation(anyInt());
// Without limiting to be inside the parent bounds, the out screen size should keep relative // Without limiting to be inside the parent bounds, the out screen size should keep relative
// to the input bounds. // to the input bounds.
final ActivityRecord.CompatDisplayInsets compatIntsets = final ActivityRecord.CompatDisplayInsets compatIntsets =
new ActivityRecord.CompatDisplayInsets(displayContent, task); new ActivityRecord.CompatDisplayInsets(display, task);
task.computeConfigResourceOverrides(inOutConfig, parentConfig, compatIntsets); task.computeConfigResourceOverrides(inOutConfig, parentConfig, compatIntsets);
assertEquals((shortSide - statusBarHeight) * DENSITY_DEFAULT / parentConfig.densityDpi, assertEquals((shortSide - statusBarHeight) * DENSITY_DEFAULT / parentConfig.densityDpi,
@@ -454,7 +458,6 @@ public class TaskRecordTests extends ActivityTestsBase {
parentConfig.screenWidthDp = 100; // 100 * 400 / 160 = 250px parentConfig.screenWidthDp = 100; // 100 * 400 / 160 = 250px
parentConfig.windowConfiguration.setRotation(ROTATION_0); parentConfig.windowConfiguration.setRotation(ROTATION_0);
final float density = 2.5f; // densityDpi / DENSITY_DEFAULT_SCALE = 400 / 160.0f
final int longSideDp = 480; // longSide / density = 1200 / 400 * 160 final int longSideDp = 480; // longSide / density = 1200 / 400 * 160
final int shortSideDp = 240; // shortSide / density = 600 / 400 * 160 final int shortSideDp = 240; // shortSide / density = 600 / 400 * 160
final int screenLayout = parentConfig.screenLayout final int screenLayout = parentConfig.screenLayout
@@ -463,31 +466,38 @@ public class TaskRecordTests extends ActivityTestsBase {
Configuration.reduceScreenLayout(screenLayout, longSideDp, shortSideDp); Configuration.reduceScreenLayout(screenLayout, longSideDp, shortSideDp);
// Portrait bounds overlapping with navigation bar, without insets. // Portrait bounds overlapping with navigation bar, without insets.
inOutConfig.windowConfiguration.getBounds().set(0, final Rect freeformBounds = new Rect(0,
displayHeight - 10 - longSide, displayHeight - 10 - longSide,
shortSide, shortSide,
displayHeight - 10); displayHeight - 10);
inOutConfig.windowConfiguration.setBounds(freeformBounds);
// Set to freeform mode to verify bug fix. // Set to freeform mode to verify bug fix.
inOutConfig.windowConfiguration.setWindowingMode(WINDOWING_MODE_FREEFORM); inOutConfig.windowConfiguration.setWindowingMode(WINDOWING_MODE_FREEFORM);
task.computeConfigResourceOverrides(inOutConfig, parentConfig); task.computeConfigResourceOverrides(inOutConfig, parentConfig);
assertEquals(parentConfig.screenWidthDp, inOutConfig.screenWidthDp); // screenW/H should not be effected by parent since overridden and freeform
assertEquals(parentConfig.screenHeightDp, inOutConfig.screenHeightDp); assertEquals(freeformBounds.width() * 160 / parentConfig.densityDpi,
inOutConfig.screenWidthDp);
assertEquals(freeformBounds.height() * 160 / parentConfig.densityDpi,
inOutConfig.screenHeightDp);
assertEquals(reducedScreenLayout, inOutConfig.screenLayout); assertEquals(reducedScreenLayout, inOutConfig.screenLayout);
inOutConfig.setToDefaults(); inOutConfig.setToDefaults();
// Landscape bounds overlapping with navigtion bar, without insets. // Landscape bounds overlapping with navigtion bar, without insets.
inOutConfig.windowConfiguration.getBounds().set(0, freeformBounds.set(0,
displayHeight - 10 - shortSide, displayHeight - 10 - shortSide,
longSide, longSide,
displayHeight - 10); displayHeight - 10);
inOutConfig.windowConfiguration.setBounds(freeformBounds);
inOutConfig.windowConfiguration.setWindowingMode(WINDOWING_MODE_FREEFORM); inOutConfig.windowConfiguration.setWindowingMode(WINDOWING_MODE_FREEFORM);
task.computeConfigResourceOverrides(inOutConfig, parentConfig); task.computeConfigResourceOverrides(inOutConfig, parentConfig);
assertEquals(parentConfig.screenWidthDp, inOutConfig.screenWidthDp); assertEquals(freeformBounds.width() * 160 / parentConfig.densityDpi,
assertEquals(parentConfig.screenHeightDp, inOutConfig.screenHeightDp); inOutConfig.screenWidthDp);
assertEquals(freeformBounds.height() * 160 / parentConfig.densityDpi,
inOutConfig.screenHeightDp);
assertEquals(reducedScreenLayout, inOutConfig.screenLayout); assertEquals(reducedScreenLayout, inOutConfig.screenLayout);
} }

View File

@@ -44,7 +44,6 @@ import static com.android.server.wm.WindowContainer.POSITION_TOP;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.any;
@@ -407,22 +406,20 @@ public class WindowOrganizerTests extends WindowTestsBase {
.setWindowingMode(WINDOWING_MODE_FREEFORM).build(); .setWindowingMode(WINDOWING_MODE_FREEFORM).build();
final Task task = stack.getTopMostTask(); final Task task = stack.getTopMostTask();
WindowContainerTransaction t = new WindowContainerTransaction(); WindowContainerTransaction t = new WindowContainerTransaction();
t.setBounds(task.mRemoteToken.toWindowContainerToken(), new Rect(10, 10, 100, 100));
mWm.mAtmService.mWindowOrganizerController.applyTransaction(t); mWm.mAtmService.mWindowOrganizerController.applyTransaction(t);
final int origScreenWDp = task.getConfiguration().screenHeightDp; final int origScreenWDp = task.getConfiguration().screenHeightDp;
final int origScreenHDp = task.getConfiguration().screenHeightDp; final int origScreenHDp = task.getConfiguration().screenHeightDp;
t = new WindowContainerTransaction(); t = new WindowContainerTransaction();
// verify that setting config overrides on parent restricts children. // verify that setting config overrides on parent restricts children.
t.setScreenSizeDp(stack.mRemoteToken t.setScreenSizeDp(stack.mRemoteToken
.toWindowContainerToken(), origScreenWDp, origScreenHDp); .toWindowContainerToken(), origScreenWDp, origScreenHDp / 2);
t.setBounds(task.mRemoteToken.toWindowContainerToken(), new Rect(10, 10, 150, 200));
mWm.mAtmService.mWindowOrganizerController.applyTransaction(t); mWm.mAtmService.mWindowOrganizerController.applyTransaction(t);
assertEquals(origScreenHDp, task.getConfiguration().screenHeightDp); assertEquals(origScreenHDp / 2, task.getConfiguration().screenHeightDp);
t = new WindowContainerTransaction(); t = new WindowContainerTransaction();
t.setScreenSizeDp(stack.mRemoteToken.toWindowContainerToken(), SCREEN_WIDTH_DP_UNDEFINED, t.setScreenSizeDp(stack.mRemoteToken.toWindowContainerToken(), SCREEN_WIDTH_DP_UNDEFINED,
SCREEN_HEIGHT_DP_UNDEFINED); SCREEN_HEIGHT_DP_UNDEFINED);
mWm.mAtmService.mWindowOrganizerController.applyTransaction(t); mWm.mAtmService.mWindowOrganizerController.applyTransaction(t);
assertNotEquals(origScreenHDp, task.getConfiguration().screenHeightDp); assertEquals(origScreenHDp, task.getConfiguration().screenHeightDp);
} }
@Test @Test