Loading services/core/java/com/android/server/wm/AppCompatCameraDisplayRotationPolicy.java +8 −2 Original line number Diff line number Diff line Loading @@ -120,6 +120,12 @@ final class AppCompatCameraDisplayRotationPolicy implements AppCompatCameraState return mIsRunning; } static boolean isPolicyEnabled(@NonNull DisplayContent displayContent) { return !Flags.cameraCompatUnifyCameraPolicies() && displayContent.mWmService.mAppCompatConfiguration .isCameraCompatForceRotateTreatmentEnabledAtBuildTime(); } /** * Determines orientation for Camera compatibility. * Loading Loading @@ -161,7 +167,7 @@ final class AppCompatCameraDisplayRotationPolicy implements AppCompatCameraState boolean isPortraitActivity = topActivity.getRequestedConfigurationOrientation() == ORIENTATION_PORTRAIT; boolean isNaturalDisplayOrientationPortrait = mDisplayContent.getNaturalOrientation() == ORIENTATION_PORTRAIT; topActivity.getDisplayContent().getNaturalOrientation() == ORIENTATION_PORTRAIT; // Rotate portrait-only activity in the natural orientation of the displays (and in the // opposite to natural orientation for landscape-only) since many apps assume that those // are aligned when they compute orientation of the preview. Loading @@ -180,7 +186,7 @@ final class AppCompatCameraDisplayRotationPolicy implements AppCompatCameraState "Display id=%d is ignoring all orientation requests, camera is active " + "and the top activity is eligible for force rotation, return %s," + "portrait activity: %b, is natural orientation portrait: %b.", mDisplayContent.mDisplayId, screenOrientationToString(orientation), topActivity.getDisplayContent().mDisplayId, screenOrientationToString(orientation), isPortraitActivity, isNaturalDisplayOrientationPortrait); return orientation; } Loading services/core/java/com/android/server/wm/AppCompatCameraPolicy.java +7 −11 Original line number Diff line number Diff line Loading @@ -28,7 +28,6 @@ import android.content.pm.ActivityInfo.ScreenOrientation; import android.content.res.Configuration; import android.view.Surface; import android.widget.Toast; import android.window.DesktopModeFlags; import com.android.internal.annotations.VisibleForTesting; Loading @@ -52,24 +51,21 @@ class AppCompatCameraPolicy { @NonNull DisplayContent displayContent) { // Not checking DeviceConfig value here to allow enabling via DeviceConfig // without the need to restart the device. final boolean needsDisplayRotationPolicy = wmService.mAppCompatConfiguration .isCameraCompatForceRotateTreatmentEnabledAtBuildTime(); final boolean needsSimReqOrientationPolicy = DesktopModeFlags.ENABLE_CAMERA_COMPAT_SIMULATE_REQUESTED_ORIENTATION.isTrue() && DesktopModeHelper.canEnterDesktopMode(wmService.mContext) && wmService.mAppCompatConfiguration .isCameraCompatSimulateRequestedOrientationTreatmentEnabled(); if (needsDisplayRotationPolicy || needsSimReqOrientationPolicy) { final boolean isDisplayRotationPolicyEnabled = AppCompatCameraDisplayRotationPolicy .isPolicyEnabled(displayContent); final boolean isSimReqOrientationPolicyEnabled = AppCompatCameraSimReqOrientationPolicy .isPolicyEnabled(displayContent); if (isDisplayRotationPolicyEnabled || isSimReqOrientationPolicyEnabled) { final AppCompatCameraStateSource cameraStateListenerDelegate = new AppCompatCameraStateSource(); mCameraStateMonitor = new CameraStateMonitor(displayContent, wmService.mH, cameraStateListenerDelegate); mActivityRefresher = new ActivityRefresher(wmService, wmService.mH); mDisplayRotationPolicy = needsDisplayRotationPolicy mDisplayRotationPolicy = isDisplayRotationPolicyEnabled ? new AppCompatCameraDisplayRotationPolicy(displayContent, mCameraStateMonitor, cameraStateListenerDelegate, mActivityRefresher) : null; mSimReqOrientationPolicy = needsSimReqOrientationPolicy mSimReqOrientationPolicy = isSimReqOrientationPolicyEnabled ? new AppCompatCameraSimReqOrientationPolicy(displayContent, mCameraStateMonitor, cameraStateListenerDelegate, mActivityRefresher) : null; Loading services/core/java/com/android/server/wm/AppCompatCameraSimReqOrientationPolicy.java +34 −11 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ import static android.app.CameraCompatTaskInfo.CAMERA_COMPAT_PORTRAIT_DEVICE_IN_ import static android.app.CameraCompatTaskInfo.CAMERA_COMPAT_PORTRAIT_DEVICE_IN_PORTRAIT; import static android.app.CameraCompatTaskInfo.CAMERA_COMPAT_UNSPECIFIED; import static android.app.WindowConfiguration.ROTATION_UNDEFINED; import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; import static android.app.WindowConfiguration.WINDOW_CONFIG_APP_BOUNDS; import static android.app.WindowConfiguration.WINDOW_CONFIG_DISPLAY_ROTATION; import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LOCKED; Loading @@ -43,6 +44,7 @@ import android.content.res.Configuration; import android.os.RemoteException; import android.util.Slog; import android.view.Surface; import android.window.DesktopModeFlags; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.protolog.ProtoLog; Loading @@ -62,7 +64,7 @@ final class AppCompatCameraSimReqOrientationPolicy implements AppCompatCameraSta private static final String TAG = TAG_WITH_CLASS_NAME ? "AppCompatCameraSROPolicy" : TAG_WM; @NonNull private final DisplayContent mDisplayContent; private final ActivityTaskManagerService mAtmService; @NonNull private final ActivityRefresher mActivityRefresher; @NonNull Loading @@ -85,7 +87,7 @@ final class AppCompatCameraSimReqOrientationPolicy implements AppCompatCameraSta @NonNull CameraStateMonitor cameraStateMonitor, @NonNull AppCompatCameraStateSource cameraStateNotifier, @NonNull ActivityRefresher activityRefresher) { mDisplayContent = displayContent; mAtmService = displayContent.mAtmService; mCameraStateMonitor = cameraStateMonitor; mCameraStateNotifier = cameraStateNotifier; mActivityRefresher = activityRefresher; Loading Loading @@ -117,6 +119,14 @@ final class AppCompatCameraSimReqOrientationPolicy implements AppCompatCameraSta return mCameraDisplayRotationProvider.getCameraDeviceRotation(); } static boolean isPolicyEnabled(@NonNull DisplayContent displayContent) { return DesktopModeFlags.ENABLE_CAMERA_COMPAT_SIMULATE_REQUESTED_ORIENTATION.isTrue() && (DesktopModeHelper.canEnterDesktopMode(displayContent.mWmService.mContext) || Flags.cameraCompatUnifyCameraPolicies()) && displayContent.mWmService.mAppCompatConfiguration .isCameraCompatSimulateRequestedOrientationTreatmentEnabled(); } // Refreshing only when configuration changes after applying camera compat treatment. @Override public boolean shouldRefreshActivity(@NonNull ActivityRecord activity, Loading Loading @@ -174,7 +184,7 @@ final class AppCompatCameraSimReqOrientationPolicy implements AppCompatCameraSta ProtoLog.v(WmProtoLogGroups.WM_DEBUG_STATES, "Display id=%d is notified that Camera %s is closed but activity is" + " still refreshing. Rescheduling an update.", mDisplayContent.mDisplayId, cameraId); topActivity.getDisplayContent().mDisplayId, cameraId); return false; } return true; Loading Loading @@ -234,7 +244,7 @@ final class AppCompatCameraSimReqOrientationPolicy implements AppCompatCameraSta Slog.w(TAG, "Insufficient app information. Cannot revert display rotation sandboxing."); return; } final CompatibilityInfo compatibilityInfo = mDisplayContent.mAtmService final CompatibilityInfo compatibilityInfo = mAtmService .compatibilityInfoForPackageLocked(app.mInfo); // CompatibilityInfo fields are static, so even if task or activity has been closed, this // state should be updated. Loading Loading @@ -341,13 +351,18 @@ final class AppCompatCameraSimReqOrientationPolicy implements AppCompatCameraSta boolean isCameraRunningAndWindowingModeEligible(@NonNull ActivityRecord activity) { return activity.mAppCompatController.getCameraOverrides() .shouldApplyCameraCompatSimReqOrientationTreatment() // Do not apply camera compat treatment when an app is running on a candybar // display. && activity.getDisplayContent().getIgnoreOrientationRequest() && isWindowingModeEligible(activity) && mCameraStateMonitor.isCameraRunningForActivity(activity); } private boolean isWindowingModeEligible(@NonNull ActivityRecord activity) { // TODO(b/432218134): consider all windowing modes, e.g. WINDOWING_MODE_PINNED. return activity.inFreeformWindowingMode() || (Flags.cameraCompatUnifyCameraPolicies() && activity.inMultiWindowMode()); || (Flags.cameraCompatUnifyCameraPolicies() && (activity.inMultiWindowMode() || activity.getWindowingMode() == WINDOWING_MODE_FULLSCREEN)); } boolean shouldCameraCompatControlAspectRatio(@NonNull ActivityRecord activity) { Loading Loading @@ -426,18 +441,26 @@ final class AppCompatCameraSimReqOrientationPolicy implements AppCompatCameraSta @VisibleForTesting boolean isTreatmentEnabledForActivity(@NonNull ActivityRecord activity, boolean checkOrientation) { int orientation = activity.getRequestedConfigurationOrientation(); return activity.mAppCompatController.getCameraOverrides() .shouldApplyCameraCompatSimReqOrientationTreatment() // Do not apply camera compat treatment when an app is running on a candybar // display. && activity.getDisplayContent().getIgnoreOrientationRequest() && mCameraStateMonitor.isCameraRunningForActivity(activity) && (!checkOrientation || orientation != ORIENTATION_UNDEFINED) && activity.inFreeformWindowingMode() && isOrientationEligibleForTreatment(activity, checkOrientation) && isWindowingModeEligible(activity) // TODO(b/332665280): investigate whether we can support activity embedding. && !activity.isEmbedded(); } private boolean isOrientationEligibleForTreatment(@NonNull ActivityRecord activity, boolean checkOrientation) { final int orientation = activity.getRequestedConfigurationOrientation(); return (!checkOrientation || orientation != ORIENTATION_UNDEFINED) // "locked" and "nosensor" values are often used by camera apps that can't // handle dynamic changes so we shouldn't force-letterbox them. && activity.getRequestedOrientation() != SCREEN_ORIENTATION_NOSENSOR && activity.getRequestedOrientation() != SCREEN_ORIENTATION_LOCKED // TODO(b/332665280): investigate whether we can support activity embedding. && !activity.isEmbedded(); && activity.getRequestedOrientation() != SCREEN_ORIENTATION_LOCKED; } @Nullable Loading services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java +20 −15 Original line number Diff line number Diff line Loading @@ -732,6 +732,24 @@ public class ActivityRecordTests extends WindowTestsBase { @DisableFlags(Flags.FLAG_ENABLE_CAMERA_COMPAT_FOR_DESKTOP_WINDOWING_OPT_OUT) @EnableCompatChanges({OVERRIDE_CAMERA_COMPAT_ENABLE_FREEFORM_WINDOWING_TREATMENT}) public void testOrientation_allowFixedOrientationForCameraCompatInFreeformWindowing() { doReturn(true).when(() -> DesktopModeHelper.canEnterDesktopMode(any())); final ActivityRecord activity = setupDisplayAndActivityForCameraCompat( /* isCameraRunning= */ true, WINDOWING_MODE_FREEFORM); // Task in landscape. assertEquals(ORIENTATION_LANDSCAPE, activity.getTask().getConfiguration().orientation); // The app should be letterboxed. assertEquals(ORIENTATION_PORTRAIT, activity.getConfiguration().orientation); assertTrue(activity.mAppCompatController.getAspectRatioPolicy() .isLetterboxedForFixedOrientationAndAspectRatio()); } @Test @EnableFlags({Flags.FLAG_ENABLE_CAMERA_COMPAT_FOR_DESKTOP_WINDOWING, Flags.FLAG_CAMERA_COMPAT_UNIFY_CAMERA_POLICIES, Flags.FLAG_ENABLE_CAMERA_COMPAT_FOR_DESKTOP_WINDOWING_OPT_OUT}) @EnableCompatChanges({OVERRIDE_CAMERA_COMPAT_ENABLE_FREEFORM_WINDOWING_TREATMENT}) public void testOrientation_allowFixedOrientationForCameraCompatWhenEnabledForAll() { final ActivityRecord activity = setupDisplayAndActivityForCameraCompat( /* isCameraRunning= */ true, WINDOWING_MODE_FREEFORM); Loading Loading @@ -789,21 +807,6 @@ public class ActivityRecordTests extends WindowTestsBase { .isLetterboxedForFixedOrientationAndAspectRatio()); } @Test @EnableFlags(Flags.FLAG_ENABLE_CAMERA_COMPAT_FOR_DESKTOP_WINDOWING) @EnableCompatChanges({OVERRIDE_CAMERA_COMPAT_ENABLE_FREEFORM_WINDOWING_TREATMENT}) public void testOrientation_dontAllowFixedOrientationForCameraCompatFreeformIfInPip() { final ActivityRecord activity = setupDisplayAndActivityForCameraCompat( /* isCameraRunning= */ true, WINDOWING_MODE_PINNED); // Task in landscape. assertEquals(ORIENTATION_LANDSCAPE, activity.getTask().getConfiguration().orientation); // Activity is not letterboxed. assertEquals(ORIENTATION_LANDSCAPE, activity.getConfiguration().orientation); assertFalse(activity.mAppCompatController.getAspectRatioPolicy() .isLetterboxedForFixedOrientationAndAspectRatio()); } @Test public void testShouldMakeActive_deferredResume() { final ActivityRecord activity = createActivityWithTask(); Loading Loading @@ -3631,6 +3634,7 @@ public class ActivityRecordTests extends WindowTestsBase { // Create a new DisplayContent so that the flag values create the camera freeform policy. mDisplayContent = new TestDisplayContent.Builder(mAtm, mDisplayContent.getSurfaceWidth(), mDisplayContent.getSurfaceHeight()).build(); mDisplayContent.setIgnoreOrientationRequest(true); final CameraStateMonitor cameraStateMonitor = mDisplayContent.mAppCompatCameraPolicy .mCameraStateMonitor; spyOn(cameraStateMonitor); Loading @@ -3646,6 +3650,7 @@ public class ActivityRecordTests extends WindowTestsBase { final ActivityRecord activity = new ActivityBuilder(mAtm) .setComponent(ComponentName.createRelative(mContext, com.android.server.wm.ActivityRecordTests.class.getName())) .setTask(rootTask) .setParentTask(rootTask) .setCreateTask(true) .setOnTop(true) Loading services/tests/wmtests/src/com/android/server/wm/AppCompatCameraPolicyTest.java +14 −0 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ import static android.content.pm.ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_ONLY_FOR import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; import static com.android.server.wm.AppCompatCameraPolicy.isTreatmentEnabledForActivity; import static com.android.server.wm.AppCompatCameraPolicy.shouldOverrideMinAspectRatioForCamera; import static com.android.window.flags.Flags.FLAG_CAMERA_COMPAT_UNIFY_CAMERA_POLICIES; import static com.android.window.flags.Flags.FLAG_ENABLE_CAMERA_COMPAT_FOR_DESKTOP_WINDOWING; import static org.junit.Assert.assertEquals; Loading Loading @@ -124,6 +125,19 @@ public class AppCompatCameraPolicyTest extends WindowTestsBase { }); } @Test @EnableFlags({FLAG_ENABLE_CAMERA_COMPAT_FOR_DESKTOP_WINDOWING, FLAG_CAMERA_COMPAT_UNIFY_CAMERA_POLICIES}) public void testSimReqOrientationPolicy_unifyCameraPoliciesAndAllowedViaConfig_present() { runTestScenario((robot) -> { robot.dw().allowEnterDesktopMode(/* isAllowed= */ false); robot.conf().enableCameraCompatSimulateRequestedOrientationTreatment( /* enabled= */ true); robot.activity().createActivityWithComponentInNewTaskAndDisplay(); robot.checkTopActivityHasSimReqOrientationPolicy(/* exists= */ true); }); } @Test @EnableFlags(FLAG_ENABLE_CAMERA_COMPAT_FOR_DESKTOP_WINDOWING) public void testSimReqOrientationPolicy_startedWhenEnabledAndDW() { Loading Loading
services/core/java/com/android/server/wm/AppCompatCameraDisplayRotationPolicy.java +8 −2 Original line number Diff line number Diff line Loading @@ -120,6 +120,12 @@ final class AppCompatCameraDisplayRotationPolicy implements AppCompatCameraState return mIsRunning; } static boolean isPolicyEnabled(@NonNull DisplayContent displayContent) { return !Flags.cameraCompatUnifyCameraPolicies() && displayContent.mWmService.mAppCompatConfiguration .isCameraCompatForceRotateTreatmentEnabledAtBuildTime(); } /** * Determines orientation for Camera compatibility. * Loading Loading @@ -161,7 +167,7 @@ final class AppCompatCameraDisplayRotationPolicy implements AppCompatCameraState boolean isPortraitActivity = topActivity.getRequestedConfigurationOrientation() == ORIENTATION_PORTRAIT; boolean isNaturalDisplayOrientationPortrait = mDisplayContent.getNaturalOrientation() == ORIENTATION_PORTRAIT; topActivity.getDisplayContent().getNaturalOrientation() == ORIENTATION_PORTRAIT; // Rotate portrait-only activity in the natural orientation of the displays (and in the // opposite to natural orientation for landscape-only) since many apps assume that those // are aligned when they compute orientation of the preview. Loading @@ -180,7 +186,7 @@ final class AppCompatCameraDisplayRotationPolicy implements AppCompatCameraState "Display id=%d is ignoring all orientation requests, camera is active " + "and the top activity is eligible for force rotation, return %s," + "portrait activity: %b, is natural orientation portrait: %b.", mDisplayContent.mDisplayId, screenOrientationToString(orientation), topActivity.getDisplayContent().mDisplayId, screenOrientationToString(orientation), isPortraitActivity, isNaturalDisplayOrientationPortrait); return orientation; } Loading
services/core/java/com/android/server/wm/AppCompatCameraPolicy.java +7 −11 Original line number Diff line number Diff line Loading @@ -28,7 +28,6 @@ import android.content.pm.ActivityInfo.ScreenOrientation; import android.content.res.Configuration; import android.view.Surface; import android.widget.Toast; import android.window.DesktopModeFlags; import com.android.internal.annotations.VisibleForTesting; Loading @@ -52,24 +51,21 @@ class AppCompatCameraPolicy { @NonNull DisplayContent displayContent) { // Not checking DeviceConfig value here to allow enabling via DeviceConfig // without the need to restart the device. final boolean needsDisplayRotationPolicy = wmService.mAppCompatConfiguration .isCameraCompatForceRotateTreatmentEnabledAtBuildTime(); final boolean needsSimReqOrientationPolicy = DesktopModeFlags.ENABLE_CAMERA_COMPAT_SIMULATE_REQUESTED_ORIENTATION.isTrue() && DesktopModeHelper.canEnterDesktopMode(wmService.mContext) && wmService.mAppCompatConfiguration .isCameraCompatSimulateRequestedOrientationTreatmentEnabled(); if (needsDisplayRotationPolicy || needsSimReqOrientationPolicy) { final boolean isDisplayRotationPolicyEnabled = AppCompatCameraDisplayRotationPolicy .isPolicyEnabled(displayContent); final boolean isSimReqOrientationPolicyEnabled = AppCompatCameraSimReqOrientationPolicy .isPolicyEnabled(displayContent); if (isDisplayRotationPolicyEnabled || isSimReqOrientationPolicyEnabled) { final AppCompatCameraStateSource cameraStateListenerDelegate = new AppCompatCameraStateSource(); mCameraStateMonitor = new CameraStateMonitor(displayContent, wmService.mH, cameraStateListenerDelegate); mActivityRefresher = new ActivityRefresher(wmService, wmService.mH); mDisplayRotationPolicy = needsDisplayRotationPolicy mDisplayRotationPolicy = isDisplayRotationPolicyEnabled ? new AppCompatCameraDisplayRotationPolicy(displayContent, mCameraStateMonitor, cameraStateListenerDelegate, mActivityRefresher) : null; mSimReqOrientationPolicy = needsSimReqOrientationPolicy mSimReqOrientationPolicy = isSimReqOrientationPolicyEnabled ? new AppCompatCameraSimReqOrientationPolicy(displayContent, mCameraStateMonitor, cameraStateListenerDelegate, mActivityRefresher) : null; Loading
services/core/java/com/android/server/wm/AppCompatCameraSimReqOrientationPolicy.java +34 −11 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ import static android.app.CameraCompatTaskInfo.CAMERA_COMPAT_PORTRAIT_DEVICE_IN_ import static android.app.CameraCompatTaskInfo.CAMERA_COMPAT_PORTRAIT_DEVICE_IN_PORTRAIT; import static android.app.CameraCompatTaskInfo.CAMERA_COMPAT_UNSPECIFIED; import static android.app.WindowConfiguration.ROTATION_UNDEFINED; import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; import static android.app.WindowConfiguration.WINDOW_CONFIG_APP_BOUNDS; import static android.app.WindowConfiguration.WINDOW_CONFIG_DISPLAY_ROTATION; import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LOCKED; Loading @@ -43,6 +44,7 @@ import android.content.res.Configuration; import android.os.RemoteException; import android.util.Slog; import android.view.Surface; import android.window.DesktopModeFlags; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.protolog.ProtoLog; Loading @@ -62,7 +64,7 @@ final class AppCompatCameraSimReqOrientationPolicy implements AppCompatCameraSta private static final String TAG = TAG_WITH_CLASS_NAME ? "AppCompatCameraSROPolicy" : TAG_WM; @NonNull private final DisplayContent mDisplayContent; private final ActivityTaskManagerService mAtmService; @NonNull private final ActivityRefresher mActivityRefresher; @NonNull Loading @@ -85,7 +87,7 @@ final class AppCompatCameraSimReqOrientationPolicy implements AppCompatCameraSta @NonNull CameraStateMonitor cameraStateMonitor, @NonNull AppCompatCameraStateSource cameraStateNotifier, @NonNull ActivityRefresher activityRefresher) { mDisplayContent = displayContent; mAtmService = displayContent.mAtmService; mCameraStateMonitor = cameraStateMonitor; mCameraStateNotifier = cameraStateNotifier; mActivityRefresher = activityRefresher; Loading Loading @@ -117,6 +119,14 @@ final class AppCompatCameraSimReqOrientationPolicy implements AppCompatCameraSta return mCameraDisplayRotationProvider.getCameraDeviceRotation(); } static boolean isPolicyEnabled(@NonNull DisplayContent displayContent) { return DesktopModeFlags.ENABLE_CAMERA_COMPAT_SIMULATE_REQUESTED_ORIENTATION.isTrue() && (DesktopModeHelper.canEnterDesktopMode(displayContent.mWmService.mContext) || Flags.cameraCompatUnifyCameraPolicies()) && displayContent.mWmService.mAppCompatConfiguration .isCameraCompatSimulateRequestedOrientationTreatmentEnabled(); } // Refreshing only when configuration changes after applying camera compat treatment. @Override public boolean shouldRefreshActivity(@NonNull ActivityRecord activity, Loading Loading @@ -174,7 +184,7 @@ final class AppCompatCameraSimReqOrientationPolicy implements AppCompatCameraSta ProtoLog.v(WmProtoLogGroups.WM_DEBUG_STATES, "Display id=%d is notified that Camera %s is closed but activity is" + " still refreshing. Rescheduling an update.", mDisplayContent.mDisplayId, cameraId); topActivity.getDisplayContent().mDisplayId, cameraId); return false; } return true; Loading Loading @@ -234,7 +244,7 @@ final class AppCompatCameraSimReqOrientationPolicy implements AppCompatCameraSta Slog.w(TAG, "Insufficient app information. Cannot revert display rotation sandboxing."); return; } final CompatibilityInfo compatibilityInfo = mDisplayContent.mAtmService final CompatibilityInfo compatibilityInfo = mAtmService .compatibilityInfoForPackageLocked(app.mInfo); // CompatibilityInfo fields are static, so even if task or activity has been closed, this // state should be updated. Loading Loading @@ -341,13 +351,18 @@ final class AppCompatCameraSimReqOrientationPolicy implements AppCompatCameraSta boolean isCameraRunningAndWindowingModeEligible(@NonNull ActivityRecord activity) { return activity.mAppCompatController.getCameraOverrides() .shouldApplyCameraCompatSimReqOrientationTreatment() // Do not apply camera compat treatment when an app is running on a candybar // display. && activity.getDisplayContent().getIgnoreOrientationRequest() && isWindowingModeEligible(activity) && mCameraStateMonitor.isCameraRunningForActivity(activity); } private boolean isWindowingModeEligible(@NonNull ActivityRecord activity) { // TODO(b/432218134): consider all windowing modes, e.g. WINDOWING_MODE_PINNED. return activity.inFreeformWindowingMode() || (Flags.cameraCompatUnifyCameraPolicies() && activity.inMultiWindowMode()); || (Flags.cameraCompatUnifyCameraPolicies() && (activity.inMultiWindowMode() || activity.getWindowingMode() == WINDOWING_MODE_FULLSCREEN)); } boolean shouldCameraCompatControlAspectRatio(@NonNull ActivityRecord activity) { Loading Loading @@ -426,18 +441,26 @@ final class AppCompatCameraSimReqOrientationPolicy implements AppCompatCameraSta @VisibleForTesting boolean isTreatmentEnabledForActivity(@NonNull ActivityRecord activity, boolean checkOrientation) { int orientation = activity.getRequestedConfigurationOrientation(); return activity.mAppCompatController.getCameraOverrides() .shouldApplyCameraCompatSimReqOrientationTreatment() // Do not apply camera compat treatment when an app is running on a candybar // display. && activity.getDisplayContent().getIgnoreOrientationRequest() && mCameraStateMonitor.isCameraRunningForActivity(activity) && (!checkOrientation || orientation != ORIENTATION_UNDEFINED) && activity.inFreeformWindowingMode() && isOrientationEligibleForTreatment(activity, checkOrientation) && isWindowingModeEligible(activity) // TODO(b/332665280): investigate whether we can support activity embedding. && !activity.isEmbedded(); } private boolean isOrientationEligibleForTreatment(@NonNull ActivityRecord activity, boolean checkOrientation) { final int orientation = activity.getRequestedConfigurationOrientation(); return (!checkOrientation || orientation != ORIENTATION_UNDEFINED) // "locked" and "nosensor" values are often used by camera apps that can't // handle dynamic changes so we shouldn't force-letterbox them. && activity.getRequestedOrientation() != SCREEN_ORIENTATION_NOSENSOR && activity.getRequestedOrientation() != SCREEN_ORIENTATION_LOCKED // TODO(b/332665280): investigate whether we can support activity embedding. && !activity.isEmbedded(); && activity.getRequestedOrientation() != SCREEN_ORIENTATION_LOCKED; } @Nullable Loading
services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java +20 −15 Original line number Diff line number Diff line Loading @@ -732,6 +732,24 @@ public class ActivityRecordTests extends WindowTestsBase { @DisableFlags(Flags.FLAG_ENABLE_CAMERA_COMPAT_FOR_DESKTOP_WINDOWING_OPT_OUT) @EnableCompatChanges({OVERRIDE_CAMERA_COMPAT_ENABLE_FREEFORM_WINDOWING_TREATMENT}) public void testOrientation_allowFixedOrientationForCameraCompatInFreeformWindowing() { doReturn(true).when(() -> DesktopModeHelper.canEnterDesktopMode(any())); final ActivityRecord activity = setupDisplayAndActivityForCameraCompat( /* isCameraRunning= */ true, WINDOWING_MODE_FREEFORM); // Task in landscape. assertEquals(ORIENTATION_LANDSCAPE, activity.getTask().getConfiguration().orientation); // The app should be letterboxed. assertEquals(ORIENTATION_PORTRAIT, activity.getConfiguration().orientation); assertTrue(activity.mAppCompatController.getAspectRatioPolicy() .isLetterboxedForFixedOrientationAndAspectRatio()); } @Test @EnableFlags({Flags.FLAG_ENABLE_CAMERA_COMPAT_FOR_DESKTOP_WINDOWING, Flags.FLAG_CAMERA_COMPAT_UNIFY_CAMERA_POLICIES, Flags.FLAG_ENABLE_CAMERA_COMPAT_FOR_DESKTOP_WINDOWING_OPT_OUT}) @EnableCompatChanges({OVERRIDE_CAMERA_COMPAT_ENABLE_FREEFORM_WINDOWING_TREATMENT}) public void testOrientation_allowFixedOrientationForCameraCompatWhenEnabledForAll() { final ActivityRecord activity = setupDisplayAndActivityForCameraCompat( /* isCameraRunning= */ true, WINDOWING_MODE_FREEFORM); Loading Loading @@ -789,21 +807,6 @@ public class ActivityRecordTests extends WindowTestsBase { .isLetterboxedForFixedOrientationAndAspectRatio()); } @Test @EnableFlags(Flags.FLAG_ENABLE_CAMERA_COMPAT_FOR_DESKTOP_WINDOWING) @EnableCompatChanges({OVERRIDE_CAMERA_COMPAT_ENABLE_FREEFORM_WINDOWING_TREATMENT}) public void testOrientation_dontAllowFixedOrientationForCameraCompatFreeformIfInPip() { final ActivityRecord activity = setupDisplayAndActivityForCameraCompat( /* isCameraRunning= */ true, WINDOWING_MODE_PINNED); // Task in landscape. assertEquals(ORIENTATION_LANDSCAPE, activity.getTask().getConfiguration().orientation); // Activity is not letterboxed. assertEquals(ORIENTATION_LANDSCAPE, activity.getConfiguration().orientation); assertFalse(activity.mAppCompatController.getAspectRatioPolicy() .isLetterboxedForFixedOrientationAndAspectRatio()); } @Test public void testShouldMakeActive_deferredResume() { final ActivityRecord activity = createActivityWithTask(); Loading Loading @@ -3631,6 +3634,7 @@ public class ActivityRecordTests extends WindowTestsBase { // Create a new DisplayContent so that the flag values create the camera freeform policy. mDisplayContent = new TestDisplayContent.Builder(mAtm, mDisplayContent.getSurfaceWidth(), mDisplayContent.getSurfaceHeight()).build(); mDisplayContent.setIgnoreOrientationRequest(true); final CameraStateMonitor cameraStateMonitor = mDisplayContent.mAppCompatCameraPolicy .mCameraStateMonitor; spyOn(cameraStateMonitor); Loading @@ -3646,6 +3650,7 @@ public class ActivityRecordTests extends WindowTestsBase { final ActivityRecord activity = new ActivityBuilder(mAtm) .setComponent(ComponentName.createRelative(mContext, com.android.server.wm.ActivityRecordTests.class.getName())) .setTask(rootTask) .setParentTask(rootTask) .setCreateTask(true) .setOnTop(true) Loading
services/tests/wmtests/src/com/android/server/wm/AppCompatCameraPolicyTest.java +14 −0 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ import static android.content.pm.ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_ONLY_FOR import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; import static com.android.server.wm.AppCompatCameraPolicy.isTreatmentEnabledForActivity; import static com.android.server.wm.AppCompatCameraPolicy.shouldOverrideMinAspectRatioForCamera; import static com.android.window.flags.Flags.FLAG_CAMERA_COMPAT_UNIFY_CAMERA_POLICIES; import static com.android.window.flags.Flags.FLAG_ENABLE_CAMERA_COMPAT_FOR_DESKTOP_WINDOWING; import static org.junit.Assert.assertEquals; Loading Loading @@ -124,6 +125,19 @@ public class AppCompatCameraPolicyTest extends WindowTestsBase { }); } @Test @EnableFlags({FLAG_ENABLE_CAMERA_COMPAT_FOR_DESKTOP_WINDOWING, FLAG_CAMERA_COMPAT_UNIFY_CAMERA_POLICIES}) public void testSimReqOrientationPolicy_unifyCameraPoliciesAndAllowedViaConfig_present() { runTestScenario((robot) -> { robot.dw().allowEnterDesktopMode(/* isAllowed= */ false); robot.conf().enableCameraCompatSimulateRequestedOrientationTreatment( /* enabled= */ true); robot.activity().createActivityWithComponentInNewTaskAndDisplay(); robot.checkTopActivityHasSimReqOrientationPolicy(/* exists= */ true); }); } @Test @EnableFlags(FLAG_ENABLE_CAMERA_COMPAT_FOR_DESKTOP_WINDOWING) public void testSimReqOrientationPolicy_startedWhenEnabledAndDW() { Loading