From b4c299fa3454f875580f456462b8060276826260 Mon Sep 17 00:00:00 2001 From: Iris Yang Date: Wed, 24 Aug 2022 13:18:44 +0800 Subject: [PATCH] Show a warning toast when PiP is blocked in the streamed display Add an API in DWPC to monitor the Pip is allowed in the streamed display by policy controller. If not allowed, pop up a warning toast for user. Bug: 229837382 Test: manually, atest WmTests:ActivityRecordTests Change-Id: Id1f39e8b54cd9c388c49b3886b9e798144ba5bf1 --- .../window/DisplayWindowPolicyController.java | 10 ++++++++ core/res/res/values/strings.xml | 2 ++ core/res/res/values/symbols.xml | 1 + .../GenericWindowPolicyController.java | 23 +++++++++++++++++++ .../companion/virtual/VirtualDeviceImpl.java | 6 +++++ .../com/android/server/wm/ActivityRecord.java | 4 ++-- .../DisplayWindowPolicyControllerHelper.java | 11 +++++++++ .../audio/VirtualAudioControllerTest.java | 1 + .../server/wm/ActivityRecordTests.java | 3 +-- .../DisplayWindowPolicyControllerTests.java | 5 ++++ 10 files changed, 62 insertions(+), 4 deletions(-) diff --git a/core/java/android/window/DisplayWindowPolicyController.java b/core/java/android/window/DisplayWindowPolicyController.java index a5aefd5157ce6..f55932eb05fd8 100644 --- a/core/java/android/window/DisplayWindowPolicyController.java +++ b/core/java/android/window/DisplayWindowPolicyController.java @@ -16,6 +16,8 @@ package android.window; +import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; + import android.annotation.NonNull; import android.app.WindowConfiguration; import android.content.ComponentName; @@ -142,6 +144,14 @@ public abstract class DisplayWindowPolicyController { */ public void onRunningAppsChanged(ArraySet runningUids) {} + /** + * This is called when an Activity is entering PIP. + * Returns {@code true} if the Activity is allowed to enter PIP. + */ + public boolean isEnteringPipAllowed(int uid) { + return isWindowingModeSupported(WINDOWING_MODE_PINNED); + } + /** Dump debug data */ public void dump(String prefix, final PrintWriter pw) { pw.println(prefix + "DisplayWindowPolicyController{" + super.toString() + "}"); diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index 9b060593651f9..4a9b69f469ed5 100644 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -6345,6 +6345,8 @@ ul. Can’t access the tablet’s camera from your %1$s This can’t be accessed while streaming. Try on your phone instead. + + Can’t view picture-in-picture while streaming System default diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index c3d40889636d3..9c23efe0a9837 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -4857,6 +4857,7 @@ + diff --git a/services/companion/java/com/android/server/companion/virtual/GenericWindowPolicyController.java b/services/companion/java/com/android/server/companion/virtual/GenericWindowPolicyController.java index fc628cfdced27..b5a35b7ae99cc 100644 --- a/services/companion/java/com/android/server/companion/virtual/GenericWindowPolicyController.java +++ b/services/companion/java/com/android/server/companion/virtual/GenericWindowPolicyController.java @@ -84,6 +84,15 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController void onSecureWindowShown(int displayId, int uid); } + /** + * For communicating when activities are blocked from entering PIP on the display by this + * policy controller. + */ + public interface PipBlockedCallback { + /** Called when an activity is blocked from entering PIP. */ + void onEnteringPipBlocked(int uid); + } + /** * If required, allow the secure activity to display on remote device since * {@link android.os.Build.VERSION_CODES#TIRAMISU}. @@ -111,6 +120,7 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController @GuardedBy("mGenericWindowPolicyControllerLock") final ArraySet mRunningUids = new ArraySet<>(); @Nullable private final ActivityListener mActivityListener; + @Nullable private final PipBlockedCallback mPipBlockedCallback; private final Handler mHandler = new Handler(Looper.getMainLooper()); private final ArraySet mRunningAppsChangedListener = new ArraySet<>(); @@ -152,6 +162,7 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController @NonNull Set blockedActivities, @ActivityPolicy int defaultActivityPolicy, @NonNull ActivityListener activityListener, + @NonNull PipBlockedCallback pipBlockedCallback, @NonNull ActivityBlockedCallback activityBlockedCallback, @NonNull SecureWindowCallback secureWindowCallback, @AssociationRequest.DeviceProfile String deviceProfile) { @@ -166,6 +177,7 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController setInterestedWindowFlags(windowFlags, systemWindowFlags); mActivityListener = activityListener; mDeviceProfile = deviceProfile; + mPipBlockedCallback = pipBlockedCallback; mSecureWindowCallback = secureWindowCallback; } @@ -306,6 +318,17 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController } } + @Override + public boolean isEnteringPipAllowed(int uid) { + if (super.isEnteringPipAllowed(uid)) { + return true; + } + mHandler.post(() -> { + mPipBlockedCallback.onEnteringPipBlocked(uid); + }); + return false; + } + /** * Returns true if an app with the given UID has an activity running on the virtual display for * this controller. diff --git a/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java b/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java index 4204162f3d988..02f5d74ae4354 100644 --- a/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java +++ b/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java @@ -579,6 +579,7 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub mParams.getBlockedActivities(), mParams.getDefaultActivityPolicy(), createListenerAdapter(), + this::onEnteringPipBlocked, this::onActivityBlocked, this::onSecureWindowShown, mAssociationInfo.getDeviceProfile()); @@ -734,6 +735,11 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub return mVirtualDisplayIds.contains(displayId); } + void onEnteringPipBlocked(int uid) { + showToastWhereUidIsRunning(uid, com.android.internal.R.string.vdm_pip_blocked, + Toast.LENGTH_LONG, mContext.getMainLooper()); + } + interface OnDeviceCloseListener { void onClose(int associationId); } diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index d8d75ed9790fa..a64e55b3e033c 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -3139,8 +3139,8 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A } // Check to see if PiP is supported for the display this container is on. - if (mDisplayContent != null && !mDisplayContent.mDwpcHelper.isWindowingModeSupported( - WINDOWING_MODE_PINNED)) { + if (mDisplayContent != null && !mDisplayContent.mDwpcHelper.isEnteringPipAllowed( + getUid())) { Slog.w(TAG, "Display " + mDisplayContent.getDisplayId() + " doesn't support enter picture-in-picture mode. caller = " + caller); return false; diff --git a/services/core/java/com/android/server/wm/DisplayWindowPolicyControllerHelper.java b/services/core/java/com/android/server/wm/DisplayWindowPolicyControllerHelper.java index 5d4904264056a..6f821b55e54a4 100644 --- a/services/core/java/com/android/server/wm/DisplayWindowPolicyControllerHelper.java +++ b/services/core/java/com/android/server/wm/DisplayWindowPolicyControllerHelper.java @@ -162,6 +162,17 @@ class DisplayWindowPolicyControllerHelper { return mDisplayWindowPolicyController.canShowTasksInRecents(); } + /** + * @see DisplayWindowPolicyController#isEnteringPipAllowed(int) + */ + public final boolean isEnteringPipAllowed(int uid) { + if (mDisplayWindowPolicyController == null) { + return true; + } + return mDisplayWindowPolicyController.isEnteringPipAllowed(uid); + } + + void dump(String prefix, PrintWriter pw) { if (mDisplayWindowPolicyController != null) { pw.println(); diff --git a/services/tests/servicestests/src/com/android/server/companion/virtual/audio/VirtualAudioControllerTest.java b/services/tests/servicestests/src/com/android/server/companion/virtual/audio/VirtualAudioControllerTest.java index 4c939f0779402..0262f564911b6 100644 --- a/services/tests/servicestests/src/com/android/server/companion/virtual/audio/VirtualAudioControllerTest.java +++ b/services/tests/servicestests/src/com/android/server/companion/virtual/audio/VirtualAudioControllerTest.java @@ -82,6 +82,7 @@ public class VirtualAudioControllerTest { /* blockedActivities= */ new ArraySet<>(), VirtualDeviceParams.ACTIVITY_POLICY_DEFAULT_ALLOWED, /* activityListener= */ null, + /* pipBlockedCallback= */ null, /* activityBlockedCallback= */ null, /* secureWindowCallback= */ null, /* deviceProfile= */ DEVICE_PROFILE_APP_STREAMING); 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 333be7bd8c611..a58cb4adc4d31 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java @@ -2284,8 +2284,7 @@ public class ActivityRecordTests extends WindowTestsBase { doReturn(false).when(mAtm).shouldDisableNonVrUiLocked(); spyOn(mDisplayContent.mDwpcHelper); - doReturn(false).when(mDisplayContent.mDwpcHelper).isWindowingModeSupported( - WINDOWING_MODE_PINNED); + doReturn(false).when(mDisplayContent.mDwpcHelper).isEnteringPipAllowed(anyInt()); assertFalse(activity.checkEnterPictureInPictureState("TEST", false /* beforeStopping */)); } diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayWindowPolicyControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayWindowPolicyControllerTests.java index 21197baaf8cc5..db1d15a4584af 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayWindowPolicyControllerTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayWindowPolicyControllerTests.java @@ -246,5 +246,10 @@ public class DisplayWindowPolicyControllerTests extends WindowTestsBase { public boolean canShowTasksInRecents() { return true; } + + @Override + public boolean isEnteringPipAllowed(int uid) { + return true; + } } }