Add #onPictureInPictureRequested to Activity and ATM
Allows vendors to signal that an activity should enter
picture-in-picture if possible.
Additionally, removes the need for an Activity to go
through onPause to enter picture-in-picture. Apps can
now override this new API and enter PIP from there
instead of relying on #onUserLeaveHint.
Bug: 143365086
Test: atest FrameworksCoreTests:android.app.activity.ActivityThreadTest
Test: atest CtsWindowManagerDeviceTestCases:PinnedStackTests
Test: atest WmTests:ActivityTaskManagerServiceTests
Change-Id: Ib7ae9d1a7055ceed73e9643982033de9d4ad7350
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 45b4818..3c5dd6c 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -156,6 +156,8 @@
import android.app.admin.DevicePolicyCache;
import android.app.assist.AssistContent;
import android.app.assist.AssistStructure;
+import android.app.servertransaction.ClientTransaction;
+import android.app.servertransaction.EnterPipRequestedItem;
import android.app.usage.UsageStatsManagerInternal;
import android.content.ActivityNotFoundException;
import android.content.ComponentName;
@@ -4941,6 +4943,44 @@
}
}
+ /**
+ * Requests that an activity should enter picture-in-picture mode if possible.
+ */
+ @Override
+ public void requestPictureInPictureMode(IBinder token) throws RemoteException {
+ mAmInternal.enforceCallingPermission(Manifest.permission.MANAGE_ACTIVITY_STACKS,
+ "requestPictureInPictureMode");
+ final long origId = Binder.clearCallingIdentity();
+ try {
+ synchronized (mGlobalLock) {
+ final ActivityRecord activity = ActivityRecord.forTokenLocked(token);
+ if (activity == null) {
+ return;
+ }
+
+ final boolean canEnterPictureInPicture = activity.checkEnterPictureInPictureState(
+ "requestPictureInPictureMode", /* beforeStopping */ false);
+ if (!canEnterPictureInPicture) {
+ throw new IllegalStateException(
+ "Requested PIP on an activity that doesn't support it");
+ }
+
+ try {
+ final ClientTransaction transaction = ClientTransaction.obtain(
+ activity.app.getThread(),
+ activity.token);
+ transaction.addCallback(EnterPipRequestedItem.obtain());
+ getLifecycleManager().scheduleTransaction(transaction);
+ } catch (Exception e) {
+ Slog.w(TAG, "Failed to send enter pip requested item: "
+ + activity.intent.getComponent(), e);
+ }
+ }
+ } finally {
+ Binder.restoreCallingIdentity(origId);
+ }
+ }
+
void dumpLastANRLocked(PrintWriter pw) {
pw.println("ACTIVITY MANAGER LAST ANR (dumpsys activity lastanr)");
if (mLastANRState == null) {