diff options
13 files changed, 304 insertions, 134 deletions
diff --git a/data/etc/services.core.protolog.json b/data/etc/services.core.protolog.json index a4a38c713a66..86c8097ee674 100644 --- a/data/etc/services.core.protolog.json +++ b/data/etc/services.core.protolog.json @@ -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", diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index e639866a6bab..418e1edca05b 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -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. diff --git a/services/core/java/com/android/server/wm/DisplayArea.java b/services/core/java/com/android/server/wm/DisplayArea.java index 3ac135076a97..71fef057d1d2 100644 --- a/services/core/java/com/android/server/wm/DisplayArea.java +++ b/services/core/java/com/android/server/wm/DisplayArea.java @@ -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); diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index 5d502f5420ca..4c499861cb9a 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -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 diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java index 69ed7a15af27..a55ea91ff196 100644 --- a/services/core/java/com/android/server/wm/Task.java +++ b/services/core/java/com/android/server/wm/Task.java @@ -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) { diff --git a/services/core/java/com/android/server/wm/TaskDisplayArea.java b/services/core/java/com/android/server/wm/TaskDisplayArea.java index e0ed356fbe59..8ad76a3eb327 100644 --- a/services/core/java/com/android/server/wm/TaskDisplayArea.java +++ b/services/core/java/com/android/server/wm/TaskDisplayArea.java @@ -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() { diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java index 2f81f93ba2ab..cb5a4338c567 100644 --- a/services/core/java/com/android/server/wm/WindowContainer.java +++ b/services/core/java/com/android/server/wm/WindowContainer.java @@ -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()); } diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java index 17ec19d3e617..a017bd6a9436 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java @@ -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) { diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayAreaTest.java b/services/tests/wmtests/src/com/android/server/wm/DisplayAreaTest.java index b87c5a364c82..10540dc5a9ee 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayAreaTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayAreaTest.java @@ -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; @@ -471,29 +473,28 @@ public class DisplayAreaTest extends WindowTestsBase { } @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(); + public void testSetIgnoreOrientationRequest_notCallSuperOnDescendantOrientationChanged() { + final TaskDisplayArea tda = mDisplayContent.getDefaultTaskDisplayArea(); + final Task stack = + new TaskBuilder(mSupervisor).setOnTop(!ON_TOP).setCreateActivity(true).build(); + final ActivityRecord activity = stack.getTopNonFinishingActivity(); - assertEquals(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE, area.getOrientation()); + tda.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */); - area.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */); + activity.setRequestedOrientation(SCREEN_ORIENTATION_LANDSCAPE); - assertEquals(ActivityInfo.SCREEN_ORIENTATION_UNSET, area.getOrientation()); + verify(tda).onDescendantOrientationChanged(any()); + verify(mDisplayContent, never()).onDescendantOrientationChanged(any()); + + tda.setIgnoreOrientationRequest(false /* ignoreOrientationRequest */); + activity.setRequestedOrientation(SCREEN_ORIENTATION_PORTRAIT); + + verify(tda, times(2)).onDescendantOrientationChanged(any()); + verify(mDisplayContent).onDescendantOrientationChanged(any()); } @Test - public void testSetIgnoreOrientationRequest_notCallSuperOnDescendantOrientationChanged() { + public void testSetIgnoreOrientationRequest_callSuperOnDescendantOrientationChangedNoSensor() { final TaskDisplayArea tda = mDisplayContent.getDefaultTaskDisplayArea(); final Task stack = new TaskBuilder(mSupervisor).setOnTop(!ON_TOP).setCreateActivity(true).build(); @@ -501,20 +502,41 @@ public class DisplayAreaTest extends WindowTestsBase { tda.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */); - activity.setRequestedOrientation(SCREEN_ORIENTATION_LANDSCAPE); + activity.setRequestedOrientation(SCREEN_ORIENTATION_NOSENSOR); verify(tda).onDescendantOrientationChanged(any()); - verify(mDisplayContent, never()).onDescendantOrientationChanged(any()); + verify(mDisplayContent).onDescendantOrientationChanged(any()); tda.setIgnoreOrientationRequest(false /* ignoreOrientationRequest */); - activity.setRequestedOrientation(SCREEN_ORIENTATION_PORTRAIT); + activity.setRequestedOrientation(SCREEN_ORIENTATION_NOSENSOR); - verify(tda, times(2)).onDescendantOrientationChanged(any()); + 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 testSetIgnoreOrientationRequest_updateOrientationRequestingTaskDisplayArea() { + 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 */); diff --git a/services/tests/wmtests/src/com/android/server/wm/DualDisplayAreaGroupPolicyTest.java b/services/tests/wmtests/src/com/android/server/wm/DualDisplayAreaGroupPolicyTest.java index 3ab4495bd7ca..232b9b2897cc 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DualDisplayAreaGroupPolicyTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/DualDisplayAreaGroupPolicyTest.java @@ -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; @@ -163,6 +165,30 @@ public class DualDisplayAreaGroupPolicyTest extends WindowTestsBase { } @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 */); mSecondRoot.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */); @@ -215,6 +241,21 @@ public class DualDisplayAreaGroupPolicyTest extends WindowTestsBase { } @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 */); mSecondRoot.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */); @@ -236,6 +277,26 @@ public class DualDisplayAreaGroupPolicyTest extends WindowTestsBase { } @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 */); mSecondRoot.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */); @@ -265,6 +326,20 @@ public class DualDisplayAreaGroupPolicyTest extends WindowTestsBase { } @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(); final DisplayArea.Tokens imeContainer = mDisplay.getImeContainer(); diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskDisplayAreaTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskDisplayAreaTests.java index e660db57fb69..582ddf21d7f9 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TaskDisplayAreaTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/TaskDisplayAreaTests.java @@ -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,63 @@ 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 testCanSpecifyOrientation() { + 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_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(testOrientation)).isFalse(); + assertThat(secondTaskDisplayArea.canSpecifyOrientation(testOrientation)).isFalse(); + + // 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(testOrientation)).isFalse(); + assertThat(secondTaskDisplayArea.canSpecifyOrientation(testOrientation)).isTrue(); } @Test - public void testIsLastFocused_onlyCountIfTaskDisplayAreaHandlesOrientationRequest() { + public void testCanSpecifyOrientationNoSensor() { final TaskDisplayArea firstTaskDisplayArea = mDisplayContent.getDefaultTaskDisplayArea(); final TaskDisplayArea secondTaskDisplayArea = createTaskDisplayArea( mDisplayContent, mRootWindowContainer.mWmService, "TestTaskDisplayArea", @@ -455,34 +495,51 @@ 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_NOSENSOR; + + // ignoreOrientationRequest is always false for SCREEN_ORIENTATION_NOSENSOR so + // only the TDAs with focus can specify orientations mDisplayContent.setFocusedApp(firstActivity); - assertThat(firstTaskDisplayArea.canSpecifyOrientation()).isFalse(); - assertThat(secondTaskDisplayArea.canSpecifyOrientation()).isFalse(); + assertThat(firstTaskDisplayArea.canSpecifyOrientation(testOrientation)).isTrue(); + assertThat(secondTaskDisplayArea.canSpecifyOrientation(testOrientation)).isFalse(); - // Activity on TDA2 is focused, and TDA2 respects orientation request 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 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 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_LOCKED; - 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(); + + mDisplayContent.setFocusedApp(secondActivity); - assertThat(taskDisplayArea.getOrientation()).isEqualTo(SCREEN_ORIENTATION_UNSET); + assertThat(firstTaskDisplayArea.canSpecifyOrientation(testOrientation)).isFalse(); + assertThat(secondTaskDisplayArea.canSpecifyOrientation(testOrientation)).isTrue(); } @Test diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskTests.java index 0c8e89a8d010..eac67770cf36 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TaskTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/TaskTests.java @@ -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. diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java index ef3ddb7b1302..ed7d12384662 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java @@ -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()); + // We use an orientation that is not an exception for the ignoreOrientationRequest flag + final int orientation = SCREEN_ORIENTATION_PORTRAIT; + final TestWindowContainer child = root.addChildWindow(); - assertFalse(child.handlesOrientationChangeFromDescendant()); + assertFalse(child.handlesOrientationChangeFromDescendant(orientation)); - Mockito.doReturn(true).when(root).handlesOrientationChangeFromDescendant(); - assertTrue(child.handlesOrientationChangeFromDescendant()); + Mockito.doReturn(true).when(root).handlesOrientationChangeFromDescendant(anyInt()); + assertTrue(child.handlesOrientationChangeFromDescendant(orientation)); } @Test |