Merge "Respect "nosensor" and "locked" with ignoreOrientationRequest being set" into tm-qpr-dev am: 099cdc6ef7

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/20552026

Change-Id: Id3b5bf98c5aff1c1ed8c5762d8eee0b081fba523
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
TreeHugger Robot
2022-12-16 18:41:15 +00:00
committed by Automerger Merge Worker
13 changed files with 306 additions and 136 deletions

View File

@@ -3871,12 +3871,6 @@
"group": "WM_DEBUG_ORIENTATION",
"at": "com\/android\/server\/wm\/TaskDisplayArea.java"
},
"1648338379": {
"message": "Display id=%d is ignoring all orientation requests, return %d",
"level": "VERBOSE",
"group": "WM_DEBUG_ORIENTATION",
"at": "com\/android\/server\/wm\/DisplayContent.java"
},
"1653025361": {
"message": "Register task fragment organizer=%s uid=%d pid=%d",
"level": "VERBOSE",
@@ -4117,6 +4111,12 @@
"group": "WM_DEBUG_WINDOW_ORGANIZER",
"at": "com\/android\/server\/wm\/DisplayAreaPolicyBuilder.java"
},
"1877863087": {
"message": "Display id=%d is ignoring orientation request for %d, return %d",
"level": "VERBOSE",
"group": "WM_DEBUG_ORIENTATION",
"at": "com\/android\/server\/wm\/DisplayContent.java"
},
"1878927091": {
"message": "prepareSurface: No changes in animation for %s",
"level": "VERBOSE",

View File

@@ -7756,10 +7756,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
// configuration. This is important to cases where activities with incompatible
// orientations launch, or user goes back from an activity of bi-orientation to an
// activity with specified orientation.
if (getRequestedOrientation() == SCREEN_ORIENTATION_UNSET) {
return;
}
if (onDescendantOrientationChanged(this)) {
// WM Shell can show additional UI elements, e.g. a restart button for size compat mode
// so ensure that WM Shell is called when an activity becomes visible.
@@ -8329,7 +8325,8 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
// If orientation is respected when insets are applied, then stableBounds will be empty.
boolean orientationRespectedWithInsets =
orientationRespectedWithInsets(parentBounds, stableBounds);
if (handlesOrientationChangeFromDescendant() && orientationRespectedWithInsets) {
if (orientationRespectedWithInsets
&& handlesOrientationChangeFromDescendant(mOrientation)) {
// No need to letterbox because of fixed orientation. Display will handle
// fixed-orientation requests and a display rotation is enough to respect requested
// orientation with insets applied.

View File

@@ -35,6 +35,8 @@ import static com.android.server.wm.DisplayAreaProto.WINDOW_CONTAINER;
import static com.android.server.wm.WindowContainerChildProto.DISPLAY_AREA;
import android.annotation.Nullable;
import android.content.pm.ActivityInfo;
import android.content.pm.ActivityInfo.ScreenOrientation;
import android.content.res.Configuration;
import android.graphics.Rect;
import android.util.proto.ProtoOutputStream;
@@ -142,26 +144,30 @@ public class DisplayArea<T extends WindowContainer> extends WindowContainer<T> {
}
@Override
@ScreenOrientation
int getOrientation(int candidate) {
mLastOrientationSource = null;
if (getIgnoreOrientationRequest()) {
final int orientation = super.getOrientation(candidate);
if (getIgnoreOrientationRequest(orientation)) {
// In all the other case, mLastOrientationSource will be reassigned to a new value
mLastOrientationSource = null;
return SCREEN_ORIENTATION_UNSET;
}
return super.getOrientation(candidate);
return orientation;
}
@Override
boolean handlesOrientationChangeFromDescendant() {
return !getIgnoreOrientationRequest()
&& super.handlesOrientationChangeFromDescendant();
boolean handlesOrientationChangeFromDescendant(@ScreenOrientation int orientation) {
return !getIgnoreOrientationRequest(orientation)
&& super.handlesOrientationChangeFromDescendant(orientation);
}
@Override
boolean onDescendantOrientationChanged(WindowContainer requestingContainer) {
boolean onDescendantOrientationChanged(@Nullable WindowContainer requestingContainer) {
// If this is set to ignore the orientation request, we don't propagate descendant
// orientation request.
return !getIgnoreOrientationRequest()
final int orientation = requestingContainer != null
? requestingContainer.mOrientation : SCREEN_ORIENTATION_UNSET;
return !getIgnoreOrientationRequest(orientation)
&& super.onDescendantOrientationChanged(requestingContainer);
}
@@ -225,6 +231,23 @@ public class DisplayArea<T extends WindowContainer> extends WindowContainer<T> {
}
}
/**
* @return {@value true} if we need to ignore the orientation in input.
*/
// TODO(b/262366204): Rename getIgnoreOrientationRequest to shouldIgnoreOrientationRequest
boolean getIgnoreOrientationRequest(@ScreenOrientation int orientation) {
// We always respect orientation request for ActivityInfo.SCREEN_ORIENTATION_LOCKED
// ActivityInfo.SCREEN_ORIENTATION_NOSENSOR.
// Main use case why this is important is Camera apps that rely on those
// properties to ensure that they will be able to determine Camera preview
// orientation correctly
if (orientation == ActivityInfo.SCREEN_ORIENTATION_LOCKED
|| orientation == ActivityInfo.SCREEN_ORIENTATION_NOSENSOR) {
return false;
}
return getIgnoreOrientationRequest();
}
boolean getIgnoreOrientationRequest() {
// Adding an exception for when ignoreOrientationRequest is overridden at runtime for all
// DisplayArea-s. For example, this is needed for the Kids Mode since many Kids apps aren't
@@ -642,11 +665,9 @@ public class DisplayArea<T extends WindowContainer> extends WindowContainer<T> {
}
@Override
@ScreenOrientation
int getOrientation(int candidate) {
mLastOrientationSource = null;
if (getIgnoreOrientationRequest()) {
return SCREEN_ORIENTATION_UNSET;
}
// Find a window requesting orientation.
final WindowState win = getWindow(mGetOrientingWindow);

View File

@@ -1558,13 +1558,15 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
}
@Override
boolean onDescendantOrientationChanged(WindowContainer requestingContainer) {
boolean onDescendantOrientationChanged(@Nullable WindowContainer requestingContainer) {
final Configuration config = updateOrientation(
requestingContainer, false /* forceUpdate */);
// If display rotation class tells us that it doesn't consider app requested orientation,
// this display won't rotate just because of an app changes its requested orientation. Thus
// it indicates that this display chooses not to handle this request.
final boolean handled = handlesOrientationChangeFromDescendant();
final int orientation = requestingContainer != null ? requestingContainer.mOrientation
: SCREEN_ORIENTATION_UNSET;
final boolean handled = handlesOrientationChangeFromDescendant(orientation);
if (config == null) {
return handled;
}
@@ -1587,8 +1589,8 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
}
@Override
boolean handlesOrientationChangeFromDescendant() {
return !getIgnoreOrientationRequest()
boolean handlesOrientationChangeFromDescendant(@ScreenOrientation int orientation) {
return !getIgnoreOrientationRequest(orientation)
&& !getDisplayRotation().isFixedToUserRotation();
}
@@ -1689,7 +1691,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
return ROTATION_UNDEFINED;
}
if (!WindowManagerService.ENABLE_FIXED_ROTATION_TRANSFORM
|| getIgnoreOrientationRequest()) {
|| getIgnoreOrientationRequest(r.mOrientation)) {
return ROTATION_UNDEFINED;
}
if (r.mOrientation == ActivityInfo.SCREEN_ORIENTATION_BEHIND) {
@@ -2688,15 +2690,6 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
@ScreenOrientation
@Override
int getOrientation() {
mLastOrientationSource = null;
if (!handlesOrientationChangeFromDescendant()) {
// Return SCREEN_ORIENTATION_UNSPECIFIED so that Display respect sensor rotation
ProtoLog.v(WM_DEBUG_ORIENTATION,
"Display id=%d is ignoring all orientation requests, return %d",
mDisplayId, SCREEN_ORIENTATION_UNSPECIFIED);
return SCREEN_ORIENTATION_UNSPECIFIED;
}
if (mWmService.mDisplayFrozen) {
if (mWmService.mPolicy.isKeyguardLocked()) {
// Use the last orientation the while the display is frozen with the keyguard
@@ -2712,6 +2705,16 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
}
final int orientation = super.getOrientation();
if (!handlesOrientationChangeFromDescendant(orientation)) {
mLastOrientationSource = null;
// Return SCREEN_ORIENTATION_UNSPECIFIED so that Display respect sensor rotation
ProtoLog.v(WM_DEBUG_ORIENTATION,
"Display id=%d is ignoring orientation request for %d, return %d",
mDisplayId, orientation, SCREEN_ORIENTATION_UNSPECIFIED);
return SCREEN_ORIENTATION_UNSPECIFIED;
}
if (orientation == SCREEN_ORIENTATION_UNSET) {
// Return SCREEN_ORIENTATION_UNSPECIFIED so that Display respect sensor rotation
ProtoLog.v(WM_DEBUG_ORIENTATION,
@@ -3832,18 +3835,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
/** Called when the focused {@link TaskDisplayArea} on this display may have changed. */
void onLastFocusedTaskDisplayAreaChanged(@Nullable TaskDisplayArea taskDisplayArea) {
// Only record the TaskDisplayArea that handles orientation request.
if (taskDisplayArea != null && taskDisplayArea.handlesOrientationChangeFromDescendant()) {
mOrientationRequestingTaskDisplayArea = taskDisplayArea;
return;
}
// If the previous TDA no longer handles orientation request, clear it.
if (mOrientationRequestingTaskDisplayArea != null
&& !mOrientationRequestingTaskDisplayArea
.handlesOrientationChangeFromDescendant()) {
mOrientationRequestingTaskDisplayArea = null;
}
mOrientationRequestingTaskDisplayArea = taskDisplayArea;
}
/**
@@ -5053,13 +5045,10 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
}
@Override
int getOrientation(int candidate) {
if (getIgnoreOrientationRequest()) {
return SCREEN_ORIENTATION_UNSET;
}
@ScreenOrientation
int getOrientation(@ScreenOrientation int candidate) {
// IME does not participate in orientation.
return candidate;
return getIgnoreOrientationRequest(candidate) ? SCREEN_ORIENTATION_UNSET : candidate;
}
@Override

View File

@@ -143,6 +143,7 @@ import android.app.WindowConfiguration;
import android.content.ComponentName;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.ActivityInfo.ScreenOrientation;
import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
@@ -2686,8 +2687,8 @@ class Task extends TaskFragment {
}
@Override
boolean handlesOrientationChangeFromDescendant() {
if (!super.handlesOrientationChangeFromDescendant()) {
boolean handlesOrientationChangeFromDescendant(@ScreenOrientation int orientation) {
if (!super.handlesOrientationChangeFromDescendant(orientation)) {
return false;
}
@@ -2702,7 +2703,7 @@ class Task extends TaskFragment {
// Check for leaf Task.
// Display won't rotate for the orientation request if the Task/TaskDisplayArea
// can't specify orientation.
return canSpecifyOrientation() && getDisplayArea().canSpecifyOrientation();
return canSpecifyOrientation() && getDisplayArea().canSpecifyOrientation(orientation);
}
void resize(boolean relayout, boolean forced) {

View File

@@ -41,6 +41,7 @@ import android.annotation.Nullable;
import android.app.ActivityOptions;
import android.app.WindowConfiguration;
import android.content.pm.ActivityInfo;
import android.content.pm.ActivityInfo.ScreenOrientation;
import android.content.res.Configuration;
import android.graphics.Color;
import android.os.UserHandle;
@@ -633,22 +634,20 @@ final class TaskDisplayArea extends DisplayArea<WindowContainer> {
}
@Override
int getOrientation(int candidate) {
mLastOrientationSource = null;
if (getIgnoreOrientationRequest()) {
return SCREEN_ORIENTATION_UNSET;
}
if (!canSpecifyOrientation()) {
@ScreenOrientation
int getOrientation(@ScreenOrientation int candidate) {
final int orientation = super.getOrientation(candidate);
if (!canSpecifyOrientation(orientation)) {
mLastOrientationSource = null;
// We only respect orientation of the focused TDA, which can be a child of this TDA.
return reduceOnAllTaskDisplayAreas((taskDisplayArea, orientation) -> {
if (taskDisplayArea == this || orientation != SCREEN_ORIENTATION_UNSET) {
return orientation;
return reduceOnAllTaskDisplayAreas((taskDisplayArea, taskOrientation) -> {
if (taskDisplayArea == this || taskOrientation != SCREEN_ORIENTATION_UNSET) {
return taskOrientation;
}
return taskDisplayArea.getOrientation(candidate);
}, SCREEN_ORIENTATION_UNSET);
}
final int orientation = super.getOrientation(candidate);
if (orientation != SCREEN_ORIENTATION_UNSET
&& orientation != SCREEN_ORIENTATION_BEHIND) {
ProtoLog.v(WM_DEBUG_ORIENTATION,
@@ -1870,12 +1869,11 @@ final class TaskDisplayArea extends DisplayArea<WindowContainer> {
}
/** Whether this task display area can request orientation. */
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
// request.
return !getIgnoreOrientationRequest()
&& mDisplayContent.getOrientationRequestingTaskDisplayArea() == this;
boolean canSpecifyOrientation(@ScreenOrientation int orientation) {
// Only allow to specify orientation if this TDA is the last focused one on this logical
// display that can request orientation request.
return mDisplayContent.getOrientationRequestingTaskDisplayArea() == this
&& !getIgnoreOrientationRequest(orientation);
}
void clearPreferredTopFocusableRootTask() {

View File

@@ -1420,9 +1420,9 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
* @return {@code true} if it handles or will handle orientation change in the future; {@code
* false} if it won't handle the change at anytime.
*/
boolean handlesOrientationChangeFromDescendant() {
boolean handlesOrientationChangeFromDescendant(int orientation) {
final WindowContainer parent = getParent();
return parent != null && parent.handlesOrientationChangeFromDescendant();
return parent != null && parent.handlesOrientationChangeFromDescendant(orientation);
}
/**
@@ -1514,7 +1514,8 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
// portrait but the task is still in landscape. While updating from display,
// the task can be updated to portrait first so the configuration can be
// computed in a consistent environment.
&& (inMultiWindowMode() || !handlesOrientationChangeFromDescendant())) {
&& (inMultiWindowMode()
|| !handlesOrientationChangeFromDescendant(orientation))) {
// Resolve the requested orientation.
onConfigurationChanged(parent.getConfiguration());
}

View File

@@ -517,7 +517,7 @@ public class ActivityRecordTests extends WindowTestsBase {
// Mimic the behavior that display doesn't handle app's requested orientation.
final DisplayContent dc = activity.getTask().getDisplayContent();
doReturn(false).when(dc).onDescendantOrientationChanged(any());
doReturn(false).when(dc).handlesOrientationChangeFromDescendant();
doReturn(false).when(dc).handlesOrientationChangeFromDescendant(anyInt());
final int requestedOrientation;
switch (newConfig.orientation) {

View File

@@ -18,6 +18,8 @@ package com.android.server.wm;
import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LOCKED;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_NOSENSOR;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
@@ -470,28 +472,6 @@ public class DisplayAreaTest extends WindowTestsBase {
area.getOrientation(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR));
}
@Test
public void testSetIgnoreOrientationRequest() {
final DisplayArea.Tokens area = new DisplayArea.Tokens(mWm, ABOVE_TASKS, "test");
final WindowToken token = createWindowToken(TYPE_APPLICATION_OVERLAY);
spyOn(token);
doReturn(mock(DisplayContent.class)).when(token).getDisplayContent();
doNothing().when(token).setParent(any());
final WindowState win = createWindowState(token);
spyOn(win);
doNothing().when(win).setParent(any());
win.mAttrs.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
token.addChild(win, 0);
area.addChild(token);
doReturn(true).when(win).isVisible();
assertEquals(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE, area.getOrientation());
area.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
assertEquals(ActivityInfo.SCREEN_ORIENTATION_UNSET, area.getOrientation());
}
@Test
public void testSetIgnoreOrientationRequest_notCallSuperOnDescendantOrientationChanged() {
final TaskDisplayArea tda = mDisplayContent.getDefaultTaskDisplayArea();
@@ -514,7 +494,49 @@ public class DisplayAreaTest extends WindowTestsBase {
}
@Test
public void testSetIgnoreOrientationRequest_updateOrientationRequestingTaskDisplayArea() {
public void testSetIgnoreOrientationRequest_callSuperOnDescendantOrientationChangedNoSensor() {
final TaskDisplayArea tda = mDisplayContent.getDefaultTaskDisplayArea();
final Task stack =
new TaskBuilder(mSupervisor).setOnTop(!ON_TOP).setCreateActivity(true).build();
final ActivityRecord activity = stack.getTopNonFinishingActivity();
tda.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
activity.setRequestedOrientation(SCREEN_ORIENTATION_NOSENSOR);
verify(tda).onDescendantOrientationChanged(any());
verify(mDisplayContent).onDescendantOrientationChanged(any());
tda.setIgnoreOrientationRequest(false /* ignoreOrientationRequest */);
activity.setRequestedOrientation(SCREEN_ORIENTATION_NOSENSOR);
verify(tda).onDescendantOrientationChanged(any());
verify(mDisplayContent).onDescendantOrientationChanged(any());
}
@Test
public void testSetIgnoreOrientationRequest_callSuperOnDescendantOrientationChangedLocked() {
final TaskDisplayArea tda = mDisplayContent.getDefaultTaskDisplayArea();
final Task stack =
new TaskBuilder(mSupervisor).setOnTop(!ON_TOP).setCreateActivity(true).build();
final ActivityRecord activity = stack.getTopNonFinishingActivity();
tda.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
activity.setRequestedOrientation(SCREEN_ORIENTATION_LOCKED);
verify(tda).onDescendantOrientationChanged(any());
verify(mDisplayContent).onDescendantOrientationChanged(any());
tda.setIgnoreOrientationRequest(false /* ignoreOrientationRequest */);
activity.setRequestedOrientation(SCREEN_ORIENTATION_LOCKED);
verify(tda).onDescendantOrientationChanged(any());
verify(mDisplayContent).onDescendantOrientationChanged(any());
}
@Test
public void testGetOrientationRequestingTaskDisplayArea_updateOrientationTaskDisplayArea() {
final TaskDisplayArea tda = mDisplayContent.getDefaultTaskDisplayArea();
final Task stack =
new TaskBuilder(mSupervisor).setOnTop(!ON_TOP).setCreateActivity(true).build();
@@ -526,7 +548,7 @@ public class DisplayAreaTest extends WindowTestsBase {
// TDA is no longer handling orientation request, clear the last focused TDA.
tda.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
assertThat(mDisplayContent.getOrientationRequestingTaskDisplayArea()).isNull();
assertThat(mDisplayContent.getOrientationRequestingTaskDisplayArea()).isEqualTo(tda);
// TDA now handles orientation request, update last focused TDA based on the focused app.
tda.setIgnoreOrientationRequest(false /* ignoreOrientationRequest */);

View File

@@ -17,6 +17,8 @@
package com.android.server.wm;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LOCKED;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_NOSENSOR;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
@@ -162,6 +164,30 @@ public class DualDisplayAreaGroupPolicyTest extends WindowTestsBase {
verify(mDisplay, never()).onDescendantOrientationChanged(any());
}
@Test
public void testIgnoreOrientationRequest_displayReceiveOrientationChangeForNoSensor() {
mFirstRoot.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
mSecondRoot.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
mDisplay.onLastFocusedTaskDisplayAreaChanged(mFirstTda);
prepareUnresizable(mFirstActivity, SCREEN_ORIENTATION_NOSENSOR);
verify(mFirstRoot).onDescendantOrientationChanged(any());
verify(mDisplay).onDescendantOrientationChanged(any());
}
@Test
public void testIgnoreOrientationRequest_displayReceiveOrientationChangeForLocked() {
mFirstRoot.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
mSecondRoot.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
mDisplay.onLastFocusedTaskDisplayAreaChanged(mFirstTda);
prepareUnresizable(mFirstActivity, SCREEN_ORIENTATION_LOCKED);
verify(mFirstRoot).onDescendantOrientationChanged(any());
verify(mDisplay).onDescendantOrientationChanged(any());
}
@Test
public void testLaunchPortraitApp_fillsDisplayAreaGroup() {
mFirstRoot.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
@@ -214,6 +240,21 @@ public class DualDisplayAreaGroupPolicyTest extends WindowTestsBase {
newTaskBounds.height() * newTaskBounds.height() / newTaskBounds.width());
}
@Test
public void testLaunchNoSensorApp_noSizeCompatAfterRotation() {
mFirstRoot.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
mSecondRoot.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
mDisplay.onLastFocusedTaskDisplayAreaChanged(mFirstTda);
prepareUnresizable(mFirstActivity, SCREEN_ORIENTATION_NOSENSOR);
assertThat(mFirstActivity.isLetterboxedForFixedOrientationAndAspectRatio()).isFalse();
assertThat(mFirstActivity.inSizeCompatMode()).isFalse();
rotateDisplay(mDisplay, ROTATION_90);
assertThat(mFirstActivity.isLetterboxedForFixedOrientationAndAspectRatio()).isFalse();
assertThat(mFirstActivity.inSizeCompatMode()).isFalse();
}
@Test
public void testLaunchLandscapeApp_activityIsLetterboxForFixedOrientationInDisplayAreaGroup() {
mFirstRoot.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
@@ -235,6 +276,26 @@ public class DualDisplayAreaGroupPolicyTest extends WindowTestsBase {
.isEqualTo(dagBounds.width() * dagBounds.width() / dagBounds.height());
}
@Test
public void testLaunchNoSensorApp_activityIsNotLetterboxForFixedOrientationDisplayAreaGroup() {
mFirstRoot.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
mSecondRoot.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
mDisplay.onLastFocusedTaskDisplayAreaChanged(mFirstTda);
prepareUnresizable(mFirstActivity, SCREEN_ORIENTATION_NOSENSOR);
assertThat(mFirstActivity.isLetterboxedForFixedOrientationAndAspectRatio()).isFalse();
}
@Test
public void testLaunchLockedApp_activityIsNotLetterboxForFixedOrientationInDisplayAreaGroup() {
mFirstRoot.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
mSecondRoot.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
mDisplay.onLastFocusedTaskDisplayAreaChanged(mFirstTda);
prepareUnresizable(mFirstActivity, SCREEN_ORIENTATION_LOCKED);
assertThat(mFirstActivity.isLetterboxedForFixedOrientationAndAspectRatio()).isFalse();
}
@Test
public void testLaunchLandscapeApp_fixedOrientationLetterboxBecomesSizeCompatAfterRotation() {
mFirstRoot.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
@@ -264,6 +325,20 @@ public class DualDisplayAreaGroupPolicyTest extends WindowTestsBase {
assertThat(newActivityBounds.height()).isEqualTo(activityBounds.height());
}
@Test
public void testLaunchNoSensorApp_fixedOrientationLetterboxBecomesSizeCompatAfterRotation() {
mFirstRoot.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
mSecondRoot.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
mDisplay.onLastFocusedTaskDisplayAreaChanged(mFirstTda);
prepareUnresizable(mFirstActivity, SCREEN_ORIENTATION_NOSENSOR);
rotateDisplay(mDisplay, ROTATION_90);
assertThat(mFirstActivity.isLetterboxedForFixedOrientationAndAspectRatio()).isFalse();
assertThat(mFirstActivity.inSizeCompatMode()).isFalse();
}
@Test
public void testPlaceImeContainer_reparentToTargetDisplayAreaGroup() {
setupImeWindow();

View File

@@ -29,8 +29,9 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.content.Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT;
import static android.content.pm.ActivityInfo.FLAG_ALWAYS_FOCUSABLE;
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_UNSET;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LOCKED;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_NOSENSOR;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
import static android.window.DisplayAreaOrganizer.FEATURE_VENDOR_FIRST;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
@@ -422,24 +423,26 @@ public class TaskDisplayAreaTests extends WindowTestsBase {
// Activity on TDA1 is focused
mDisplayContent.setFocusedApp(firstActivity);
assertThat(firstTaskDisplayArea.canSpecifyOrientation()).isTrue();
assertThat(secondTaskDisplayArea.canSpecifyOrientation()).isFalse();
final int testOrientation = SCREEN_ORIENTATION_PORTRAIT;
assertThat(firstTaskDisplayArea.canSpecifyOrientation(testOrientation)).isTrue();
assertThat(secondTaskDisplayArea.canSpecifyOrientation(testOrientation)).isFalse();
// No focused app, TDA1 is still recorded as last focused.
mDisplayContent.setFocusedApp(null);
assertThat(firstTaskDisplayArea.canSpecifyOrientation()).isTrue();
assertThat(secondTaskDisplayArea.canSpecifyOrientation()).isFalse();
assertThat(firstTaskDisplayArea.canSpecifyOrientation(testOrientation)).isTrue();
assertThat(secondTaskDisplayArea.canSpecifyOrientation(testOrientation)).isFalse();
// Activity on TDA2 is focused
mDisplayContent.setFocusedApp(secondActivity);
assertThat(firstTaskDisplayArea.canSpecifyOrientation()).isFalse();
assertThat(secondTaskDisplayArea.canSpecifyOrientation()).isTrue();
assertThat(firstTaskDisplayArea.canSpecifyOrientation(testOrientation)).isFalse();
assertThat(secondTaskDisplayArea.canSpecifyOrientation(testOrientation)).isTrue();
}
@Test
public void testIsLastFocused_onlyCountIfTaskDisplayAreaHandlesOrientationRequest() {
public void testCanSpecifyOrientation() {
final TaskDisplayArea firstTaskDisplayArea = mDisplayContent.getDefaultTaskDisplayArea();
final TaskDisplayArea secondTaskDisplayArea = createTaskDisplayArea(
mDisplayContent, mRootWindowContainer.mWmService, "TestTaskDisplayArea",
@@ -455,34 +458,88 @@ public class TaskDisplayAreaTests extends WindowTestsBase {
firstTaskDisplayArea.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
secondTaskDisplayArea.setIgnoreOrientationRequest(false /* ignoreOrientationRequest */);
// Activity on TDA1 is focused, but TDA1 doesn't respect orientation request
final int testOrientation = SCREEN_ORIENTATION_PORTRAIT;
// Activity on TDA1 is focused, but TDA1 cannot specify orientation because
// ignoreOrientationRequest is true
// Activity on TDA2 has ignoreOrientationRequest false but it doesn't have focus so it
// cannot specify orientation
mDisplayContent.setFocusedApp(firstActivity);
assertThat(firstTaskDisplayArea.canSpecifyOrientation()).isFalse();
assertThat(secondTaskDisplayArea.canSpecifyOrientation()).isFalse();
assertThat(firstTaskDisplayArea.canSpecifyOrientation(testOrientation)).isFalse();
assertThat(secondTaskDisplayArea.canSpecifyOrientation(testOrientation)).isFalse();
// Activity on TDA2 is focused, and TDA2 respects orientation request
// Activity on TDA1 is not focused, and so it cannot specify orientation
// Activity on TDA2 is focused, and it can specify orientation because
// ignoreOrientationRequest is false
mDisplayContent.setFocusedApp(secondActivity);
assertThat(firstTaskDisplayArea.canSpecifyOrientation()).isFalse();
assertThat(secondTaskDisplayArea.canSpecifyOrientation()).isTrue();
assertThat(firstTaskDisplayArea.canSpecifyOrientation(testOrientation)).isFalse();
assertThat(secondTaskDisplayArea.canSpecifyOrientation(testOrientation)).isTrue();
}
@Test
public void testIgnoreOrientationRequest() {
final TaskDisplayArea taskDisplayArea = mDisplayContent.getDefaultTaskDisplayArea();
final Task task = taskDisplayArea.createRootTask(
public void testCanSpecifyOrientationNoSensor() {
final TaskDisplayArea firstTaskDisplayArea = mDisplayContent.getDefaultTaskDisplayArea();
final TaskDisplayArea secondTaskDisplayArea = createTaskDisplayArea(
mDisplayContent, mRootWindowContainer.mWmService, "TestTaskDisplayArea",
FEATURE_VENDOR_FIRST);
final Task firstRootTask = firstTaskDisplayArea.createRootTask(
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, false /* onTop */);
final ActivityRecord activity = new ActivityBuilder(mAtm).setTask(task).build();
final Task secondRootTask = secondTaskDisplayArea.createRootTask(
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, false /* onTop */);
final ActivityRecord firstActivity = new ActivityBuilder(mAtm)
.setTask(firstRootTask).build();
final ActivityRecord secondActivity = new ActivityBuilder(mAtm)
.setTask(secondRootTask).build();
firstTaskDisplayArea.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
secondTaskDisplayArea.setIgnoreOrientationRequest(false /* ignoreOrientationRequest */);
mDisplayContent.setFocusedApp(activity);
activity.setRequestedOrientation(SCREEN_ORIENTATION_LANDSCAPE);
final int testOrientation = SCREEN_ORIENTATION_NOSENSOR;
assertThat(taskDisplayArea.getOrientation()).isEqualTo(SCREEN_ORIENTATION_LANDSCAPE);
// ignoreOrientationRequest is always false for SCREEN_ORIENTATION_NOSENSOR so
// only the TDAs with focus can specify orientations
mDisplayContent.setFocusedApp(firstActivity);
taskDisplayArea.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
assertThat(firstTaskDisplayArea.canSpecifyOrientation(testOrientation)).isTrue();
assertThat(secondTaskDisplayArea.canSpecifyOrientation(testOrientation)).isFalse();
assertThat(taskDisplayArea.getOrientation()).isEqualTo(SCREEN_ORIENTATION_UNSET);
mDisplayContent.setFocusedApp(secondActivity);
assertThat(firstTaskDisplayArea.canSpecifyOrientation(testOrientation)).isFalse();
assertThat(secondTaskDisplayArea.canSpecifyOrientation(testOrientation)).isTrue();
}
@Test
public void testCanSpecifyOrientationLocked() {
final TaskDisplayArea firstTaskDisplayArea = mDisplayContent.getDefaultTaskDisplayArea();
final TaskDisplayArea secondTaskDisplayArea = createTaskDisplayArea(
mDisplayContent, mRootWindowContainer.mWmService, "TestTaskDisplayArea",
FEATURE_VENDOR_FIRST);
final Task firstRootTask = firstTaskDisplayArea.createRootTask(
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, false /* onTop */);
final Task secondRootTask = secondTaskDisplayArea.createRootTask(
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, false /* onTop */);
final ActivityRecord firstActivity = new ActivityBuilder(mAtm)
.setTask(firstRootTask).build();
final ActivityRecord secondActivity = new ActivityBuilder(mAtm)
.setTask(secondRootTask).build();
firstTaskDisplayArea.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
secondTaskDisplayArea.setIgnoreOrientationRequest(false /* ignoreOrientationRequest */);
final int testOrientation = SCREEN_ORIENTATION_LOCKED;
// ignoreOrientationRequest is always false for SCREEN_ORIENTATION_NOSENSOR so
// only the TDAs with focus can specify orientations
mDisplayContent.setFocusedApp(firstActivity);
assertThat(firstTaskDisplayArea.canSpecifyOrientation(testOrientation)).isTrue();
assertThat(secondTaskDisplayArea.canSpecifyOrientation(testOrientation)).isFalse();
mDisplayContent.setFocusedApp(secondActivity);
assertThat(firstTaskDisplayArea.canSpecifyOrientation(testOrientation)).isFalse();
assertThat(secondTaskDisplayArea.canSpecifyOrientation(testOrientation)).isTrue();
}
@Test

View File

@@ -57,6 +57,7 @@ import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.same;
@@ -392,12 +393,16 @@ public class TaskTests extends WindowTestsBase {
leafTask1.getWindowConfiguration().setActivityType(ACTIVITY_TYPE_HOME);
leafTask2.getWindowConfiguration().setActivityType(ACTIVITY_TYPE_STANDARD);
// We need to use an orientation that is not an exception for the
// ignoreOrientationRequest flag.
final int orientation = SCREEN_ORIENTATION_PORTRAIT;
assertEquals(leafTask2, rootTask.getTopChild());
assertTrue(rootTask.handlesOrientationChangeFromDescendant());
assertTrue(rootTask.handlesOrientationChangeFromDescendant(orientation));
// Treat orientation request from home as handled.
assertTrue(leafTask1.handlesOrientationChangeFromDescendant());
assertTrue(leafTask1.handlesOrientationChangeFromDescendant(orientation));
// Orientation request from standard activity in multi window will not be handled.
assertFalse(leafTask2.handlesOrientationChangeFromDescendant());
assertFalse(leafTask2.handlesOrientationChangeFromDescendant(orientation));
}
@Test
@@ -636,7 +641,8 @@ public class TaskTests extends WindowTestsBase {
doReturn(parentWindowContainer).when(task).getParent();
doReturn(display.getDefaultTaskDisplayArea()).when(task).getDisplayArea();
doReturn(rootTask).when(task).getRootTask();
doReturn(true).when(parentWindowContainer).handlesOrientationChangeFromDescendant();
doReturn(true).when(parentWindowContainer)
.handlesOrientationChangeFromDescendant(anyInt());
// Setting app to fixed portrait fits within parent, but Task shouldn't adjust the
// bounds because its parent says it will handle it at a later time.

View File

@@ -662,13 +662,13 @@ public class WindowContainerTests extends WindowTestsBase {
public void testSetOrientation() {
final TestWindowContainer root = spy(new TestWindowContainerBuilder(mWm).build());
final TestWindowContainer child = spy(root.addChildWindow());
doReturn(true).when(root).handlesOrientationChangeFromDescendant();
doReturn(true).when(root).handlesOrientationChangeFromDescendant(anyInt());
child.getWindowConfiguration().setWindowingMode(WINDOWING_MODE_FULLSCREEN);
child.setOrientation(SCREEN_ORIENTATION_PORTRAIT);
// The ancestor should decide whether to dispatch the configuration change.
verify(child, never()).onConfigurationChanged(any());
doReturn(false).when(root).handlesOrientationChangeFromDescendant();
doReturn(false).when(root).handlesOrientationChangeFromDescendant(anyInt());
child.setOrientation(SCREEN_ORIENTATION_LANDSCAPE);
// The ancestor doesn't handle the request so the descendant applies the change directly.
verify(child).onConfigurationChanged(any());
@@ -843,11 +843,14 @@ public class WindowContainerTests extends WindowTestsBase {
final TestWindowContainerBuilder builder = new TestWindowContainerBuilder(mWm);
final TestWindowContainer root = spy(builder.build());
final TestWindowContainer child = root.addChildWindow();
assertFalse(child.handlesOrientationChangeFromDescendant());
// We use an orientation that is not an exception for the ignoreOrientationRequest flag
final int orientation = SCREEN_ORIENTATION_PORTRAIT;
Mockito.doReturn(true).when(root).handlesOrientationChangeFromDescendant();
assertTrue(child.handlesOrientationChangeFromDescendant());
final TestWindowContainer child = root.addChildWindow();
assertFalse(child.handlesOrientationChangeFromDescendant(orientation));
Mockito.doReturn(true).when(root).handlesOrientationChangeFromDescendant(anyInt());
assertTrue(child.handlesOrientationChangeFromDescendant(orientation));
}
@Test