Merge "Handle orientation behind for fixed rotation" into tm-qpr-dev

This commit is contained in:
Riddle Hsu
2022-04-20 08:05:58 +00:00
committed by Android (Google) Code Review
2 changed files with 45 additions and 8 deletions

View File

@@ -1575,8 +1575,10 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
mAtmService.getTaskChangeNotificationController()
.notifyTaskRequestedOrientationChanged(task.mTaskId, orientation);
}
// Currently there is no use case from non-activity.
if (handleTopActivityLaunchingInDifferentOrientation(r, true /* checkOpening */)) {
// The orientation source may not be the top if it uses SCREEN_ORIENTATION_BEHIND.
final ActivityRecord topCandidate = !r.mVisibleRequested ? topRunningActivity() : r;
if (handleTopActivityLaunchingInDifferentOrientation(
topCandidate, r, true /* checkOpening */)) {
// Display orientation should be deferred until the top fixed rotation is finished.
return false;
}
@@ -1593,7 +1595,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
/**
* Returns a valid rotation if the activity can use different orientation than the display.
* Otherwise {@link #ROTATION_UNDEFINED}.
* Otherwise {@link android.app.WindowConfiguration#ROTATION_UNDEFINED}.
*/
@Rotation
int rotationForActivityInDifferentOrientation(@NonNull ActivityRecord r) {
@@ -1603,6 +1605,15 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
if (!WindowManagerService.ENABLE_FIXED_ROTATION_TRANSFORM) {
return ROTATION_UNDEFINED;
}
if (r.mOrientation == ActivityInfo.SCREEN_ORIENTATION_BEHIND) {
final ActivityRecord nextCandidate = getActivity(
a -> a.mOrientation != SCREEN_ORIENTATION_UNSET
&& a.mOrientation != ActivityInfo.SCREEN_ORIENTATION_BEHIND,
r, false /* includeBoundary */, true /* traverseTopToBottom */);
if (nextCandidate != null) {
r = nextCandidate;
}
}
if (r.inMultiWindowMode() || r.getRequestedConfigurationOrientation(true /* forDisplay */)
== getConfiguration().orientation) {
return ROTATION_UNDEFINED;
@@ -1616,18 +1627,25 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
return rotation;
}
boolean handleTopActivityLaunchingInDifferentOrientation(@NonNull ActivityRecord r,
boolean checkOpening) {
return handleTopActivityLaunchingInDifferentOrientation(r, r, checkOpening);
}
/**
* We need to keep display rotation fixed for a while when the activity in different orientation
* is launching until the launch animation is done to avoid showing the previous activity
* inadvertently in a wrong orientation.
*
* @param r The launching activity which may change display orientation.
* @param orientationSrc It may be different from {@param r} if the launching activity uses
* "behind" orientation.
* @param checkOpening Whether to check if the activity is animating by transition. Set to
* {@code true} if the caller is not sure whether the activity is launching.
* @return {@code true} if the fixed rotation is started.
*/
boolean handleTopActivityLaunchingInDifferentOrientation(@NonNull ActivityRecord r,
boolean checkOpening) {
private boolean handleTopActivityLaunchingInDifferentOrientation(@NonNull ActivityRecord r,
@NonNull ActivityRecord orientationSrc, boolean checkOpening) {
if (!WindowManagerService.ENABLE_FIXED_ROTATION_TRANSFORM) {
return false;
}
@@ -1676,7 +1694,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
// animation is not running (it may be swiping to home).
return false;
}
final int rotation = rotationForActivityInDifferentOrientation(r);
final int rotation = rotationForActivityInDifferentOrientation(orientationSrc);
if (rotation == ROTATION_UNDEFINED) {
// The display rotation won't be changed by current top activity. The client side
// adjustments of previous rotated activity should be cleared earlier. Otherwise if

View File

@@ -22,6 +22,7 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.content.pm.ActivityInfo.FLAG_SHOW_WHEN_LOCKED;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
@@ -1092,6 +1093,25 @@ public class DisplayContentTests extends WindowTestsBase {
assertEquals(ROTATION_180, dc.getRotation());
}
@Test
public void testOrientationBehind() {
final ActivityRecord prev = new ActivityBuilder(mAtm).setCreateTask(true)
.setScreenOrientation(getRotatedOrientation(mDisplayContent)).build();
prev.mVisibleRequested = false;
final ActivityRecord top = new ActivityBuilder(mAtm).setCreateTask(true)
.setScreenOrientation(SCREEN_ORIENTATION_BEHIND).build();
assertNotEquals(WindowConfiguration.ROTATION_UNDEFINED,
mDisplayContent.rotationForActivityInDifferentOrientation(top));
mDisplayContent.requestTransitionAndLegacyPrepare(WindowManager.TRANSIT_OPEN, 0);
top.setVisibility(true);
mDisplayContent.updateOrientation();
// The top uses "behind", so the orientation is decided by the previous.
assertEquals(prev, mDisplayContent.getLastOrientationSource());
// The top will use the rotation from "prev" with fixed rotation.
assertTrue(top.hasFixedRotationTransform());
}
@Test
public void testFixedToUserRotationChanged() {
final DisplayContent dc = createNewDisplay();
@@ -1650,8 +1670,7 @@ public class DisplayContentTests extends WindowTestsBase {
// The condition should reject using fixed rotation because the resumed client in real case
// might get display info immediately. And the fixed rotation adjustments haven't arrived
// client side so the info may be inconsistent with the requested orientation.
verify(mDisplayContent).handleTopActivityLaunchingInDifferentOrientation(eq(app),
eq(true) /* checkOpening */);
verify(mDisplayContent).updateOrientation(eq(app), anyBoolean());
assertFalse(app.isFixedRotationTransforming());
assertFalse(mDisplayContent.hasTopFixedRotationLaunchingApp());
}