From 2c2516afc79d34a1b91c5c250faea69ef712f52e Mon Sep 17 00:00:00 2001 From: Iris Yang Date: Tue, 15 Mar 2022 08:33:51 +0000 Subject: [PATCH] Check whether a display supported pip when an activity try to enter pip ActivityRecord#supportsPictureInPicture() will also be called when an activity sets PictureInPictureParams, this cause an issue if an activity is trying to set pip params but it doesn't enter pip. We should only block an activity enter pip on specified display instead of telling caller that the Activity doesn't support pip. Bug: 224699616 Test: manually, atest WmTests:ActivityRecordTests Change-Id: Id8eb421ebab57e6c022650f3e820175531a2e8fc --- .../com/android/server/wm/ActivityRecord.java | 12 +++++-- .../server/wm/ActivityRecordTests.java | 34 ++++++++++++------- 2 files changed, 31 insertions(+), 15 deletions(-) diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index bfe1f30f671ad..5239acebc7afa 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -2915,9 +2915,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A */ boolean supportsPictureInPicture() { return mAtmService.mSupportsPictureInPicture && isActivityTypeStandardOrUndefined() - && info.supportsPictureInPicture() - && (mDisplayContent != null && mDisplayContent.mDwpcHelper.isWindowingModeSupported( - WINDOWING_MODE_PINNED)); + && info.supportsPictureInPicture(); } /** @@ -3015,6 +3013,14 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A return false; } + // Check to see if PiP is supported for the display this container is on. + if (mDisplayContent != null && !mDisplayContent.mDwpcHelper.isWindowingModeSupported( + WINDOWING_MODE_PINNED)) { + Slog.w(TAG, "Display " + mDisplayContent.getDisplayId() + + " doesn't support enter picture-in-picture mode. caller = " + caller); + return false; + } + boolean isCurrentAppLocked = mAtmService.getLockTaskModeState() != LOCK_TASK_MODE_NONE; final TaskDisplayArea taskDisplayArea = getDisplayArea(); diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java index f8e15041f8f40..f9d4dffd4643d 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java @@ -16,6 +16,8 @@ package com.android.server.wm; +import static android.app.AppOpsManager.MODE_ALLOWED; +import static android.app.AppOpsManager.OP_PICTURE_IN_PICTURE; import static android.app.TaskInfo.CAMERA_COMPAT_CONTROL_DISMISSED; import static android.app.TaskInfo.CAMERA_COMPAT_CONTROL_HIDDEN; import static android.app.TaskInfo.CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED; @@ -110,6 +112,7 @@ import static org.mockito.Mockito.clearInvocations; import static org.mockito.Mockito.never; import android.app.ActivityOptions; +import android.app.AppOpsManager; import android.app.ICompatCameraControlCallback; import android.app.PictureInPictureParams; import android.app.servertransaction.ActivityConfigurationChangeItem; @@ -2184,17 +2187,11 @@ public class ActivityRecordTests extends WindowTestsBase { @Test public void testSupportsPictureInPicture() { - final Task task = new TaskBuilder(mSupervisor) - .setDisplay(mDisplayContent).build(); final ActivityRecord activity = new ActivityBuilder(mAtm) - .setTask(task) + .setCreateTask(true) .setResizeMode(ActivityInfo.RESIZE_MODE_UNRESIZEABLE) .setActivityFlags(FLAG_SUPPORTS_PICTURE_IN_PICTURE) .build(); - spyOn(mDisplayContent); - spyOn(mDisplayContent.mDwpcHelper); - doReturn(true).when(mDisplayContent.mDwpcHelper).isWindowingModeSupported( - WINDOWING_MODE_PINNED); // Device not supports PIP mAtm.mSupportsPictureInPicture = false; @@ -2207,15 +2204,28 @@ public class ActivityRecordTests extends WindowTestsBase { // Activity not supports PIP activity.info.flags &= ~FLAG_SUPPORTS_PICTURE_IN_PICTURE; assertFalse(activity.supportsPictureInPicture()); + } - // Activity supports PIP - activity.info.flags |= FLAG_SUPPORTS_PICTURE_IN_PICTURE; - assertTrue(activity.supportsPictureInPicture()); + @Test + public void testCheckEnterPictureInPictureState_displayNotSupportedPip() { + final Task task = new TaskBuilder(mSupervisor) + .setDisplay(mDisplayContent).build(); + final ActivityRecord activity = new ActivityBuilder(mAtm) + .setTask(task) + .setResizeMode(ActivityInfo.RESIZE_MODE_UNRESIZEABLE) + .setActivityFlags(FLAG_SUPPORTS_PICTURE_IN_PICTURE) + .build(); + mAtm.mSupportsPictureInPicture = true; + AppOpsManager appOpsManager = mAtm.getAppOpsManager(); + doReturn(MODE_ALLOWED).when(appOpsManager).checkOpNoThrow(eq(OP_PICTURE_IN_PICTURE), + anyInt(), any()); + doReturn(false).when(mAtm).shouldDisableNonVrUiLocked(); - // Display not supports PIP + spyOn(mDisplayContent.mDwpcHelper); doReturn(false).when(mDisplayContent.mDwpcHelper).isWindowingModeSupported( WINDOWING_MODE_PINNED); - assertFalse(activity.supportsPictureInPicture()); + + assertFalse(activity.checkEnterPictureInPictureState("TEST", false /* beforeStopping */)); } @Test