diff options
9 files changed, 239 insertions, 12 deletions
diff --git a/core/java/android/content/pm/ActivityInfo.java b/core/java/android/content/pm/ActivityInfo.java index 80cea55111ba..ca1183e82a49 100644 --- a/core/java/android/content/pm/ActivityInfo.java +++ b/core/java/android/content/pm/ActivityInfo.java @@ -1238,6 +1238,18 @@ public class ActivityInfo extends ComponentInfo implements Parcelable { 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 * activity will be still respected by bounds resolution logic. For instance, if an activity diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index a74c787fdab1..15c40c0fa3a9 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -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" /> diff --git a/services/core/java/com/android/server/wm/DisplayRotationCompatPolicy.java b/services/core/java/com/android/server/wm/DisplayRotationCompatPolicy.java index 3ffb2fa7eaad..e04900c94f15 100644 --- a/services/core/java/com/android/server/wm/DisplayRotationCompatPolicy.java +++ b/services/core/java/com/android/server/wm/DisplayRotationCompatPolicy.java @@ -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. diff --git a/services/core/java/com/android/server/wm/LetterboxConfiguration.java b/services/core/java/com/android/server/wm/LetterboxConfiguration.java index 22db37034153..7066a330cc1b 100644 --- a/services/core/java/com/android/server/wm/LetterboxConfiguration.java +++ b/services/core/java/com/android/server/wm/LetterboxConfiguration.java @@ -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; @@ -308,6 +309,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); mDeviceConfig.updateFlagActiveStatus( @@ -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. */ diff --git a/services/core/java/com/android/server/wm/LetterboxConfigurationDeviceConfig.java b/services/core/java/com/android/server/wm/LetterboxConfigurationDeviceConfig.java index 3f067e3a1556..d004fa664775 100644 --- a/services/core/java/com/android/server/wm/LetterboxConfigurationDeviceConfig.java +++ b/services/core/java/com/android/server/wm/LetterboxConfigurationDeviceConfig.java @@ -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); diff --git a/services/core/java/com/android/server/wm/LetterboxUiController.java b/services/core/java/com/android/server/wm/LetterboxUiController.java index 59e5ca4d1fbf..8d6de58c7246 100644 --- a/services/core/java/com/android/server/wm/LetterboxUiController.java +++ b/services/core/java/com/android/server/wm/LetterboxUiController.java @@ -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. diff --git a/services/core/java/com/android/server/wm/ScreenRotationAnimation.java b/services/core/java/com/android/server/wm/ScreenRotationAnimation.java index fd8b614de9b7..ef45c221a6cc 100644 --- a/services/core/java/com/android/server/wm/ScreenRotationAnimation.java +++ b/services/core/java/com/android/server/wm/ScreenRotationAnimation.java @@ -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(); } diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayRotationCompatPolicyTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayRotationCompatPolicyTests.java index 45b30b204801..4954e89c1ffd 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayRotationCompatPolicyTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayRotationCompatPolicyTests.java @@ -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; @@ -128,6 +133,69 @@ public final class DisplayRotationCompatPolicyTests extends WindowTestsBase { } @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( /* checkDeviceConfig */ anyBoolean())) diff --git a/services/tests/wmtests/src/com/android/server/wm/LetterboxUiControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/LetterboxUiControllerTest.java index f6f7dca57e08..0d20f1772d0b 100644 --- a/services/tests/wmtests/src/com/android/server/wm/LetterboxUiControllerTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/LetterboxUiControllerTest.java @@ -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 |