Remember and revert camera compat orientation change when camera closes

Also, revert rotation after the top activity stops being SCREEN_ORIENTATION_NOSENSOR and add a RotationReversionController to manage the reversion behaviour for camera compat, NOSENSOR and half-fold transitions.

Bug: 264186382
Bug: 267751289
Test: tested locally
Test: atest WmTests:DisplayRotationCompatPolicyTests
Test: atest WmTests:DisplayContentTests
Change-Id: I0033a5de7c4a7b886b241088577c32715ecccc57
This commit is contained in:
Mariia Sandrikova
2023-04-04 23:06:47 +00:00
parent d9f955a5cc
commit c53fa6bad1
8 changed files with 326 additions and 6 deletions

View File

@@ -469,6 +469,18 @@
"group": "WM_DEBUG_TASKS", "group": "WM_DEBUG_TASKS",
"at": "com\/android\/server\/wm\/RecentTasks.java" "at": "com\/android\/server\/wm\/RecentTasks.java"
}, },
"-1643780158": {
"message": "Saving original orientation before camera compat, last orientation is %d",
"level": "VERBOSE",
"group": "WM_DEBUG_ORIENTATION",
"at": "com\/android\/server\/wm\/DisplayRotationCompatPolicy.java"
},
"-1639406696": {
"message": "NOSENSOR override detected",
"level": "VERBOSE",
"group": "WM_DEBUG_ORIENTATION",
"at": "com\/android\/server\/wm\/DisplayRotationReversionController.java"
},
"-1638958146": { "-1638958146": {
"message": "Removing activity %s from task=%s adding to task=%s Callers=%s", "message": "Removing activity %s from task=%s adding to task=%s Callers=%s",
"level": "INFO", "level": "INFO",
@@ -751,6 +763,12 @@
"group": "WM_DEBUG_IME", "group": "WM_DEBUG_IME",
"at": "com\/android\/server\/wm\/ImeInsetsSourceProvider.java" "at": "com\/android\/server\/wm\/ImeInsetsSourceProvider.java"
}, },
"-1397175017": {
"message": "Other orientation overrides are in place: not reverting",
"level": "VERBOSE",
"group": "WM_DEBUG_ORIENTATION",
"at": "com\/android\/server\/wm\/DisplayRotationReversionController.java"
},
"-1394745488": { "-1394745488": {
"message": "ControlAdapter onAnimationCancelled mSource: %s mControlTarget: %s", "message": "ControlAdapter onAnimationCancelled mSource: %s mControlTarget: %s",
"level": "INFO", "level": "INFO",
@@ -1669,6 +1687,12 @@
"group": "WM_DEBUG_WINDOW_TRANSITIONS", "group": "WM_DEBUG_WINDOW_TRANSITIONS",
"at": "com\/android\/server\/wm\/Transition.java" "at": "com\/android\/server\/wm\/Transition.java"
}, },
"-529187878": {
"message": "Reverting orientation after camera compat force rotation",
"level": "VERBOSE",
"group": "WM_DEBUG_ORIENTATION",
"at": "com\/android\/server\/wm\/DisplayRotationCompatPolicy.java"
},
"-521613870": { "-521613870": {
"message": "App died during pause, not stopping: %s", "message": "App died during pause, not stopping: %s",
"level": "VERBOSE", "level": "VERBOSE",
@@ -2365,6 +2389,12 @@
"group": "WM_DEBUG_FOCUS_LIGHT", "group": "WM_DEBUG_FOCUS_LIGHT",
"at": "com\/android\/server\/wm\/WindowManagerService.java" "at": "com\/android\/server\/wm\/WindowManagerService.java"
}, },
"138097009": {
"message": "NOSENSOR override is absent: reverting",
"level": "VERBOSE",
"group": "WM_DEBUG_ORIENTATION",
"at": "com\/android\/server\/wm\/DisplayRotationReversionController.java"
},
"140319294": { "140319294": {
"message": "IME target changed within ActivityRecord", "message": "IME target changed within ActivityRecord",
"level": "DEBUG", "level": "DEBUG",

View File

@@ -746,6 +746,8 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
*/ */
DisplayWindowPolicyControllerHelper mDwpcHelper; DisplayWindowPolicyControllerHelper mDwpcHelper;
private final DisplayRotationReversionController mRotationReversionController;
private final Consumer<WindowState> mUpdateWindowsForAnimator = w -> { private final Consumer<WindowState> mUpdateWindowsForAnimator = w -> {
WindowStateAnimator winAnimator = w.mWinAnimator; WindowStateAnimator winAnimator = w.mWinAnimator;
final ActivityRecord activity = w.mActivityRecord; final ActivityRecord activity = w.mActivityRecord;
@@ -1170,6 +1172,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
mWmService.mLetterboxConfiguration.isCameraCompatTreatmentEnabled( mWmService.mLetterboxConfiguration.isCameraCompatTreatmentEnabled(
/* checkDeviceConfig */ false) /* checkDeviceConfig */ false)
? new DisplayRotationCompatPolicy(this) : null; ? new DisplayRotationCompatPolicy(this) : null;
mRotationReversionController = new DisplayRotationReversionController(this);
mInputMonitor = new InputMonitor(mWmService, this); mInputMonitor = new InputMonitor(mWmService, this);
mInsetsPolicy = new InsetsPolicy(mInsetsStateController, this); mInsetsPolicy = new InsetsPolicy(mInsetsStateController, this);
@@ -1283,6 +1286,10 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
.show(mOverlayLayer); .show(mOverlayLayer);
} }
DisplayRotationReversionController getRotationReversionController() {
return mRotationReversionController;
}
boolean isReady() { boolean isReady() {
// The display is ready when the system and the individual display are both ready. // The display is ready when the system and the individual display are both ready.
return mWmService.mDisplayReady && mDisplayReady; return mWmService.mDisplayReady && mDisplayReady;
@@ -1665,9 +1672,14 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
} }
private boolean updateOrientation(boolean forceUpdate) { private boolean updateOrientation(boolean forceUpdate) {
final WindowContainer prevOrientationSource = mLastOrientationSource;
final int orientation = getOrientation(); final int orientation = getOrientation();
// The last orientation source is valid only after getOrientation. // The last orientation source is valid only after getOrientation.
final WindowContainer orientationSource = getLastOrientationSource(); final WindowContainer orientationSource = getLastOrientationSource();
if (orientationSource != prevOrientationSource
&& mRotationReversionController.isRotationReversionEnabled()) {
mRotationReversionController.updateForNoSensorOverride();
}
final ActivityRecord r = final ActivityRecord r =
orientationSource != null ? orientationSource.asActivityRecord() : null; orientationSource != null ? orientationSource.asActivityRecord() : null;
if (r != null) { if (r != null) {

View File

@@ -34,6 +34,9 @@ import static com.android.server.wm.DisplayRotationProto.IS_FIXED_TO_USER_ROTATI
import static com.android.server.wm.DisplayRotationProto.LAST_ORIENTATION; import static com.android.server.wm.DisplayRotationProto.LAST_ORIENTATION;
import static com.android.server.wm.DisplayRotationProto.ROTATION; import static com.android.server.wm.DisplayRotationProto.ROTATION;
import static com.android.server.wm.DisplayRotationProto.USER_ROTATION; import static com.android.server.wm.DisplayRotationProto.USER_ROTATION;
import static com.android.server.wm.DisplayRotationReversionController.REVERSION_TYPE_CAMERA_COMPAT;
import static com.android.server.wm.DisplayRotationReversionController.REVERSION_TYPE_HALF_FOLD;
import static com.android.server.wm.DisplayRotationReversionController.REVERSION_TYPE_NOSENSOR;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
import static com.android.server.wm.WindowManagerService.WINDOWS_FREEZING_SCREENS_ACTIVE; import static com.android.server.wm.WindowManagerService.WINDOWS_FREEZING_SCREENS_ACTIVE;
@@ -106,6 +109,9 @@ public class DisplayRotation {
int mExit; int mExit;
} }
@Nullable
final FoldController mFoldController;
private final WindowManagerService mService; private final WindowManagerService mService;
private final DisplayContent mDisplayContent; private final DisplayContent mDisplayContent;
private final DisplayPolicy mDisplayPolicy; private final DisplayPolicy mDisplayPolicy;
@@ -127,8 +133,6 @@ public class DisplayRotation {
private OrientationListener mOrientationListener; private OrientationListener mOrientationListener;
private StatusBarManagerInternal mStatusBarManagerInternal; private StatusBarManagerInternal mStatusBarManagerInternal;
private SettingsObserver mSettingsObserver; private SettingsObserver mSettingsObserver;
@Nullable
private FoldController mFoldController;
@NonNull @NonNull
private final DeviceStateController mDeviceStateController; private final DeviceStateController mDeviceStateController;
@@ -279,7 +283,11 @@ public class DisplayRotation {
if (mSupportAutoRotation && mContext.getResources().getBoolean( if (mSupportAutoRotation && mContext.getResources().getBoolean(
R.bool.config_windowManagerHalfFoldAutoRotateOverride)) { R.bool.config_windowManagerHalfFoldAutoRotateOverride)) {
mFoldController = new FoldController(); mFoldController = new FoldController();
} else {
mFoldController = null;
} }
} else {
mFoldController = null;
} }
} }
@@ -337,6 +345,11 @@ public class DisplayRotation {
return -1; return -1;
} }
@VisibleForTesting
boolean useDefaultSettingsProvider() {
return isDefaultDisplay;
}
/** /**
* Updates the configuration which may have different values depending on current user, e.g. * Updates the configuration which may have different values depending on current user, e.g.
* runtime resource overlay. * runtime resource overlay.
@@ -870,7 +883,7 @@ public class DisplayRotation {
@VisibleForTesting @VisibleForTesting
void setUserRotation(int userRotationMode, int userRotation) { void setUserRotation(int userRotationMode, int userRotation) {
mRotationChoiceShownToUserForConfirmation = ROTATION_UNDEFINED; mRotationChoiceShownToUserForConfirmation = ROTATION_UNDEFINED;
if (isDefaultDisplay) { if (useDefaultSettingsProvider()) {
// We'll be notified via settings listener, so we don't need to update internal values. // We'll be notified via settings listener, so we don't need to update internal values.
final ContentResolver res = mContext.getContentResolver(); final ContentResolver res = mContext.getContentResolver();
final int accelerometerRotation = final int accelerometerRotation =
@@ -1814,7 +1827,7 @@ public class DisplayRotation {
return false; return false;
} }
if (mDeviceState == DeviceStateController.DeviceState.HALF_FOLDED) { if (mDeviceState == DeviceStateController.DeviceState.HALF_FOLDED) {
return !(isTabletop ^ mTabletopRotations.contains(mRotation)); return isTabletop == mTabletopRotations.contains(mRotation);
} }
return true; return true;
} }
@@ -1838,14 +1851,17 @@ public class DisplayRotation {
return mDeviceState == DeviceStateController.DeviceState.OPEN return mDeviceState == DeviceStateController.DeviceState.OPEN
&& !mShouldIgnoreSensorRotation // Ignore if the hinge angle still moving && !mShouldIgnoreSensorRotation // Ignore if the hinge angle still moving
&& mInHalfFoldTransition && mInHalfFoldTransition
&& mHalfFoldSavedRotation != -1 // Ignore if we've already reverted. && mDisplayContent.getRotationReversionController().isOverrideActive(
REVERSION_TYPE_HALF_FOLD)
&& mUserRotationMode && mUserRotationMode
== WindowManagerPolicy.USER_ROTATION_LOCKED; // Ignore if we're unlocked. == WindowManagerPolicy.USER_ROTATION_LOCKED; // Ignore if we're unlocked.
} }
int revertOverriddenRotation() { int revertOverriddenRotation() {
int savedRotation = mHalfFoldSavedRotation; int savedRotation = mHalfFoldSavedRotation;
mHalfFoldSavedRotation = -1; mHalfFoldSavedRotation = -1;
mDisplayContent.getRotationReversionController()
.revertOverride(REVERSION_TYPE_HALF_FOLD);
mInHalfFoldTransition = false; mInHalfFoldTransition = false;
return savedRotation; return savedRotation;
} }
@@ -1865,6 +1881,8 @@ public class DisplayRotation {
&& mDeviceState != DeviceStateController.DeviceState.HALF_FOLDED) { && mDeviceState != DeviceStateController.DeviceState.HALF_FOLDED) {
// The device has transitioned to HALF_FOLDED state: save the current rotation and // The device has transitioned to HALF_FOLDED state: save the current rotation and
// update the device rotation. // update the device rotation.
mDisplayContent.getRotationReversionController().beforeOverrideApplied(
REVERSION_TYPE_HALF_FOLD);
mHalfFoldSavedRotation = mRotation; mHalfFoldSavedRotation = mRotation;
mDeviceState = newState; mDeviceState = newState;
// Now mFoldState is set to HALF_FOLDED, the overrideFrozenRotation function will // Now mFoldState is set to HALF_FOLDED, the overrideFrozenRotation function will
@@ -2069,6 +2087,8 @@ public class DisplayRotation {
final int mHalfFoldSavedRotation; final int mHalfFoldSavedRotation;
final boolean mInHalfFoldTransition; final boolean mInHalfFoldTransition;
final DeviceStateController.DeviceState mDeviceState; final DeviceStateController.DeviceState mDeviceState;
@Nullable final boolean[] mRotationReversionSlots;
@Nullable final String mDisplayRotationCompatPolicySummary; @Nullable final String mDisplayRotationCompatPolicySummary;
Record(DisplayRotation dr, int fromRotation, int toRotation) { Record(DisplayRotation dr, int fromRotation, int toRotation) {
@@ -2109,6 +2129,8 @@ public class DisplayRotation {
? null ? null
: dc.mDisplayRotationCompatPolicy : dc.mDisplayRotationCompatPolicy
.getSummaryForDisplayRotationHistoryRecord(); .getSummaryForDisplayRotationHistoryRecord();
mRotationReversionSlots =
dr.mDisplayContent.getRotationReversionController().getSlotsCopy();
} }
void dump(String prefix, PrintWriter pw) { void dump(String prefix, PrintWriter pw) {
@@ -2134,6 +2156,12 @@ public class DisplayRotation {
if (mDisplayRotationCompatPolicySummary != null) { if (mDisplayRotationCompatPolicySummary != null) {
pw.println(prefix + mDisplayRotationCompatPolicySummary); pw.println(prefix + mDisplayRotationCompatPolicySummary);
} }
if (mRotationReversionSlots != null) {
pw.println(prefix + " reversionSlots= NOSENSOR "
+ mRotationReversionSlots[REVERSION_TYPE_NOSENSOR] + ", CAMERA "
+ mRotationReversionSlots[REVERSION_TYPE_CAMERA_COMPAT] + " HALF_FOLD "
+ mRotationReversionSlots[REVERSION_TYPE_HALF_FOLD]);
}
} }
} }

View File

@@ -33,6 +33,7 @@ import static android.view.Display.TYPE_INTERNAL;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ORIENTATION; import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ORIENTATION;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_STATES; import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_STATES;
import static com.android.server.wm.DisplayRotationReversionController.REVERSION_TYPE_CAMERA_COMPAT;
import android.annotation.NonNull; import android.annotation.NonNull;
import android.annotation.Nullable; import android.annotation.Nullable;
@@ -156,6 +157,11 @@ final class DisplayRotationCompatPolicy {
@ScreenOrientation @ScreenOrientation
int getOrientation() { int getOrientation() {
mLastReportedOrientation = getOrientationInternal(); mLastReportedOrientation = getOrientationInternal();
if (mLastReportedOrientation != SCREEN_ORIENTATION_UNSPECIFIED) {
rememberOverriddenOrientationIfNeeded();
} else {
restoreOverriddenOrientationIfNeeded();
}
return mLastReportedOrientation; return mLastReportedOrientation;
} }
@@ -277,6 +283,34 @@ final class DisplayRotationCompatPolicy {
+ " }"; + " }";
} }
private void restoreOverriddenOrientationIfNeeded() {
if (!isOrientationOverridden()) {
return;
}
if (mDisplayContent.getRotationReversionController().revertOverride(
REVERSION_TYPE_CAMERA_COMPAT)) {
ProtoLog.v(WM_DEBUG_ORIENTATION,
"Reverting orientation after camera compat force rotation");
// Reset last orientation source since we have reverted the orientation.
mDisplayContent.mLastOrientationSource = null;
}
}
private boolean isOrientationOverridden() {
return mDisplayContent.getRotationReversionController().isOverrideActive(
REVERSION_TYPE_CAMERA_COMPAT);
}
private void rememberOverriddenOrientationIfNeeded() {
if (!isOrientationOverridden()) {
mDisplayContent.getRotationReversionController().beforeOverrideApplied(
REVERSION_TYPE_CAMERA_COMPAT);
ProtoLog.v(WM_DEBUG_ORIENTATION,
"Saving original orientation before camera compat, last orientation is %d",
mDisplayContent.getLastOrientation());
}
}
// Refreshing only when configuration changes after rotation. // Refreshing only when configuration changes after rotation.
private boolean shouldRefreshActivity(ActivityRecord activity, Configuration newConfig, private boolean shouldRefreshActivity(ActivityRecord activity, Configuration newConfig,
Configuration lastReportedConfig) { Configuration lastReportedConfig) {

View File

@@ -0,0 +1,148 @@
/*
* Copyright (C) 2023 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.server.wm;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ORIENTATION;
import android.annotation.Nullable;
import android.app.WindowConfiguration;
import android.content.ActivityInfoProto;
import android.view.Surface;
import com.android.internal.protolog.common.ProtoLog;
import com.android.server.policy.WindowManagerPolicy;
/**
* Defines the behavior of reversion from device rotation overrides.
*
* <p>There are 3 override types:
* <ol>
* <li>The top application has {@link SCREEN_ORIENTATION_NOSENSOR} set and is rotated to
* {@link ROTATION_0}.
* <li>Camera compat treatment has rotated the app {@link DisplayRotationCompatPolicy}.
* <li>The device is half-folded and has auto-rotate is temporarily enabled.
* </ol>
*
* <p>Before an override is enabled, a component should call {@code beforeOverrideApplied}. When
* it wishes to revert, it should call {@code revertOverride}. The user rotation will be restored
* if there are no other overrides present.
*/
final class DisplayRotationReversionController {
static final int REVERSION_TYPE_NOSENSOR = 0;
static final int REVERSION_TYPE_CAMERA_COMPAT = 1;
static final int REVERSION_TYPE_HALF_FOLD = 2;
private static final int NUM_SLOTS = 3;
@Surface.Rotation
private int mUserRotationOverridden = WindowConfiguration.ROTATION_UNDEFINED;
@WindowManagerPolicy.UserRotationMode
private int mUserRotationModeOverridden;
private final boolean[] mSlots = new boolean[NUM_SLOTS];
private final DisplayContent mDisplayContent;
DisplayRotationReversionController(DisplayContent content) {
mDisplayContent = content;
}
boolean isRotationReversionEnabled() {
return mDisplayContent.mDisplayRotationCompatPolicy != null
|| mDisplayContent.getDisplayRotation().mFoldController != null
|| mDisplayContent.getIgnoreOrientationRequest();
}
void beforeOverrideApplied(int slotIndex) {
if (mSlots[slotIndex]) return;
maybeSaveUserRotation();
mSlots[slotIndex] = true;
}
boolean isOverrideActive(int slotIndex) {
return mSlots[slotIndex];
}
@Nullable
boolean[] getSlotsCopy() {
return isRotationReversionEnabled() ? mSlots.clone() : null;
}
void updateForNoSensorOverride() {
if (!mSlots[REVERSION_TYPE_NOSENSOR]) {
if (isTopFullscreenActivityNoSensor()) {
ProtoLog.v(WM_DEBUG_ORIENTATION, "NOSENSOR override detected");
beforeOverrideApplied(REVERSION_TYPE_NOSENSOR);
}
} else {
if (!isTopFullscreenActivityNoSensor()) {
ProtoLog.v(WM_DEBUG_ORIENTATION, "NOSENSOR override is absent: reverting");
revertOverride(REVERSION_TYPE_NOSENSOR);
}
}
}
boolean isAnyOverrideActive() {
for (int i = 0; i < NUM_SLOTS; ++i) {
if (mSlots[i]) {
return true;
}
}
return false;
}
boolean revertOverride(int slotIndex) {
if (!mSlots[slotIndex]) return false;
mSlots[slotIndex] = false;
if (isAnyOverrideActive()) {
ProtoLog.v(WM_DEBUG_ORIENTATION,
"Other orientation overrides are in place: not reverting");
return false;
}
// Only override if the rotation is frozen and there are no other active slots.
if (mDisplayContent.getDisplayRotation().isRotationFrozen()) {
mDisplayContent.getDisplayRotation().setUserRotation(
mUserRotationModeOverridden,
mUserRotationOverridden);
return true;
} else {
return false;
}
}
private void maybeSaveUserRotation() {
if (!isAnyOverrideActive()) {
mUserRotationModeOverridden =
mDisplayContent.getDisplayRotation().getUserRotationMode();
mUserRotationOverridden = mDisplayContent.getDisplayRotation().getUserRotation();
}
}
private boolean isTopFullscreenActivityNoSensor() {
final Task topFullscreenTask =
mDisplayContent.getTask(
t -> t.getWindowingMode() == WINDOWING_MODE_FULLSCREEN);
if (topFullscreenTask != null) {
final ActivityRecord topActivity =
topFullscreenTask.topRunningActivity();
return topActivity != null && topActivity.getOrientation()
== ActivityInfoProto.SCREEN_ORIENTATION_NOSENSOR;
}
return false;
}
}

View File

@@ -24,6 +24,7 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.content.pm.ActivityInfo.FLAG_SHOW_WHEN_LOCKED; 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_BEHIND;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE; import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
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_PORTRAIT;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR; import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR;
@@ -1061,6 +1062,51 @@ public class DisplayContentTests extends WindowTestsBase {
assertEquals(SCREEN_ORIENTATION_LANDSCAPE, dc.getOrientation()); assertEquals(SCREEN_ORIENTATION_LANDSCAPE, dc.getOrientation());
} }
private void updateAllDisplayContentAndRotation(DisplayContent dc) {
// NB updateOrientation will not revert the user orientation until a settings change
// takes effect.
dc.updateOrientation();
dc.onDisplayChanged(dc);
dc.mWmService.updateRotation(true /* alwaysSendConfiguration */,
false /* forceRelayout */);
waitUntilHandlersIdle();
}
@Test
public void testNoSensorRevert() {
final DisplayContent dc = mDisplayContent;
spyOn(dc);
doReturn(true).when(dc).getIgnoreOrientationRequest();
final DisplayRotation dr = dc.getDisplayRotation();
spyOn(dr);
doReturn(false).when(dr).useDefaultSettingsProvider();
final ActivityRecord app = new ActivityBuilder(mAtm).setCreateTask(true).build();
app.setOrientation(SCREEN_ORIENTATION_LANDSCAPE, app);
assertFalse(dc.getRotationReversionController().isAnyOverrideActive());
dc.getDisplayRotation().setUserRotation(WindowManagerPolicy.USER_ROTATION_LOCKED,
ROTATION_90);
updateAllDisplayContentAndRotation(dc);
assertEquals(ROTATION_90, dc.getDisplayRotation()
.rotationForOrientation(SCREEN_ORIENTATION_UNSPECIFIED, ROTATION_90));
app.setOrientation(SCREEN_ORIENTATION_NOSENSOR);
updateAllDisplayContentAndRotation(dc);
assertTrue(dc.getRotationReversionController().isAnyOverrideActive());
assertEquals(ROTATION_0, dc.getRotation());
app.setOrientation(SCREEN_ORIENTATION_UNSPECIFIED);
updateAllDisplayContentAndRotation(dc);
assertFalse(dc.getRotationReversionController().isAnyOverrideActive());
assertEquals(WindowManagerPolicy.USER_ROTATION_LOCKED,
dc.getDisplayRotation().getUserRotationMode());
assertEquals(ROTATION_90, dc.getDisplayRotation().getUserRotation());
assertEquals(ROTATION_90, dc.getDisplayRotation()
.rotationForOrientation(SCREEN_ORIENTATION_UNSPECIFIED, ROTATION_0));
dc.getDisplayRotation().setUserRotation(WindowManagerPolicy.USER_ROTATION_FREE,
ROTATION_0);
}
@Test @Test
public void testOnDescendantOrientationRequestChanged() { public void testOnDescendantOrientationRequestChanged() {
final DisplayContent dc = createNewDisplay(); final DisplayContent dc = createNewDisplay();

View File

@@ -364,6 +364,23 @@ public final class DisplayRotationCompatPolicyTests extends WindowTestsBase {
assertActivityRefreshRequested(/* refreshRequested */ true); assertActivityRefreshRequested(/* refreshRequested */ true);
} }
@Test
public void testCameraDisconnected_revertRotationAndRefresh() throws Exception {
configureActivityAndDisplay(SCREEN_ORIENTATION_PORTRAIT, ORIENTATION_LANDSCAPE);
// Open camera and test for compat treatment
mCameraAvailabilityCallback.onCameraOpened(CAMERA_ID_1, TEST_PACKAGE_1);
callOnActivityConfigurationChanging(mActivity, /* isDisplayRotationChanging */ true);
assertEquals(mDisplayRotationCompatPolicy.getOrientation(),
SCREEN_ORIENTATION_LANDSCAPE);
assertActivityRefreshRequested(/* refreshRequested */ true);
// Close camera and test for revert
mCameraAvailabilityCallback.onCameraClosed(CAMERA_ID_1);
callOnActivityConfigurationChanging(mActivity, /* isDisplayRotationChanging */ true);
assertEquals(mDisplayRotationCompatPolicy.getOrientation(),
SCREEN_ORIENTATION_UNSPECIFIED);
assertActivityRefreshRequested(/* refreshRequested */ true);
}
@Test @Test
public void testGetOrientation_cameraConnectionClosed_returnUnspecified() { public void testGetOrientation_cameraConnectionClosed_returnUnspecified() {
configureActivity(SCREEN_ORIENTATION_PORTRAIT); configureActivity(SCREEN_ORIENTATION_PORTRAIT);

View File

@@ -112,6 +112,7 @@ public class DisplayRotationTests {
private static WindowManagerService sMockWm; private static WindowManagerService sMockWm;
private DisplayContent mMockDisplayContent; private DisplayContent mMockDisplayContent;
private DisplayRotationReversionController mMockDisplayRotationReversionController;
private DisplayPolicy mMockDisplayPolicy; private DisplayPolicy mMockDisplayPolicy;
private DisplayAddress mMockDisplayAddress; private DisplayAddress mMockDisplayAddress;
private Context mMockContext; private Context mMockContext;
@@ -1367,6 +1368,10 @@ public class DisplayRotationTests {
when(mMockContext.getResources().getBoolean( when(mMockContext.getResources().getBoolean(
com.android.internal.R.bool.config_windowManagerHalfFoldAutoRotateOverride)) com.android.internal.R.bool.config_windowManagerHalfFoldAutoRotateOverride))
.thenReturn(mSupportHalfFoldAutoRotateOverride); .thenReturn(mSupportHalfFoldAutoRotateOverride);
mMockDisplayRotationReversionController =
mock(DisplayRotationReversionController.class);
when(mMockDisplayContent.getRotationReversionController())
.thenReturn(mMockDisplayRotationReversionController);
mMockResolver = mock(ContentResolver.class); mMockResolver = mock(ContentResolver.class);
when(mMockContext.getContentResolver()).thenReturn(mMockResolver); when(mMockContext.getContentResolver()).thenReturn(mMockResolver);