Merge changes from topic "camera-orientation-override" into tm-qpr-dev

* changes:
  [6/n] Camera Compat: Orientation override for camera only
  [5/n] Camera Compat: Toasts explaining compat treatment
This commit is contained in:
Mariia Sandrikova
2023-02-01 12:05:51 +00:00
committed by Android (Google) Code Review
9 changed files with 239 additions and 12 deletions

View File

@@ -1237,6 +1237,18 @@ public class ActivityInfo extends ComponentInfo implements Parcelable {
@Overridable
public static final long OVERRIDE_ANY_ORIENTATION = 265464455L;
/**
* When enabled, activates OVERRIDE_LANDSCAPE_ORIENTATION_TO_REVERSE_LANDSCAPE,
* OVERRIDE_UNDEFINED_ORIENTATION_TO_NOSENSOR and OVERRIDE_UNDEFINED_ORIENTATION_TO_PORTRAIT
* only when an app is connected to the camera. See
* com.android.server.wm.DisplayRotationCompatPolicy for more context.
* @hide
*/
@ChangeId
@Disabled
@Overridable
public static final long OVERRIDE_ORIENTATION_ONLY_FOR_CAMERA = 265456536L;
/**
* This override fixes display orientation to landscape natural orientation when a task is
* fullscreen. While display rotation is fixed to landscape, the orientation requested by the

View File

@@ -2562,6 +2562,8 @@
<java-symbol type="string" name="zen_mode_default_weekends_name" />
<java-symbol type="string" name="zen_mode_default_events_name" />
<java-symbol type="string" name="zen_mode_default_every_night_name" />
<java-symbol type="string" name="display_rotation_camera_compat_toast_after_rotation" />
<java-symbol type="string" name="display_rotation_camera_compat_toast_in_split_screen" />
<java-symbol type="array" name="config_system_condition_providers" />
<java-symbol type="string" name="muted_by" />
<java-symbol type="string" name="zen_mode_alarm" />

View File

@@ -16,6 +16,8 @@
package com.android.server.wm;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
import static android.app.servertransaction.ActivityLifecycleItem.ON_PAUSE;
import static android.app.servertransaction.ActivityLifecycleItem.ON_STOP;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
@@ -34,6 +36,7 @@ import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_STATES;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.StringRes;
import android.app.servertransaction.ClientTransaction;
import android.app.servertransaction.RefreshCallbackItem;
import android.app.servertransaction.ResumeActivityItem;
@@ -44,10 +47,13 @@ import android.os.Handler;
import android.os.RemoteException;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.widget.Toast;
import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.protolog.common.ProtoLog;
import com.android.server.UiThread;
import java.util.Map;
import java.util.Set;
@@ -232,6 +238,27 @@ final class DisplayRotationCompatPolicy {
activity.mLetterboxUiController.setIsRefreshAfterRotationRequested(false);
}
/**
* Notifies that animation in {@link ScreenAnimationRotation} has finished.
*
* <p>This class uses this signal as a trigger for notifying the user about forced rotation
* reason with the {@link Toast}.
*/
void onScreenRotationAnimationFinished() {
if (!isTreatmentEnabledForDisplay() || mCameraIdPackageBiMap.isEmpty()) {
return;
}
ActivityRecord topActivity = mDisplayContent.topRunningActivity(
/* considerKeyguardState= */ true);
if (topActivity == null
// Checking windowing mode on activity level because we don't want to
// show toast in case of activity embedding.
|| topActivity.getWindowingMode() != WINDOWING_MODE_FULLSCREEN) {
return;
}
showToast(R.string.display_rotation_camera_compat_toast_after_rotation);
}
String getSummaryForDisplayRotationHistoryRecord() {
String summaryIfEnabled = "";
if (isTreatmentEnabledForDisplay()) {
@@ -281,6 +308,10 @@ final class DisplayRotationCompatPolicy {
&& mDisplayContent.getDisplay().getType() == TYPE_INTERNAL;
}
boolean isActivityEligibleForOrientationOverride(@NonNull ActivityRecord activity) {
return isTreatmentEnabledForDisplay() && isCameraActiveInFullscreen(activity);
}
/**
* Whether camera compat treatment is applicable for the given activity.
*
@@ -292,12 +323,16 @@ final class DisplayRotationCompatPolicy {
* </ul>
*/
boolean isTreatmentEnabledForActivity(@Nullable ActivityRecord activity) {
return activity != null && !activity.inMultiWindowMode()
return activity != null && isCameraActiveInFullscreen(activity)
&& activity.getRequestedConfigurationOrientation() != ORIENTATION_UNDEFINED
// "locked" and "nosensor" values are often used by camera apps that can't
// handle dynamic changes so we shouldn't force rotate them.
&& activity.getOverrideOrientation() != SCREEN_ORIENTATION_NOSENSOR
&& activity.getOverrideOrientation() != SCREEN_ORIENTATION_LOCKED
&& activity.getOverrideOrientation() != SCREEN_ORIENTATION_LOCKED;
}
private boolean isCameraActiveInFullscreen(@NonNull ActivityRecord activity) {
return !activity.inMultiWindowMode()
&& mCameraIdPackageBiMap.containsPackageName(activity.packageName)
&& activity.mLetterboxUiController.shouldForceRotateForCameraCompat();
}
@@ -334,7 +369,31 @@ final class DisplayRotationCompatPolicy {
}
mCameraIdPackageBiMap.put(packageName, cameraId);
}
updateOrientationWithWmLock();
ActivityRecord topActivity = mDisplayContent.topRunningActivity(
/* considerKeyguardState= */ true);
if (topActivity == null || topActivity.getTask() == null) {
return;
}
// Checking whether an activity in fullscreen rather than the task as this camera compat
// treatment doesn't cover activity embedding.
if (topActivity.getWindowingMode() == WINDOWING_MODE_FULLSCREEN) {
if (topActivity.mLetterboxUiController.isOverrideOrientationOnlyForCameraEnabled()) {
topActivity.recomputeConfiguration();
}
updateOrientationWithWmLock();
return;
}
// Checking that the whole app is in multi-window mode as we shouldn't show toast
// for the activity embedding case.
if (topActivity.getTask().getWindowingMode() == WINDOWING_MODE_MULTI_WINDOW) {
showToast(R.string.display_rotation_camera_compat_toast_in_split_screen);
}
}
@VisibleForTesting
void showToast(@StringRes int stringRes) {
UiThread.getHandler().post(
() -> Toast.makeText(mWmService.mContext, stringRes, Toast.LENGTH_LONG).show());
}
private synchronized void notifyCameraClosed(@NonNull String cameraId) {
@@ -375,6 +434,17 @@ final class DisplayRotationCompatPolicy {
ProtoLog.v(WM_DEBUG_ORIENTATION,
"Display id=%d is notified that Camera %s is closed, updating rotation.",
mDisplayContent.mDisplayId, cameraId);
ActivityRecord topActivity = mDisplayContent.topRunningActivity(
/* considerKeyguardState= */ true);
if (topActivity == null
// Checking whether an activity in fullscreen rather than the task as this camera
// compat treatment doesn't cover activity embedding.
|| topActivity.getWindowingMode() != WINDOWING_MODE_FULLSCREEN) {
return;
}
if (topActivity.mLetterboxUiController.isOverrideOrientationOnlyForCameraEnabled()) {
topActivity.recomputeConfiguration();
}
updateOrientationWithWmLock();
}
@@ -396,6 +466,10 @@ final class DisplayRotationCompatPolicy {
private final Map<String, String> mPackageToCameraIdMap = new ArrayMap<>();
private final Map<String, String> mCameraIdToPackageMap = new ArrayMap<>();
boolean isEmpty() {
return mCameraIdToPackageMap.isEmpty();
}
void put(String packageName, String cameraId) {
// Always using the last connected camera ID for the package even for the concurrent
// camera use case since we can't guess which camera is more important anyway.

View File

@@ -19,6 +19,7 @@ package com.android.server.wm;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.LetterboxConfigurationDeviceConfig.KEY_ALLOW_IGNORE_ORIENTATION_REQUEST;
import static com.android.server.wm.LetterboxConfigurationDeviceConfig.KEY_ENABLE_CAMERA_COMPAT_TREATMENT;
import static com.android.server.wm.LetterboxConfigurationDeviceConfig.KEY_ENABLE_DISPLAY_ROTATION_IMMERSIVE_APP_COMPAT_POLICY;
import android.annotation.IntDef;
@@ -307,6 +308,9 @@ final class LetterboxConfiguration {
mIsDisplayRotationImmersiveAppCompatPolicyEnabled = mContext.getResources().getBoolean(
R.bool.config_letterboxIsDisplayRotationImmersiveAppCompatPolicyEnabled);
mDeviceConfig.updateFlagActiveStatus(
/* isActive */ mIsCameraCompatTreatmentEnabled,
/* key */ KEY_ENABLE_CAMERA_COMPAT_TREATMENT);
mDeviceConfig.updateFlagActiveStatus(
/* isActive */ mIsDisplayRotationImmersiveAppCompatPolicyEnabled,
/* key */ KEY_ENABLE_DISPLAY_ROTATION_IMMERSIVE_APP_COMPAT_POLICY);
@@ -1086,15 +1090,8 @@ final class LetterboxConfiguration {
/** Whether camera compatibility treatment is enabled. */
boolean isCameraCompatTreatmentEnabled(boolean checkDeviceConfig) {
return mIsCameraCompatTreatmentEnabled
&& (!checkDeviceConfig || isCameraCompatTreatmentAllowed());
}
// TODO(b/262977416): Cache a runtime flag and implement
// DeviceConfig.OnPropertiesChangedListener
private static boolean isCameraCompatTreatmentAllowed() {
return DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_WINDOW_MANAGER,
"enable_compat_camera_treatment", true);
return mIsCameraCompatTreatmentEnabled && (!checkDeviceConfig
|| mDeviceConfig.getFlag(KEY_ENABLE_CAMERA_COMPAT_TREATMENT));
}
/** Whether camera compatibility refresh is enabled. */

View File

@@ -33,6 +33,9 @@ import java.util.concurrent.Executor;
final class LetterboxConfigurationDeviceConfig
implements DeviceConfig.OnPropertiesChangedListener {
static final String KEY_ENABLE_CAMERA_COMPAT_TREATMENT = "enable_compat_camera_treatment";
private static final boolean DEFAULT_VALUE_ENABLE_CAMERA_COMPAT_TREATMENT = true;
static final String KEY_ENABLE_DISPLAY_ROTATION_IMMERSIVE_APP_COMPAT_POLICY =
"enable_display_rotation_immersive_app_compat_policy";
private static final boolean DEFAULT_VALUE_ENABLE_DISPLAY_ROTATION_IMMERSIVE_APP_COMPAT_POLICY =
@@ -44,12 +47,19 @@ final class LetterboxConfigurationDeviceConfig
@VisibleForTesting
static final Map<String, Boolean> sKeyToDefaultValueMap = Map.of(
KEY_ENABLE_CAMERA_COMPAT_TREATMENT,
DEFAULT_VALUE_ENABLE_CAMERA_COMPAT_TREATMENT,
KEY_ENABLE_DISPLAY_ROTATION_IMMERSIVE_APP_COMPAT_POLICY,
DEFAULT_VALUE_ENABLE_DISPLAY_ROTATION_IMMERSIVE_APP_COMPAT_POLICY,
KEY_ALLOW_IGNORE_ORIENTATION_REQUEST,
DEFAULT_VALUE_ALLOW_IGNORE_ORIENTATION_REQUEST
);
// Whether camera compatibility treatment is enabled.
// See DisplayRotationCompatPolicy for context.
private boolean mIsCameraCompatTreatmentEnabled =
DEFAULT_VALUE_ENABLE_CAMERA_COMPAT_TREATMENT;
// Whether enabling rotation compat policy for immersive apps that prevents auto rotation
// into non-optimal screen orientation while in fullscreen. This is needed because immersive
// apps, such as games, are often not optimized for all orientations and can have a poor UX
@@ -101,6 +111,8 @@ final class LetterboxConfigurationDeviceConfig
*/
boolean getFlag(String key) {
switch (key) {
case KEY_ENABLE_CAMERA_COMPAT_TREATMENT:
return mIsCameraCompatTreatmentEnabled;
case KEY_ENABLE_DISPLAY_ROTATION_IMMERSIVE_APP_COMPAT_POLICY:
return mIsDisplayRotationImmersiveAppCompatPolicyEnabled;
case KEY_ALLOW_IGNORE_ORIENTATION_REQUEST:
@@ -116,6 +128,10 @@ final class LetterboxConfigurationDeviceConfig
throw new AssertionError("Haven't found default value for flag: " + key);
}
switch (key) {
case KEY_ENABLE_CAMERA_COMPAT_TREATMENT:
mIsCameraCompatTreatmentEnabled =
getDeviceConfig(key, defaultValue);
break;
case KEY_ENABLE_DISPLAY_ROTATION_IMMERSIVE_APP_COMPAT_POLICY:
mIsDisplayRotationImmersiveAppCompatPolicyEnabled =
getDeviceConfig(key, defaultValue);

View File

@@ -24,6 +24,7 @@ import static android.content.pm.ActivityInfo.OVERRIDE_CAMERA_COMPAT_ENABLE_REFR
import static android.content.pm.ActivityInfo.OVERRIDE_ENABLE_COMPAT_FAKE_FOCUS;
import static android.content.pm.ActivityInfo.OVERRIDE_ENABLE_COMPAT_IGNORE_REQUESTED_ORIENTATION;
import static android.content.pm.ActivityInfo.OVERRIDE_LANDSCAPE_ORIENTATION_TO_REVERSE_LANDSCAPE;
import static android.content.pm.ActivityInfo.OVERRIDE_ORIENTATION_ONLY_FOR_CAMERA;
import static android.content.pm.ActivityInfo.OVERRIDE_UNDEFINED_ORIENTATION_TO_NOSENSOR;
import static android.content.pm.ActivityInfo.OVERRIDE_UNDEFINED_ORIENTATION_TO_PORTRAIT;
import static android.content.pm.ActivityInfo.OVERRIDE_USE_DISPLAY_LANDSCAPE_NATURAL_ORIENTATION;
@@ -138,6 +139,8 @@ final class LetterboxUiController {
private final boolean mIsOverrideToNosensorOrientationEnabled;
// Corresponds to OVERRIDE_LANDSCAPE_ORIENTATION_TO_REVERSE_LANDSCAPE
private final boolean mIsOverrideToReverseLandscapeOrientationEnabled;
// Corresponds to OVERRIDE_ORIENTATION_ONLY_FOR_CAMERA
private final boolean mIsOverrideOrientationOnlyForCameraEnabled;
// Corresponds to OVERRIDE_USE_DISPLAY_LANDSCAPE_NATURAL_ORIENTATION
private final boolean mIsOverrideUseDisplayLandscapeNaturalOrientationEnabled;
@@ -265,6 +268,8 @@ final class LetterboxUiController {
isCompatChangeEnabled(OVERRIDE_LANDSCAPE_ORIENTATION_TO_REVERSE_LANDSCAPE);
mIsOverrideToNosensorOrientationEnabled =
isCompatChangeEnabled(OVERRIDE_UNDEFINED_ORIENTATION_TO_NOSENSOR);
mIsOverrideOrientationOnlyForCameraEnabled =
isCompatChangeEnabled(OVERRIDE_ORIENTATION_ONLY_FOR_CAMERA);
mIsOverrideUseDisplayLandscapeNaturalOrientationEnabled =
isCompatChangeEnabled(OVERRIDE_USE_DISPLAY_LANDSCAPE_NATURAL_ORIENTATION);
@@ -444,6 +449,14 @@ final class LetterboxUiController {
return candidate;
}
DisplayContent displayContent = mActivityRecord.mDisplayContent;
if (mIsOverrideOrientationOnlyForCameraEnabled && displayContent != null
&& (displayContent.mDisplayRotationCompatPolicy == null
|| !displayContent.mDisplayRotationCompatPolicy
.isActivityEligibleForOrientationOverride(mActivityRecord))) {
return candidate;
}
if (mIsOverrideToReverseLandscapeOrientationEnabled
&& (isFixedOrientationLandscape(candidate) || mIsOverrideAnyOrientationEnabled)) {
Slog.w(TAG, "Requested orientation " + screenOrientationToString(candidate) + " for "
@@ -473,6 +486,10 @@ final class LetterboxUiController {
return candidate;
}
boolean isOverrideOrientationOnlyForCameraEnabled() {
return mIsOverrideOrientationOnlyForCameraEnabled;
}
/**
* Whether activity is eligible for activity "refresh" after camera compat force rotation
* treatment. See {@link DisplayRotationCompatPolicy} for context.

View File

@@ -800,6 +800,10 @@ class ScreenRotationAnimation {
if (mDisplayContent.getRotationAnimation() == ScreenRotationAnimation.this) {
// It also invokes kill().
mDisplayContent.setRotationAnimation(null);
if (mDisplayContent.mDisplayRotationCompatPolicy != null) {
mDisplayContent.mDisplayRotationCompatPolicy
.onScreenRotationAnimationFinished();
}
} else {
kill();
}

View File

@@ -16,6 +16,7 @@
package com.android.server.wm;
import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
import static android.app.servertransaction.ActivityLifecycleItem.ON_PAUSE;
import static android.app.servertransaction.ActivityLifecycleItem.ON_STOP;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
@@ -30,7 +31,9 @@ import static android.view.Surface.ROTATION_90;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.never;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;
import static org.junit.Assert.assertEquals;
@@ -58,6 +61,8 @@ import android.view.Surface.Rotation;
import androidx.test.filters.SmallTest;
import com.android.internal.R;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -127,6 +132,69 @@ public final class DisplayRotationCompatPolicyTests extends WindowTestsBase {
mDisplayContent, mMockHandler);
}
@Test
public void testOpenedCameraInSplitScreen_showToast() {
configureActivity(SCREEN_ORIENTATION_PORTRAIT);
spyOn(mTask);
spyOn(mDisplayRotationCompatPolicy);
doReturn(WINDOWING_MODE_MULTI_WINDOW).when(mActivity).getWindowingMode();
doReturn(WINDOWING_MODE_MULTI_WINDOW).when(mTask).getWindowingMode();
mCameraAvailabilityCallback.onCameraOpened(CAMERA_ID_1, TEST_PACKAGE_1);
verify(mDisplayRotationCompatPolicy).showToast(
R.string.display_rotation_camera_compat_toast_in_split_screen);
}
@Test
public void testOnScreenRotationAnimationFinished_treatmentNotEnabled_doNotShowToast() {
when(mLetterboxConfiguration.isCameraCompatTreatmentEnabled(
/* checkDeviceConfig */ anyBoolean()))
.thenReturn(false);
spyOn(mDisplayRotationCompatPolicy);
mDisplayRotationCompatPolicy.onScreenRotationAnimationFinished();
verify(mDisplayRotationCompatPolicy, never()).showToast(
R.string.display_rotation_camera_compat_toast_after_rotation);
}
@Test
public void testOnScreenRotationAnimationFinished_noOpenCamera_doNotShowToast() {
spyOn(mDisplayRotationCompatPolicy);
mDisplayRotationCompatPolicy.onScreenRotationAnimationFinished();
verify(mDisplayRotationCompatPolicy, never()).showToast(
R.string.display_rotation_camera_compat_toast_after_rotation);
}
@Test
public void testOnScreenRotationAnimationFinished_notFullscreen_doNotShowToast() {
configureActivity(SCREEN_ORIENTATION_PORTRAIT);
doReturn(WINDOWING_MODE_MULTI_WINDOW).when(mActivity).getWindowingMode();
spyOn(mDisplayRotationCompatPolicy);
mCameraAvailabilityCallback.onCameraOpened(CAMERA_ID_1, TEST_PACKAGE_1);
mDisplayRotationCompatPolicy.onScreenRotationAnimationFinished();
verify(mDisplayRotationCompatPolicy, never()).showToast(
R.string.display_rotation_camera_compat_toast_after_rotation);
}
@Test
public void testOnScreenRotationAnimationFinished_showToast() {
configureActivity(SCREEN_ORIENTATION_PORTRAIT);
mCameraAvailabilityCallback.onCameraOpened(CAMERA_ID_1, TEST_PACKAGE_1);
spyOn(mDisplayRotationCompatPolicy);
mDisplayRotationCompatPolicy.onScreenRotationAnimationFinished();
verify(mDisplayRotationCompatPolicy).showToast(
R.string.display_rotation_camera_compat_toast_after_rotation);
}
@Test
public void testTreatmentNotEnabled_noForceRotationOrRefresh() throws Exception {
when(mLetterboxConfiguration.isCameraCompatTreatmentEnabled(

View File

@@ -23,6 +23,7 @@ import static android.content.pm.ActivityInfo.OVERRIDE_CAMERA_COMPAT_ENABLE_REFR
import static android.content.pm.ActivityInfo.OVERRIDE_ENABLE_COMPAT_FAKE_FOCUS;
import static android.content.pm.ActivityInfo.OVERRIDE_ENABLE_COMPAT_IGNORE_REQUESTED_ORIENTATION;
import static android.content.pm.ActivityInfo.OVERRIDE_LANDSCAPE_ORIENTATION_TO_REVERSE_LANDSCAPE;
import static android.content.pm.ActivityInfo.OVERRIDE_ORIENTATION_ONLY_FOR_CAMERA;
import static android.content.pm.ActivityInfo.OVERRIDE_UNDEFINED_ORIENTATION_TO_NOSENSOR;
import static android.content.pm.ActivityInfo.OVERRIDE_UNDEFINED_ORIENTATION_TO_PORTRAIT;
import static android.content.pm.ActivityInfo.OVERRIDE_USE_DISPLAY_LANDSCAPE_NATURAL_ORIENTATION;
@@ -579,6 +580,42 @@ public class LetterboxUiControllerTest extends WindowTestsBase {
/* candidate */ SCREEN_ORIENTATION_UNSPECIFIED), SCREEN_ORIENTATION_UNSPECIFIED);
}
@Test
@EnableCompatChanges({OVERRIDE_UNDEFINED_ORIENTATION_TO_PORTRAIT,
OVERRIDE_ORIENTATION_ONLY_FOR_CAMERA})
public void testOverrideOrientationIfNeeded_whenCameraNotActive_returnsUnchanged() {
doReturn(true).when(mLetterboxConfiguration).isCameraCompatTreatmentEnabled(anyBoolean());
// Recreate DisplayContent with DisplayRotationCompatPolicy
mActivity = setUpActivityWithComponent();
mController = new LetterboxUiController(mWm, mActivity);
spyOn(mDisplayContent.mDisplayRotationCompatPolicy);
doReturn(false).when(mDisplayContent.mDisplayRotationCompatPolicy)
.isActivityEligibleForOrientationOverride(eq(mActivity));
assertEquals(mController.overrideOrientationIfNeeded(
/* candidate */ SCREEN_ORIENTATION_UNSPECIFIED), SCREEN_ORIENTATION_UNSPECIFIED);
}
@Test
@EnableCompatChanges({OVERRIDE_UNDEFINED_ORIENTATION_TO_PORTRAIT,
OVERRIDE_ORIENTATION_ONLY_FOR_CAMERA})
public void testOverrideOrientationIfNeeded_whenCameraActive_returnsPortrait() {
doReturn(true).when(mLetterboxConfiguration).isCameraCompatTreatmentEnabled(anyBoolean());
// Recreate DisplayContent with DisplayRotationCompatPolicy
mActivity = setUpActivityWithComponent();
mController = new LetterboxUiController(mWm, mActivity);
spyOn(mDisplayContent.mDisplayRotationCompatPolicy);
doReturn(true).when(mDisplayContent.mDisplayRotationCompatPolicy)
.isActivityEligibleForOrientationOverride(eq(mActivity));
assertEquals(mController.overrideOrientationIfNeeded(
/* candidate */ SCREEN_ORIENTATION_UNSPECIFIED), SCREEN_ORIENTATION_PORTRAIT);
}
// shouldUseDisplayLandscapeNaturalOrientation
@Test