[5/n] Camera Compat: Toasts explaining compat treatment
Add two toasts explaining compat treatment: - after the system rotates the screen for camera compatibility - when a camera view is started within the app that may not be able to display the camera preview correctly while in split screen. Fix: 255939392 Test: atest WmTests:DisplayRotationCompatPolicyTests Change-Id: I50d91601ac6e6fb90a626c5496aca60d454ff960
This commit is contained in:
@@ -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" />
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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(
|
||||
|
||||
Reference in New Issue
Block a user