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

Commit 9f86389c authored by jorgegil@google.com's avatar jorgegil@google.com
Browse files

Add tests to verify last pip component name updates

Bug: 169373982
Test: atest com.android.wm.shell.pip
Change-Id: I49df43b9462c50f1beef774a14583afda9d8cf3b
parent 9bc88aad
Loading
Loading
Loading
Loading
+26 −22
Original line number Diff line number Diff line
@@ -29,7 +29,6 @@ import android.content.Context;
import android.content.pm.ActivityInfo;
import android.content.pm.ParceledListSlice;
import android.graphics.Rect;
import android.os.Handler;
import android.os.RemoteException;
import android.os.UserHandle;
import android.os.UserManager;
@@ -45,6 +44,7 @@ import com.android.wm.shell.WindowManagerShellWrapper;
import com.android.wm.shell.common.DisplayChangeController;
import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.DisplayLayout;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.pip.PinnedStackListenerForwarder;
import com.android.wm.shell.pip.Pip;
import com.android.wm.shell.pip.PipBoundsHandler;
@@ -61,7 +61,7 @@ public class PipController implements Pip, PipTaskOrganizer.PipTransitionCallbac
    private static final String TAG = "PipController";

    private Context mContext;
    private Handler mHandler = new Handler();
    private ShellExecutor mMainExecutor;

    private final DisplayInfo mTmpDisplayInfo = new DisplayInfo();
    private final Rect mTmpInsetBounds = new Rect();
