Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2a4a400e authored by Jorge Gil's avatar Jorge Gil Committed by Android (Google) Code Review
Browse files

Merge "Request enter PIP on WCT#setWindowingMode(PINNED)" into tm-qpr-dev

parents a74fee41 76def33f
Loading
Loading
Loading
Loading
+8 −6
Original line number Diff line number Diff line
@@ -841,22 +841,22 @@ class ActivityClientController extends IActivityClientController.Stub {
    /**
     * Requests that an activity should enter picture-in-picture mode if possible. This method may
     * be used by the implementation of non-phone form factors.
     *
     * @return false if the activity cannot enter PIP mode.
     */
    void requestPictureInPictureMode(@NonNull ActivityRecord r) {
    boolean requestPictureInPictureMode(@NonNull ActivityRecord r) {
        if (r.inPinnedWindowingMode()) {
            throw new IllegalStateException("Activity is already in PIP mode");
            return false;
        }

        final boolean canEnterPictureInPicture = r.checkEnterPictureInPictureState(
                "requestPictureInPictureMode", /* beforeStopping */ false);
        if (!canEnterPictureInPicture) {
            throw new IllegalStateException(
                    "Requested PIP on an activity that doesn't support it");
            return false;
        }

        if (r.pictureInPictureArgs.isAutoEnterEnabled()) {
            mService.enterPictureInPictureMode(r, r.pictureInPictureArgs);
            return;
            return mService.enterPictureInPictureMode(r, r.pictureInPictureArgs);
        }

        try {
@@ -864,9 +864,11 @@ class ActivityClientController extends IActivityClientController.Stub {
                    r.app.getThread(), r.token);
            transaction.addCallback(EnterPipRequestedItem.obtain());
            mService.getLifecycleManager().scheduleTransaction(transaction);
            return true;
        } catch (Exception e) {
            Slog.w(TAG, "Failed to send enter pip requested item: "
                    + r.intent.getComponent(), e);
            return false;
        }
    }

+29 −0
Original line number Diff line number Diff line
@@ -546,6 +546,13 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub
                        + " windowing mode during locked task mode.");
            }

            if (windowingMode == WindowConfiguration.WINDOWING_MODE_PINNED) {
                // Do not directly put the container into PINNED mode as it may not support it or
                // the app may not want to enter it. Instead, send a signal to request PIP
                // mode to the app if they wish to support it below in #applyTaskChanges.
                return effects;
            }

            final int prevMode = container.getWindowingMode();
            container.setWindowingMode(windowingMode);
            if (prevMode != container.getWindowingMode()) {
@@ -582,6 +589,28 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub
            tr.mDisplayContent.mPinnedTaskController.setEnterPipBounds(enterPipBounds);
        }

        if (c.getWindowingMode() == WindowConfiguration.WINDOWING_MODE_PINNED
                && !tr.inPinnedWindowingMode()) {
            final ActivityRecord activity = tr.getTopNonFinishingActivity();
            if (activity != null) {
                final boolean lastSupportsEnterPipOnTaskSwitch =
                        activity.supportsEnterPipOnTaskSwitch;
                // Temporarily force enable enter PIP on task switch so that PIP is requested
                // regardless of whether the activity is resumed or paused.
                activity.supportsEnterPipOnTaskSwitch = true;
                boolean canEnterPip = activity.checkEnterPictureInPictureState(
                        "applyTaskChanges", true /* beforeStopping */);
                if (canEnterPip) {
                    canEnterPip = mService.mActivityClientController
                            .requestPictureInPictureMode(activity);
                }
                if (!canEnterPip) {
                    // Restore the flag to its previous state when the activity cannot enter PIP.
                    activity.supportsEnterPipOnTaskSwitch = lastSupportsEnterPipOnTaskSwitch;
                }
            }
        }

        return effects;
    }

+17 −9
Original line number Diff line number Diff line
@@ -21,7 +21,6 @@ import static android.content.pm.ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
import static android.content.res.Configuration.ORIENTATION_PORTRAIT;

import static com.android.dx.mockito.inline.extended.ExtendedMockito.any;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
@@ -42,8 +41,8 @@ import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.atLeast;
import static org.mockito.Mockito.doCallRealMethod;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.when;

