summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/res/res/values/symbols.xml2
-rw-r--r--services/core/java/com/android/server/wm/DisplayRotationCompatPolicy.java54
-rw-r--r--services/core/java/com/android/server/wm/ScreenRotationAnimation.java4
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/DisplayRotationCompatPolicyTests.java68
4 files changed, 127 insertions, 1 deletions
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..22367605d0a1 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()) {
@@ -334,7 +361,28 @@ 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) {
+ 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) {
@@ -396,6 +444,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/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()))