@@ -81,6 +81,8 @@ public class PipController implements Pip, PipTaskOrganizer.PipTransitionCallbac

    protected PipMenuActivityController mMenuController;
    protected PipTaskOrganizer mPipTaskOrganizer;
    protected PinnedStackListenerForwarder.PinnedStackListener mPinnedStackListener =
            new PipControllerPinnedStackListener();

    /**
     * Handler for display rotation changes.
@@ -149,12 +151,12 @@ public class PipController implements Pip, PipTaskOrganizer.PipTransitionCallbac
            PinnedStackListenerForwarder.PinnedStackListener {
        @Override
        public void onListenerRegistered(IPinnedStackController controller) {
            mHandler.post(() -> mTouchHandler.setPinnedStackController(controller));
            mMainExecutor.execute(() -> mTouchHandler.setPinnedStackController(controller));
        }

        @Override
        public void onImeVisibilityChanged(boolean imeVisible, int imeHeight) {
            mHandler.post(() -> {
            mMainExecutor.execute(() -> {
                mPipBoundsHandler.onImeVisibilityChanged(imeVisible, imeHeight);
                mTouchHandler.onImeVisibilityChanged(imeVisible, imeHeight);
            });
@@ -162,19 +164,19 @@ public class PipController implements Pip, PipTaskOrganizer.PipTransitionCallbac

        @Override
        public void onMovementBoundsChanged(boolean fromImeAdjustment) {
            mHandler.post(() -> updateMovementBounds(null /* toBounds */,
            mMainExecutor.execute(() -> updateMovementBounds(null /* toBounds */,
                    false /* fromRotation */, fromImeAdjustment, false /* fromShelfAdjustment */,
                    null /* windowContainerTransaction */));
        }

        @Override
        public void onActionsChanged(ParceledListSlice<RemoteAction> actions) {
            mHandler.post(() -> mMenuController.setAppActions(actions));
            mMainExecutor.execute(() -> mMenuController.setAppActions(actions));
        }

        @Override
        public void onActivityHidden(ComponentName componentName) {
            mHandler.post(() -> {
            mMainExecutor.execute(() -> {
                if (componentName.equals(mPipBoundsState.getLastPipComponentName())) {
                    // The activity was removed, we don't want to restore to the reentry state
                    // saved for this component anymore.
@@ -185,12 +187,12 @@ public class PipController implements Pip, PipTaskOrganizer.PipTransitionCallbac

        @Override
        public void onDisplayInfoChanged(DisplayInfo displayInfo) {
            mHandler.post(() -> mPipBoundsState.setDisplayInfo(displayInfo));
            mMainExecutor.execute(() -> mPipBoundsState.setDisplayInfo(displayInfo));
        }

        @Override
        public void onConfigurationChanged() {
            mHandler.post(() -> {
            mMainExecutor.execute(() -> {
                mPipBoundsHandler.onConfigurationChanged(mContext);
                mTouchHandler.onConfigurationChanged();
            });
@@ -200,7 +202,7 @@ public class PipController implements Pip, PipTaskOrganizer.PipTransitionCallbac
        public void onAspectRatioChanged(float aspectRatio) {
            // TODO(b/169373982): Remove this callback as it is redundant with PipTaskOrg params
            // change.
            mHandler.post(() -> {
            mMainExecutor.execute(() -> {
                mPipBoundsState.setAspectRatio(aspectRatio);
                mTouchHandler.onAspectRatioChanged();
            });
@@ -216,7 +218,8 @@ public class PipController implements Pip, PipTaskOrganizer.PipTransitionCallbac
            PipMenuActivityController pipMenuActivityController,
            PipTaskOrganizer pipTaskOrganizer,
            PipTouchHandler pipTouchHandler,
            WindowManagerShellWrapper windowManagerShellWrapper
            WindowManagerShellWrapper windowManagerShellWrapper,
            ShellExecutor mainExecutor
    ) {
        // Ensure that we are the primary user's SystemUI.
        final int processUser = UserManager.get(context).getUserHandle();
@@ -230,6 +233,7 @@ public class PipController implements Pip, PipTaskOrganizer.PipTransitionCallbac
        mPipBoundsHandler = pipBoundsHandler;
        mPipBoundsState = pipBoundsState;
        mPipTaskOrganizer = pipTaskOrganizer;
        mMainExecutor = mainExecutor;
        mPipTaskOrganizer.registerPipTransitionCallback(this);
        mPipTaskOrganizer.registerOnDisplayIdChangeCallback((int displayId) -> {
            final DisplayInfo newDisplayInfo = new DisplayInfo();
@@ -253,8 +257,7 @@ public class PipController implements Pip, PipTaskOrganizer.PipTransitionCallbac
        mPipBoundsState.setDisplayInfo(displayInfo);

        try {
            mWindowManagerShellWrapper.addPinnedStackListener(
                    new PipControllerPinnedStackListener());
            mWindowManagerShellWrapper.addPinnedStackListener(mPinnedStackListener);
        } catch (RemoteException e) {
            Slog.e(TAG, "Failed to register pinned stack listener", e);
        }
@@ -262,14 +265,14 @@ public class PipController implements Pip, PipTaskOrganizer.PipTransitionCallbac

    @Override
    public void onDensityOrFontScaleChanged() {
        mHandler.post(() -> {
        mMainExecutor.execute(() -> {
            mPipTaskOrganizer.onDensityOrFontScaleChanged(mContext);
        });
    }

    @Override
    public void onActivityPinned(String packageName) {
        mHandler.post(() -> {
        mMainExecutor.execute(() -> {
            mTouchHandler.onActivityPinned();
            mMediaController.onActivityPinned();
            mMenuController.onActivityPinned();
@@ -279,7 +282,7 @@ public class PipController implements Pip, PipTaskOrganizer.PipTransitionCallbac

    @Override
    public void onActivityUnpinned(ComponentName topActivity) {
        mHandler.post(() -> {
        mMainExecutor.execute(() -> {
            mMenuController.onActivityUnpinned();
            mTouchHandler.onActivityUnpinned(topActivity);
            mAppOpsListener.onActivityUnpinned();
@@ -298,7 +301,7 @@ public class PipController implements Pip, PipTaskOrganizer.PipTransitionCallbac

    @Override
    public void onOverlayChanged() {
        mHandler.post(() -> {
        mMainExecutor.execute(() -> {
            mPipBoundsState.setDisplayLayout(new DisplayLayout(mContext, mContext.getDisplay()));
            updateMovementBounds(null /* toBounds */,
                    false /* fromRotation */, false /* fromImeAdjustment */,
@@ -357,7 +360,7 @@ public class PipController implements Pip, PipTaskOrganizer.PipTransitionCallbac
     */
    @Override
    public void setShelfHeight(boolean visible, int height) {
        mHandler.post(() -> setShelfHeightLocked(visible, height));
        mMainExecutor.execute(() -> setShelfHeightLocked(visible, height));
    }

    private void setShelfHeightLocked(boolean visible, int height) {
@@ -373,12 +376,12 @@ public class PipController implements Pip, PipTaskOrganizer.PipTransitionCallbac

    @Override
    public void setPinnedStackAnimationType(int animationType) {
        mHandler.post(() -> mPipTaskOrganizer.setOneShotAnimationType(animationType));
        mMainExecutor.execute(() -> mPipTaskOrganizer.setOneShotAnimationType(animationType));
    }

    @Override
    public void setPinnedStackAnimationListener(Consumer<Boolean> callback) {
        mHandler.post(() -> mPinnedStackAnimationRecentsCallback = callback);
        mMainExecutor.execute(() -> mPinnedStackAnimationRecentsCallback = callback);
    }

    @Override
@@ -475,7 +478,8 @@ public class PipController implements Pip, PipTaskOrganizer.PipTransitionCallbac
            PipBoundsState pipBoundsState, PipMediaController pipMediaController,
            PipMenuActivityController pipMenuActivityController,
            PipTaskOrganizer pipTaskOrganizer, PipTouchHandler pipTouchHandler,
            WindowManagerShellWrapper windowManagerShellWrapper) {
            WindowManagerShellWrapper windowManagerShellWrapper,
            ShellExecutor mainExecutor) {
        if (!context.getPackageManager().hasSystemFeature(FEATURE_PICTURE_IN_PICTURE)) {
            Slog.w(TAG, "Device doesn't support Pip feature");
            return null;
@@ -483,6 +487,6 @@ public class PipController implements Pip, PipTaskOrganizer.PipTransitionCallbac

        return new PipController(context, displayController, pipAppOpsListener, pipBoundsHandler,
                pipBoundsState, pipMediaController, pipMenuActivityController,
                pipTaskOrganizer, pipTouchHandler, windowManagerShellWrapper);
                pipTaskOrganizer, pipTouchHandler, windowManagerShellWrapper, mainExecutor);
    }
}
+36 −4
Original line number Diff line number Diff line
@@ -69,11 +69,13 @@ public class PipTaskOrganizerTest extends PipTestCase {
    private PipBoundsState mPipBoundsState;

    private ComponentName mComponent1;
    private ComponentName mComponent2;

    @Before
    public void setUp() throws RemoteException {
        MockitoAnnotations.initMocks(this);
        mComponent1 = new ComponentName(mContext, "component1");
        mComponent2 = new ComponentName(mContext, "component2");
        mPipBoundsState = new PipBoundsState();
        mSpiedPipTaskOrganizer = spy(new PipTaskOrganizer(mContext, mPipBoundsState,
                mMockPipBoundsHandler, mMockPipSurfaceTransactionHelper, mMockOptionalSplitScreen,
@@ -100,30 +102,58 @@ public class PipTaskOrganizerTest extends PipTestCase {
        assertEquals(aspectRatio.floatValue(), mPipBoundsState.getAspectRatio(), 0.01f);
    }

    @Test
    public void startSwipePipToHome_updatesLastPipComponentName() {
        mSpiedPipTaskOrganizer.startSwipePipToHome(mComponent1, null, null);

        assertEquals(mComponent1, mPipBoundsState.getLastPipComponentName());
    }

    @Test
    public void onTaskAppeared_updatesAspectRatio() {
        final Rational aspectRatio = new Rational(2, 1);

        mSpiedPipTaskOrganizer.onTaskAppeared(createTaskInfo(
        mSpiedPipTaskOrganizer.onTaskAppeared(createTaskInfo(mComponent1,
                createPipParams(aspectRatio)), null /* leash */);

        assertEquals(aspectRatio.floatValue(), mPipBoundsState.getAspectRatio(), 0.01f);
    }

    @Test
    public void onTaskAppeared_updatesLastPipComponentName() {
        mSpiedPipTaskOrganizer.onTaskAppeared(createTaskInfo(mComponent1, createPipParams(null)),
                null /* leash */);

        assertEquals(mComponent1, mPipBoundsState.getLastPipComponentName());
    }

    @Test
    public void onTaskInfoChanged_updatesAspectRatioIfChanged() {
        final Rational startAspectRatio = new Rational(2, 1);
        final Rational newAspectRatio = new Rational(1, 2);
        mSpiedPipTaskOrganizer.onTaskAppeared(createTaskInfo(
        mSpiedPipTaskOrganizer.onTaskAppeared(createTaskInfo(mComponent1,
                createPipParams(startAspectRatio)), null /* leash */);

        mSpiedPipTaskOrganizer.onTaskInfoChanged(createTaskInfo(createPipParams(newAspectRatio)));
        mSpiedPipTaskOrganizer.onTaskInfoChanged(createTaskInfo(mComponent1,
                createPipParams(newAspectRatio)));

        assertEquals(newAspectRatio.floatValue(), mPipBoundsState.getAspectRatio(), 0.01f);
    }

    @Test
    public void onTaskInfoChanged_updatesLastPipComponentName() {
        mSpiedPipTaskOrganizer.onTaskAppeared(createTaskInfo(mComponent1,
                createPipParams(null)), null /* leash */);

        mSpiedPipTaskOrganizer.onTaskInfoChanged(createTaskInfo(mComponent2,
                createPipParams(null)));

        assertEquals(mComponent2, mPipBoundsState.getLastPipComponentName());
    }

    private void preparePipTaskOrg() {
        final DisplayInfo info = new DisplayInfo();
        mPipBoundsState.setDisplayInfo(info);
        when(mMockPipBoundsHandler.getDestinationBounds(any(), any())).thenReturn(new Rect());
        when(mMockPipBoundsHandler.getDestinationBounds(any(), any(), anyBoolean()))
                .thenReturn(new Rect());
@@ -133,10 +163,12 @@ public class PipTaskOrganizerTest extends PipTestCase {
        doNothing().when(mSpiedPipTaskOrganizer).scheduleAnimateResizePip(any(), anyInt(), any());
    }

    private static ActivityManager.RunningTaskInfo createTaskInfo(PictureInPictureParams params) {
    private static ActivityManager.RunningTaskInfo createTaskInfo(
            ComponentName componentName, PictureInPictureParams params) {
        final ActivityManager.RunningTaskInfo info = new ActivityManager.RunningTaskInfo();
        info.token = mock(WindowContainerToken.class);
        info.pictureInPictureParams = params;
        info.topActivity = componentName;
        return info;
    }

+32 −2
Original line number Diff line number Diff line
@@ -20,11 +20,14 @@ import static android.content.pm.PackageManager.FEATURE_PICTURE_IN_PICTURE;

import static org.junit.Assert.assertNull;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import android.content.ComponentName;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.RemoteException;
@@ -34,6 +37,7 @@ import android.testing.TestableLooper;

import com.android.wm.shell.WindowManagerShellWrapper;
import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.pip.PipBoundsHandler;
import com.android.wm.shell.pip.PipBoundsState;
import com.android.wm.shell.pip.PipTaskOrganizer;
@@ -63,6 +67,7 @@ public class PipControllerTest extends PipTestCase {
    @Mock private PipTouchHandler mMockPipTouchHandler;
    @Mock private WindowManagerShellWrapper mMockWindowManagerShellWrapper;
    @Mock private PipBoundsState mMockPipBoundsState;
    @Mock private ShellExecutor mMockExecutor;

    @Before
    public void setUp() throws RemoteException {
@@ -70,7 +75,11 @@ public class PipControllerTest extends PipTestCase {
        mPipController = new PipController(mContext, mMockDisplayController,
                mMockPipAppOpsListener, mMockPipBoundsHandler, mMockPipBoundsState,
                mMockPipMediaController, mMockPipMenuActivityController, mMockPipTaskOrganizer,
                mMockPipTouchHandler, mMockWindowManagerShellWrapper);
                mMockPipTouchHandler, mMockWindowManagerShellWrapper, mMockExecutor);
        doAnswer(invocation -> {
            ((Runnable) invocation.getArgument(0)).run();
            return null;
        }).when(mMockExecutor).execute(any());
    }

    @Test
@@ -98,6 +107,27 @@ public class PipControllerTest extends PipTestCase {
        assertNull(PipController.create(spyContext, mMockDisplayController,
                mMockPipAppOpsListener, mMockPipBoundsHandler, mMockPipBoundsState,
                mMockPipMediaController, mMockPipMenuActivityController, mMockPipTaskOrganizer,
                mMockPipTouchHandler, mMockWindowManagerShellWrapper));
                mMockPipTouchHandler, mMockWindowManagerShellWrapper, mMockExecutor));
    }

    @Test
    public void onActivityHidden_isLastPipComponentName_clearLastPipComponent() {
        final ComponentName component1 = new ComponentName(mContext, "component1");
        when(mMockPipBoundsState.getLastPipComponentName()).thenReturn(component1);

        mPipController.mPinnedStackListener.onActivityHidden(component1);

        verify(mMockPipBoundsState).setLastPipComponentName(null);
    }

    @Test
    public void onActivityHidden_isNotLastPipComponentName_lastPipComponentNotCleared() {
        final ComponentName component1 = new ComponentName(mContext, "component1");
        final ComponentName component2 = new ComponentName(mContext, "component2");
        when(mMockPipBoundsState.getLastPipComponentName()).thenReturn(component1);

        mPipController.mPinnedStackListener.onActivityHidden(component2);

        verify(mMockPipBoundsState, never()).setLastPipComponentName(null);
    }
}
+10 −2
Original line number Diff line number Diff line
@@ -34,6 +34,7 @@ import com.android.wm.shell.common.AnimationThread;
import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.DisplayImeController;
import com.android.wm.shell.common.HandlerExecutor;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.SyncTransactionQueue;
import com.android.wm.shell.common.SystemWindows;
import com.android.wm.shell.common.TransactionPool;
@@ -158,9 +159,9 @@ public abstract class WMShellBaseModule {
    @WMSingleton
    @Provides
    static ShellTaskOrganizer provideShellTaskOrganizer(SyncTransactionQueue syncQueue,
            @Main Handler handler, TransactionPool transactionPool) {
            ShellExecutor mainExecutor, TransactionPool transactionPool) {
        return new ShellTaskOrganizer(syncQueue, transactionPool,
                new HandlerExecutor(handler), AnimationThread.instance().getExecutor());
                mainExecutor, AnimationThread.instance().getExecutor());
    }

    @BindsOptionalOf
@@ -175,4 +176,11 @@ public abstract class WMShellBaseModule {
            DisplayController displayController) {
        return Optional.ofNullable(OneHandedController.create(context, displayController));
    }

    @WMSingleton
    @Provides
    static ShellExecutor provideMainShellExecutor(@Main Handler handler) {
        return new HandlerExecutor(handler);
    }

}
+4 −2
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@ import com.android.wm.shell.WindowManagerShellWrapper;
import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.DisplayImeController;
import com.android.wm.shell.common.FloatingContentCoordinator;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.SyncTransactionQueue;
import com.android.wm.shell.common.SystemWindows;
import com.android.wm.shell.common.TransactionPool;
@@ -82,11 +83,12 @@ public class WMShellModule {
            PipAppOpsListener pipAppOpsListener, PipBoundsHandler pipBoundsHandler,
            PipBoundsState pipBoundsState, PipMediaController pipMediaController,
            PipMenuActivityController pipMenuActivityController, PipTaskOrganizer pipTaskOrganizer,
            PipTouchHandler pipTouchHandler, WindowManagerShellWrapper windowManagerShellWrapper) {
            PipTouchHandler pipTouchHandler, WindowManagerShellWrapper windowManagerShellWrapper,
            ShellExecutor mainExecutor) {
        return Optional.ofNullable(PipController.create(context, displayController,
                pipAppOpsListener, pipBoundsHandler, pipBoundsState, pipMediaController,
                pipMenuActivityController, pipTaskOrganizer, pipTouchHandler,
                windowManagerShellWrapper));
                windowManagerShellWrapper, mainExecutor));
    }

    @WMSingleton