diff options
10 files changed, 62 insertions, 4 deletions
diff --git a/core/java/android/window/DisplayWindowPolicyController.java b/core/java/android/window/DisplayWindowPolicyController.java index a5aefd5157ce..f55932eb05fd 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<Integer> 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 48484c7d41f9..216975d2d2e6 100644 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -6331,6 +6331,8 @@ ul.</string> <string name="vdm_camera_access_denied" product="tablet">Can’t access the tablet’s camera from your <xliff:g id="device" example="Chromebook">%1$s</xliff:g></string> <!-- Error message indicating the user cannot access secure content when running on a virtual device. [CHAR LIMIT=NONE] --> <string name="vdm_secure_window">This can’t be accessed while streaming. Try on your phone instead.</string> + <!-- Error message indicating the user cannot view picture-in-picture when running on a virtual device. [CHAR LIMIT=NONE] --> + <string name="vdm_pip_blocked">Can’t view picture-in-picture while streaming</string> <!-- Title for preference of the system default locale. [CHAR LIMIT=50]--> <string name="system_locale_title">System default</string> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 375a2c01762c..5eb62919214c 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -4861,6 +4861,7 @@ <!-- For VirtualDeviceManager --> <java-symbol type="string" name="vdm_camera_access_denied" /> <java-symbol type="string" name="vdm_secure_window" /> + <java-symbol type="string" name="vdm_pip_blocked" /> <java-symbol type="color" name="camera_privacy_light_day"/> <java-symbol type="color" name="camera_privacy_light_night"/> 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 000bafe1d650..ce7854d7368a 100644 --- a/services/companion/java/com/android/server/companion/virtual/GenericWindowPolicyController.java +++ b/services/companion/java/com/android/server/companion/virtual/GenericWindowPolicyController.java @@ -86,6 +86,15 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController } /** + * 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}. */ @@ -112,6 +121,7 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController @GuardedBy("mGenericWindowPolicyControllerLock") final ArraySet<Integer> mRunningUids = new ArraySet<>(); @Nullable private final ActivityListener mActivityListener; + @Nullable private final PipBlockedCallback mPipBlockedCallback; private final Handler mHandler = new Handler(Looper.getMainLooper()); @NonNull @GuardedBy("mGenericWindowPolicyControllerLock") @@ -155,6 +165,7 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController @NonNull Set<ComponentName> blockedActivities, @ActivityPolicy int defaultActivityPolicy, @NonNull ActivityListener activityListener, + @NonNull PipBlockedCallback pipBlockedCallback, @NonNull ActivityBlockedCallback activityBlockedCallback, @NonNull SecureWindowCallback secureWindowCallback, @AssociationRequest.DeviceProfile String deviceProfile) { @@ -169,6 +180,7 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController setInterestedWindowFlags(windowFlags, systemWindowFlags); mActivityListener = activityListener; mDeviceProfile = deviceProfile; + mPipBlockedCallback = pipBlockedCallback; mSecureWindowCallback = secureWindowCallback; } @@ -317,6 +329,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 5ebbf07526f1..be2107529f8b 100644 --- a/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java +++ b/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java @@ -624,6 +624,7 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub mParams.getBlockedActivities(), mParams.getDefaultActivityPolicy(), createListenerAdapter(), + this::onEnteringPipBlocked, this::onActivityBlocked, this::onSecureWindowShown, mAssociationInfo.getDeviceProfile()); @@ -779,6 +780,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 e5401f509394..eba337594f26 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -3131,8 +3131,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 5d4904264056..6f821b55e54a 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 4c939f077940..0262f564911b 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 3a8e1ccce122..bd8da4e713b7 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 21197baaf8cc..db1d15a4584a 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; + } } } |