import android.annotation.Nullable;
@@ -60,7 +59,6 @@ import android.graphics.Rect;
import android.os.Binder;
import android.os.IBinder;
import android.os.LocaleList;
import android.os.PowerManager;
import android.os.RemoteException;
import android.platform.test.annotations.Presubmit;
import android.view.Display;
@@ -136,7 +134,7 @@ public class ActivityTaskManagerServiceTests extends WindowTestsBase {
        assertNull(transaction.getLifecycleStateRequest());
    }

    @Test(expected = IllegalStateException.class)
    @Test
    public void testOnPictureInPictureRequested_cannotEnterPip() throws RemoteException {
        final Task stack = new TaskBuilder(mSupervisor).setCreateActivity(true).build();
        final ActivityRecord activity = stack.getBottomMostTask().getTopNonFinishingActivity();
@@ -146,11 +144,16 @@ public class ActivityTaskManagerServiceTests extends WindowTestsBase {

        mAtm.mActivityClientController.requestPictureInPictureMode(activity);

        // Check enter no transactions with enter pip requests are made.
        verify(lifecycleManager, times(0)).scheduleTransaction(any());
        verify(lifecycleManager, atLeast(0))
                .scheduleTransaction(mClientTransactionCaptor.capture());
        final ClientTransaction transaction = mClientTransactionCaptor.getValue();
        // Check that none are enter pip request items.
        transaction.getCallbacks().forEach(clientTransactionItem -> {
            assertFalse(clientTransactionItem instanceof EnterPipRequestedItem);
        });
    }

    @Test(expected = IllegalStateException.class)
    @Test
    public void testOnPictureInPictureRequested_alreadyInPIPMode() throws RemoteException {
        final Task stack = new TaskBuilder(mSupervisor).setCreateActivity(true).build();
        final ActivityRecord activity = stack.getBottomMostTask().getTopNonFinishingActivity();
@@ -159,8 +162,13 @@ public class ActivityTaskManagerServiceTests extends WindowTestsBase {

        mAtm.mActivityClientController.requestPictureInPictureMode(activity);

        // Check that no transactions with enter pip requests are made.
        verify(lifecycleManager, times(0)).scheduleTransaction(any());
        verify(lifecycleManager, atLeast(0))
                .scheduleTransaction(mClientTransactionCaptor.capture());
        final ClientTransaction transaction = mClientTransactionCaptor.getValue();
        // Check that none are enter pip request items.
        transaction.getCallbacks().forEach(clientTransactionItem -> {
            assertFalse(clientTransactionItem instanceof EnterPipRequestedItem);
        });
    }

    @Test
+11 −2
Original line number Diff line number Diff line
@@ -522,7 +522,10 @@ public class WindowOrganizerTests extends WindowTestsBase {
        mWm.mAtmService.mWindowOrganizerController.applyTransaction(t);

        assertEquals(WINDOWING_MODE_FULLSCREEN, record.getWindowingMode());
        assertEquals(WINDOWING_MODE_PINNED, rootTask.getWindowingMode());
        // Get the root task from the PIP activity record again, since the PIP root task may have
        // changed when the activity entered PIP mode.
        final Task pipRootTask = record.getRootTask();
        assertEquals(WINDOWING_MODE_PINNED, pipRootTask.getWindowingMode());
    }

    @Test
@@ -1015,6 +1018,8 @@ public class WindowOrganizerTests extends WindowTestsBase {
        final ActivityRecord record = createActivityRecordWithParentTask(mDisplayContent,
                WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
        record.info.flags |= ActivityInfo.FLAG_SUPPORTS_PICTURE_IN_PICTURE;
        record.setPictureInPictureParams(new PictureInPictureParams.Builder()
                .setAutoEnterEnabled(true).build());
        spyOn(record);
        doReturn(true).when(record).checkEnterPictureInPictureState(any(), anyBoolean());

@@ -1499,7 +1504,11 @@ public class WindowOrganizerTests extends WindowTestsBase {
        verify(mWm.mAtmService.mRootWindowContainer).resumeFocusedTasksTopActivities();

        clearInvocations(mWm.mAtmService.mRootWindowContainer);
        t.setWindowingMode(wct, WINDOWING_MODE_FULLSCREEN);
        // The token for the PIP root task may have changed when the task entered PIP mode, so do
        // not reuse the one from above.
        final WindowContainerToken newToken =
                record.getRootTask().mRemoteToken.toWindowContainerToken();
        t.setWindowingMode(newToken, WINDOWING_MODE_FULLSCREEN);
        mWm.mAtmService.mWindowOrganizerController.applyTransaction(t);
        verify(mWm.mAtmService.mRootWindowContainer).resumeFocusedTasksTopActivities();
    }