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

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

Merge "Add tests to verify last pip component name updates"

parents f4896df8 9f86389c
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;
@@ -62,7 +62,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();
@@ -82,6 +82,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.
@@ -150,12 +152,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);
            });
@@ -163,19 +165,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.
@@ -186,12 +188,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();
            });
@@ -201,7 +203,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();
            });
@@ -217,7 +219,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();
@@ -231,6 +234,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();
@@ -254,8 +258,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);
        }
@@ -263,14 +266,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();
@@ -280,7 +283,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();
@@ -299,7 +302,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 */,
@@ -358,7 +361,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) {
@@ -374,12 +377,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
@@ -476,7 +479,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;
@@ -484,6 +488,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.PipMediaController;
@@ -64,6 +68,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 {
@@ -71,7 +76,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
@@ -99,6 +108,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;
@@ -157,9 +158,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
@@ -174,4 +175,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