Task letterbox for resizable fixed-orientation app in dual DisplayAreas
Before, when both DisplayAreaGroups set ignoreOrientationRequest to false, launching two resizable apps with different orientations will end up with two apps in the same orientations. One app is in the orientation different from its request. This is because Task only letterboxes when ignoreOrientationRequest is true, but it should also letterbox when the TaskDisplayArea can't specify orientation (happens when it doesn't have focus). Bug: 176566401 Test: atest WmTests:DualDisplayAreaGroupPolicyTest Change-Id: I6f093f3c2631970fcc2fa839e5b394106e5acc29
This commit is contained in:
@@ -3329,6 +3329,14 @@ class Task extends WindowContainer<WindowContainer> {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean handlesOrientationChangeFromDescendant() {
|
||||
return super.handlesOrientationChangeFromDescendant()
|
||||
// Display won't rotate for the orientation request if the TaskDisplayArea can't
|
||||
// specify orientation.
|
||||
&& getDisplayArea().canSpecifyOrientation();
|
||||
}
|
||||
|
||||
void resize(boolean relayout, boolean forced) {
|
||||
if (setBounds(getRequestedOverrideBounds(), forced) != BOUNDS_CHANGE_NONE && relayout) {
|
||||
getDisplayContent().layoutAndAssignWindowLayersIfNeeded();
|
||||
|
||||
@@ -1902,7 +1902,6 @@ final class TaskDisplayArea extends DisplayArea<WindowContainer> {
|
||||
}
|
||||
|
||||
/** Whether this task display area can request orientation. */
|
||||
@VisibleForTesting
|
||||
boolean canSpecifyOrientation() {
|
||||
// Only allow to specify orientation if this TDA is not set to ignore orientation request,
|
||||
// and it is the last focused one on this logical display that can request orientation
|
||||
|
||||
@@ -33,6 +33,7 @@ import static android.window.DisplayAreaOrganizer.FEATURE_VENDOR_FIRST;
|
||||
import static android.window.DisplayAreaOrganizer.FEATURE_WINDOWED_MAGNIFICATION;
|
||||
|
||||
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
|
||||
import static com.android.server.wm.SizeCompatTests.prepareLimitedBounds;
|
||||
import static com.android.server.wm.SizeCompatTests.prepareUnresizable;
|
||||
import static com.android.server.wm.SizeCompatTests.rotateDisplay;
|
||||
|
||||
@@ -309,6 +310,43 @@ public class DualDisplayAreaGroupPolicyTest extends WindowTestsBase {
|
||||
assertThat(mSecondRoot.findAreaForToken(imeToken)).isEqualTo(imeContainer);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResizableFixedOrientationApp_taskLevelLetterboxing() {
|
||||
mFirstRoot.setIgnoreOrientationRequest(false /* ignoreOrientationRequest */);
|
||||
mSecondRoot.setIgnoreOrientationRequest(false /* ignoreOrientationRequest */);
|
||||
|
||||
// Launch portrait on first DAG
|
||||
mDisplay.onLastFocusedTaskDisplayAreaChanged(mFirstTda);
|
||||
prepareLimitedBounds(mFirstActivity, SCREEN_ORIENTATION_PORTRAIT,
|
||||
false /* isUnresizable */);
|
||||
|
||||
// Display in landscape (as opposite to DAG), first DAG and activity in portrait
|
||||
assertThat(mDisplay.getLastOrientation()).isEqualTo(SCREEN_ORIENTATION_LANDSCAPE);
|
||||
assertThat(mFirstRoot.getConfiguration().orientation).isEqualTo(ORIENTATION_PORTRAIT);
|
||||
assertThat(mFirstActivity.getConfiguration().orientation).isEqualTo(ORIENTATION_PORTRAIT);
|
||||
assertThat(mFirstTask.isTaskLetterboxed()).isFalse();
|
||||
assertThat(mFirstActivity.inSizeCompatMode()).isFalse();
|
||||
|
||||
// Launch portrait on second DAG
|
||||
mDisplay.onLastFocusedTaskDisplayAreaChanged(mSecondTda);
|
||||
prepareLimitedBounds(mSecondActivity, SCREEN_ORIENTATION_LANDSCAPE,
|
||||
false /* isUnresizable */);
|
||||
|
||||
// Display in portrait (as opposite to DAG), first DAG and activity in landscape
|
||||
assertThat(mDisplay.getLastOrientation()).isEqualTo(SCREEN_ORIENTATION_PORTRAIT);
|
||||
assertThat(mSecondRoot.getConfiguration().orientation).isEqualTo(ORIENTATION_LANDSCAPE);
|
||||
assertThat(mSecondActivity.getConfiguration().orientation).isEqualTo(ORIENTATION_LANDSCAPE);
|
||||
assertThat(mSecondTask.isTaskLetterboxed()).isFalse();
|
||||
assertThat(mSecondActivity.inSizeCompatMode()).isFalse();
|
||||
|
||||
// First activity is letterboxed in portrait as requested.
|
||||
assertThat(mFirstRoot.getConfiguration().orientation).isEqualTo(ORIENTATION_LANDSCAPE);
|
||||
assertThat(mFirstActivity.getConfiguration().orientation).isEqualTo(ORIENTATION_PORTRAIT);
|
||||
assertThat(mFirstTask.isTaskLetterboxed()).isTrue();
|
||||
assertThat(mFirstActivity.inSizeCompatMode()).isFalse();
|
||||
|
||||
}
|
||||
|
||||
private void setupImeWindow() {
|
||||
final WindowState imeWindow = createWindow(null /* parent */,
|
||||
TYPE_INPUT_METHOD, mDisplay, "mImeWindow");
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package com.android.server.wm;
|
||||
|
||||
import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE;
|
||||
import static android.content.pm.ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
|
||||
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
|
||||
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
|
||||
@@ -505,7 +506,7 @@ public class SizeCompatTests extends WindowTestsBase {
|
||||
|
||||
compatTokens.clear();
|
||||
// Make the activity resizable again by restarting it
|
||||
activity.info.resizeMode = ActivityInfo.RESIZE_MODE_RESIZEABLE;
|
||||
activity.info.resizeMode = RESIZE_MODE_RESIZEABLE;
|
||||
activity.mVisibleRequested = true;
|
||||
activity.restartProcessIfVisible();
|
||||
// The full lifecycle isn't hooked up so manually set state to resumed
|
||||
@@ -522,7 +523,7 @@ public class SizeCompatTests extends WindowTestsBase {
|
||||
setUpDisplaySizeWithApp(1000, 2500);
|
||||
|
||||
// Make the task root resizable.
|
||||
mActivity.info.resizeMode = ActivityInfo.RESIZE_MODE_RESIZEABLE;
|
||||
mActivity.info.resizeMode = RESIZE_MODE_RESIZEABLE;
|
||||
|
||||
// Create a size compat activity on the same task.
|
||||
final ActivityRecord activity = new ActivityBuilder(mAtm)
|
||||
@@ -550,7 +551,7 @@ public class SizeCompatTests extends WindowTestsBase {
|
||||
setUpDisplaySizeWithApp(1000, 2500);
|
||||
|
||||
// Make the task root resizable.
|
||||
mActivity.info.resizeMode = ActivityInfo.RESIZE_MODE_RESIZEABLE;
|
||||
mActivity.info.resizeMode = RESIZE_MODE_RESIZEABLE;
|
||||
|
||||
// Create a size compat activity on the same task.
|
||||
final ActivityRecord activity = new ActivityBuilder(mAtm)
|
||||
@@ -946,13 +947,25 @@ public class SizeCompatTests extends WindowTestsBase {
|
||||
prepareUnresizable(activity, -1 /* maxAspect */, screenOrientation);
|
||||
}
|
||||
|
||||
/**
|
||||
* Setups {@link #mActivity} as a size-compat-mode-able activity with fixed aspect and/or
|
||||
* orientation.
|
||||
*/
|
||||
static void prepareUnresizable(ActivityRecord activity, float maxAspect,
|
||||
int screenOrientation) {
|
||||
activity.info.resizeMode = RESIZE_MODE_UNRESIZEABLE;
|
||||
prepareLimitedBounds(activity, maxAspect, screenOrientation, true /* isUnresizable */);
|
||||
}
|
||||
|
||||
static void prepareLimitedBounds(ActivityRecord activity, int screenOrientation,
|
||||
boolean isUnresizable) {
|
||||
prepareLimitedBounds(activity, -1 /* maxAspect */, screenOrientation, isUnresizable);
|
||||
}
|
||||
|
||||
/**
|
||||
* Setups {@link #mActivity} with restriction on its bounds, such as maxAspect, fixed
|
||||
* orientation, and/or whether it is resizable.
|
||||
*/
|
||||
static void prepareLimitedBounds(ActivityRecord activity, float maxAspect,
|
||||
int screenOrientation, boolean isUnresizable) {
|
||||
activity.info.resizeMode = isUnresizable
|
||||
? RESIZE_MODE_UNRESIZEABLE
|
||||
: RESIZE_MODE_RESIZEABLE;
|
||||
activity.mVisibleRequested = true;
|
||||
if (maxAspect >= 0) {
|
||||
activity.info.maxAspectRatio = maxAspect;
|
||||
|
||||
Reference in New Issue
Block a user