From 6d2ef5a0953ae1c275fc63a5c2a103fd5e69355f Mon Sep 17 00:00:00 2001 From: Chris Li Date: Thu, 12 Nov 2020 14:02:16 -0800 Subject: [PATCH] Only update lastFocusedTaskDisplayArea if it handles orientation request Before, when there are two DAGs, where one respects orientation request, and one doesn't, the orientation request from the former DAG may be ignored if the later DAG gets the focus. Now, when the focus changed, we should only update to the new TDA if it handles orientation change, otherwise we should still use the orientation from the previous focused TDA. Bug: 155431879 Test: manual: test with dual display where only one DAG respect request Test: atest WmTests:TaskDisplayAreaTests Test: atest WmTests:DisplayAreaTest Change-Id: I1d38980347e65b5b729acd3457035e4d4b7cd1c0 --- .../com/android/server/wm/DisplayArea.java | 7 ++++ .../com/android/server/wm/DisplayContent.java | 36 +++++++++++----- .../android/server/wm/TaskDisplayArea.java | 14 ++++--- .../server/wm/DisplayAreaGroupTest.java | 2 +- .../android/server/wm/DisplayAreaTest.java | 24 ++++++++++- .../server/wm/SystemServicesTestRule.java | 2 +- .../server/wm/TaskDisplayAreaTests.java | 42 ++++++++++++++++--- .../android/server/wm/TestDisplayContent.java | 2 +- 8 files changed, 102 insertions(+), 27 deletions(-) diff --git a/services/core/java/com/android/server/wm/DisplayArea.java b/services/core/java/com/android/server/wm/DisplayArea.java index cd3f322781659..15483cb90ce21 100644 --- a/services/core/java/com/android/server/wm/DisplayArea.java +++ b/services/core/java/com/android/server/wm/DisplayArea.java @@ -174,6 +174,13 @@ public class DisplayArea extends WindowContainer { return false; } + if (mDisplayContent.mFocusedApp != null) { + // We record the last focused TDA that respects orientation request, check if this + // change may affect it. + mDisplayContent.onLastFocusedTaskDisplayAreaChanged( + mDisplayContent.mFocusedApp.getDisplayArea()); + } + // The orientation request from this DA may now be respected. if (!ignoreOrientationRequest) { return mDisplayContent.updateOrientation(); diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index 1d2cd0a0a350c..8e434cef3ca65 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -488,8 +488,13 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp */ ActivityRecord mFocusedApp = null; - /** The last focused {@link TaskDisplayArea} on this display. */ - private TaskDisplayArea mLastFocusedTaskDisplayArea = null; + /** + * We only respect the orientation request from apps below this {@link TaskDisplayArea}. + * It is the last focused {@link TaskDisplayArea} on this display that handles orientation + * request. + */ + @Nullable + private TaskDisplayArea mOrientationRequestingTaskDisplayArea = null; /** * The launching activity which is using fixed rotation transformation. @@ -3325,7 +3330,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp // Called even if the focused app is not changed in case the app is moved to a different // TaskDisplayArea. - setLastFocusedTaskDisplayArea(newFocus.getDisplayArea()); + onLastFocusedTaskDisplayAreaChanged(newFocus.getDisplayArea()); } if (mFocusedApp == newFocus) { return false; @@ -3339,16 +3344,27 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp } /** Called when the focused {@link TaskDisplayArea} on this display may have changed. */ - @VisibleForTesting - void setLastFocusedTaskDisplayArea(@Nullable TaskDisplayArea taskDisplayArea) { - if (taskDisplayArea != null) { - mLastFocusedTaskDisplayArea = taskDisplayArea; + 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; } } - /** Gets the last focused {@link TaskDisplayArea} on this display. */ - TaskDisplayArea getLastFocusedTaskDisplayArea() { - return mLastFocusedTaskDisplayArea; + /** + * Gets the {@link TaskDisplayArea} that we respect orientation requests from apps below it. + */ + @Nullable + TaskDisplayArea getOrientationRequestingTaskDisplayArea() { + return mOrientationRequestingTaskDisplayArea; } /** Updates the layer assignment of windows on this display. */ diff --git a/services/core/java/com/android/server/wm/TaskDisplayArea.java b/services/core/java/com/android/server/wm/TaskDisplayArea.java index 4498a8c82583d..9425602763c5d 100644 --- a/services/core/java/com/android/server/wm/TaskDisplayArea.java +++ b/services/core/java/com/android/server/wm/TaskDisplayArea.java @@ -641,9 +641,7 @@ final class TaskDisplayArea extends DisplayArea { @Override int getOrientation(int candidate) { mLastOrientationSource = null; - // Only allow to specify orientation if this TDA is not set to ignore orientation request, - // and it has the focus. - if (mIgnoreOrientationRequest || !isLastFocused()) { + if (!canSpecifyOrientation()) { return SCREEN_ORIENTATION_UNSET; } @@ -1918,10 +1916,14 @@ final class TaskDisplayArea extends DisplayArea { return lastReparentedStack; } - /** Whether this task display area is the last focused one on this logical display. */ + /** Whether this task display area can request orientation. */ @VisibleForTesting - boolean isLastFocused() { - return mDisplayContent.getLastFocusedTaskDisplayArea() == this; + 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 !mIgnoreOrientationRequest + && mDisplayContent.getOrientationRequestingTaskDisplayArea() == this; } @Override diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayAreaGroupTest.java b/services/tests/wmtests/src/com/android/server/wm/DisplayAreaGroupTest.java index bc91c709aeb1d..f536cd0b0ed48 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayAreaGroupTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayAreaGroupTest.java @@ -61,7 +61,7 @@ public class DisplayAreaGroupTest extends WindowTestsBase { mTaskDisplayArea = new TaskDisplayArea( mDisplayContent, mWm, "TDA1", FEATURE_VENDOR_FIRST + 1); mDisplayAreaGroup.addChild(mTaskDisplayArea, POSITION_TOP); - mDisplayContent.setLastFocusedTaskDisplayArea(mTaskDisplayArea); + mDisplayContent.onLastFocusedTaskDisplayAreaChanged(mTaskDisplayArea); } @Test 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 025c5a6bb1807..6f5a874114eac 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayAreaTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayAreaTest.java @@ -458,8 +458,7 @@ public class DisplayAreaTest extends WindowTestsBase { @Test public void testSetIgnoreOrientationRequest_notCallSuperOnDescendantOrientationChanged() { - final TaskDisplayArea tda = - mDisplayContent.getDefaultTaskDisplayArea(); + final TaskDisplayArea tda = mDisplayContent.getDefaultTaskDisplayArea(); final Task stack = new TaskBuilder(mSupervisor).setOnTop(!ON_TOP).setCreateActivity(true).build(); final ActivityRecord activity = stack.getTopNonFinishingActivity(); @@ -478,6 +477,27 @@ public class DisplayAreaTest extends WindowTestsBase { verify(mDisplayContent).onDescendantOrientationChanged(any()); } + @Test + public void testSetIgnoreOrientationRequest_updateOrientationRequestingTaskDisplayArea() { + final TaskDisplayArea tda = mDisplayContent.getDefaultTaskDisplayArea(); + final Task stack = + new TaskBuilder(mSupervisor).setOnTop(!ON_TOP).setCreateActivity(true).build(); + final ActivityRecord activity = stack.getTopNonFinishingActivity(); + + mDisplayContent.setFocusedApp(activity); + assertThat(mDisplayContent.getOrientationRequestingTaskDisplayArea()).isEqualTo(tda); + + // TDA is no longer handling orientation request, clear the last focused TDA. + tda.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */); + + assertThat(mDisplayContent.getOrientationRequestingTaskDisplayArea()).isNull(); + + // TDA now handles orientation request, update last focused TDA based on the focused app. + tda.setIgnoreOrientationRequest(false /* ignoreOrientationRequest */); + + assertThat(mDisplayContent.getOrientationRequestingTaskDisplayArea()).isEqualTo(tda); + } + private static class TestDisplayArea extends DisplayArea { private TestDisplayArea(WindowManagerService wms, Rect bounds) { super(wms, ANY, "half display area"); diff --git a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java index 83e3d22345e1d..e1bc90a2551c7 100644 --- a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java +++ b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java @@ -325,7 +325,7 @@ public class SystemServicesTestRule implements TestRule { final TaskDisplayArea taskDisplayArea = display.getDefaultTaskDisplayArea(); // Set the default focused TDA. - display.setLastFocusedTaskDisplayArea(taskDisplayArea); + display.onLastFocusedTaskDisplayAreaChanged(taskDisplayArea); spyOn(taskDisplayArea); final Task homeStack = taskDisplayArea.getRootTask( WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME); 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 d80f816424740..1c93e0f7e185d 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TaskDisplayAreaTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/TaskDisplayAreaTests.java @@ -262,20 +262,50 @@ public class TaskDisplayAreaTests extends WindowTestsBase { // Activity on TDA1 is focused mDisplayContent.setFocusedApp(firstActivity); - assertThat(firstTaskDisplayArea.isLastFocused()).isTrue(); - assertThat(secondTaskDisplayArea.isLastFocused()).isFalse(); + assertThat(firstTaskDisplayArea.canSpecifyOrientation()).isTrue(); + assertThat(secondTaskDisplayArea.canSpecifyOrientation()).isFalse(); // No focused app, TDA1 is still recorded as last focused. mDisplayContent.setFocusedApp(null); - assertThat(firstTaskDisplayArea.isLastFocused()).isTrue(); - assertThat(secondTaskDisplayArea.isLastFocused()).isFalse(); + assertThat(firstTaskDisplayArea.canSpecifyOrientation()).isTrue(); + assertThat(secondTaskDisplayArea.canSpecifyOrientation()).isFalse(); // Activity on TDA2 is focused mDisplayContent.setFocusedApp(secondActivity); - assertThat(firstTaskDisplayArea.isLastFocused()).isFalse(); - assertThat(secondTaskDisplayArea.isLastFocused()).isTrue(); + assertThat(firstTaskDisplayArea.canSpecifyOrientation()).isFalse(); + assertThat(secondTaskDisplayArea.canSpecifyOrientation()).isTrue(); + } + + @Test + public void testIsLastFocused_onlyCountIfTaskDisplayAreaHandlesOrientationRequest() { + final TaskDisplayArea firstTaskDisplayArea = mDisplayContent.getDefaultTaskDisplayArea(); + final TaskDisplayArea secondTaskDisplayArea = createTaskDisplayArea( + mDisplayContent, mRootWindowContainer.mWmService, "TestTaskDisplayArea", + FEATURE_VENDOR_FIRST); + final Task firstStack = firstTaskDisplayArea.createRootTask( + WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, false /* onTop */); + final Task secondStack = secondTaskDisplayArea.createRootTask( + WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, false /* onTop */); + final ActivityRecord firstActivity = new ActivityBuilder(mAtm) + .setTask(firstStack).build(); + final ActivityRecord secondActivity = new ActivityBuilder(mAtm) + .setTask(secondStack).build(); + firstTaskDisplayArea.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */); + secondTaskDisplayArea.setIgnoreOrientationRequest(false /* ignoreOrientationRequest */); + + // Activity on TDA1 is focused, but TDA1 doesn't respect orientation request + mDisplayContent.setFocusedApp(firstActivity); + + assertThat(firstTaskDisplayArea.canSpecifyOrientation()).isFalse(); + assertThat(secondTaskDisplayArea.canSpecifyOrientation()).isFalse(); + + // Activity on TDA2 is focused, and TDA2 respects orientation request + mDisplayContent.setFocusedApp(secondActivity); + + assertThat(firstTaskDisplayArea.canSpecifyOrientation()).isFalse(); + assertThat(secondTaskDisplayArea.canSpecifyOrientation()).isTrue(); } @Test diff --git a/services/tests/wmtests/src/com/android/server/wm/TestDisplayContent.java b/services/tests/wmtests/src/com/android/server/wm/TestDisplayContent.java index e95efe785e8c3..59e79d728d6ff 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TestDisplayContent.java +++ b/services/tests/wmtests/src/com/android/server/wm/TestDisplayContent.java @@ -158,7 +158,7 @@ class TestDisplayContent extends DisplayContent { mService.mRootWindowContainer.addChild(newDisplay, mPosition); // Set the default focused TDA. - newDisplay.setLastFocusedTaskDisplayArea(newDisplay.getDefaultTaskDisplayArea()); + newDisplay.onLastFocusedTaskDisplayAreaChanged(newDisplay.getDefaultTaskDisplayArea()); return newDisplay; }