From d5c1ec0ad9877508007d615e52e47c768feae7ec Mon Sep 17 00:00:00 2001 From: Bill Lin Date: Thu, 17 Sep 2020 17:22:08 +0800 Subject: [PATCH] Add Unit Tests to guarantee non Pip feature device quality Since Android Go disabled PIP feature, the current PIP arch register a bunch of callback at ctor, however, with dagger's mechanism it's not easy to predict which pip components was inited and register callback, that could introduce NPE unexpectly. Adding more test to verify disabled pip is a good option Adding new unit tests for PIP : + PipControllerTest + PipTaskOrganizerTest + OverviewProxyServiceTest Test: atest PipControllerTest Test: atest PipTaskOrganizerTest Test: atest WMShellTest Test: make SystemUI Test: make ArcSystemUI Test: make WMShellUnitTests Test: lunch aosp_tv_arm-userdebug & make Test: atest SystemUITests Test: atest WindowManagerShellTests Test: atest WMShellUnitTests Test: adb shell input keyevent 171(KEYCODE_WINDOW) Test: manual test Pip demo AP Test: adb shell dumpsys activity service com.android.systemui Bug: 168715160 Change-Id: Idee90d00265d2ced629d4ba4eb0bb85c2a7905ac --- .../systemui/pip/PipTaskOrganizer.java | 6 + .../systemui/pip/phone/PipController.java | 6 +- .../android/systemui/pip/phone/PipUtils.java | 11 ++ .../recents/OverviewProxyService.java | 8 +- .../com/android/systemui/wmshell/WMShell.java | 7 +- .../systemui/pip/phone/PipControllerTest.java | 115 +++++++++++++++++ .../pip/phone/PipTaskOrganizerTest.java | 93 ++++++++++++++ .../recents/OverviewProxyServiceTest.java | 117 ++++++++++++++++++ .../android/systemui/wmshell/WMShellTest.java | 30 ++++- 9 files changed, 378 insertions(+), 15 deletions(-) create mode 100644 packages/SystemUI/tests/src/com/android/systemui/pip/phone/PipControllerTest.java create mode 100644 packages/SystemUI/tests/src/com/android/systemui/pip/phone/PipTaskOrganizerTest.java create mode 100644 packages/SystemUI/tests/src/com/android/systemui/recents/OverviewProxyServiceTest.java diff --git a/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java b/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java index 9ca5f2a0dfd12..d33cf2f79e8b0 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java +++ b/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java @@ -62,6 +62,7 @@ import com.android.internal.os.SomeArgs; import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.pip.phone.PipMenuActivityController; import com.android.systemui.pip.phone.PipUpdateThread; +import com.android.systemui.pip.phone.PipUtils; import com.android.wm.shell.R; import com.android.wm.shell.ShellTaskOrganizer; import com.android.wm.shell.common.DisplayController; @@ -260,6 +261,11 @@ public class PipTaskOrganizer extends TaskOrganizer implements ShellTaskOrganize mSurfaceControlTransactionFactory = SurfaceControl.Transaction::new; mSplitScreenOptional = splitScreenOptional; mTaskOrganizer = shellTaskOrganizer; + + if (!PipUtils.hasSystemFeature(context)) { + Log.w(TAG, "Device not support PIP feature"); + return; + } mTaskOrganizer.addListener(this, WINDOWING_MODE_PINNED); displayController.addDisplayWindowListener(this); } diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipController.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipController.java index 5bb179484e5d9..8a2e9e23343cb 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipController.java +++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipController.java @@ -18,7 +18,6 @@ package com.android.systemui.pip.phone; import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED; import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; -import static android.content.pm.PackageManager.FEATURE_PICTURE_IN_PICTURE; import static com.android.systemui.pip.PipAnimationController.isOutPipDirection; @@ -30,7 +29,6 @@ import android.app.IActivityManager; import android.app.RemoteAction; import android.content.ComponentName; import android.content.Context; -import android.content.pm.PackageManager; import android.content.pm.ParceledListSlice; import android.content.res.Configuration; import android.graphics.Rect; @@ -278,9 +276,7 @@ public class PipController implements Pip, PipTaskOrganizer.PipTransitionCallbac mContext = context; mActivityManager = ActivityManager.getService(); - PackageManager pm = context.getPackageManager(); - boolean supportsPip = pm.hasSystemFeature(FEATURE_PICTURE_IN_PICTURE); - if (supportsPip) { + if (PipUtils.hasSystemFeature(mContext)) { initController(context, broadcastDispatcher, configController, deviceConfig, displayController, floatingContentCoordinator, sysUiState, pipBoundsHandler, pipSurfaceTransactionHelper, pipTaskOrganizer, pipUiEventLogger); diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipUtils.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipUtils.java index baa8f118f362a..1bf6dd7bb9ef4 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipUtils.java +++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipUtils.java @@ -18,6 +18,7 @@ package com.android.systemui.pip.phone; import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED; import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; +import static android.content.pm.PackageManager.FEATURE_PICTURE_IN_PICTURE; import android.app.ActivityTaskManager; import android.app.ActivityTaskManager.RootTaskInfo; @@ -57,4 +58,14 @@ public class PipUtils { } return new Pair<>(null, 0); } + + /** + * The util to check if device has PIP feature + * + * @param context application context + * @return true if device has PIP feature, false otherwise. + */ + public static boolean hasSystemFeature(Context context) { + return context.getPackageManager().hasSystemFeature(FEATURE_PICTURE_IN_PICTURE); + } } diff --git a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java index 2a976f546ba42..ed8da7c3d80bb 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java +++ b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java @@ -16,7 +16,6 @@ package com.android.systemui.recents; -import static android.content.pm.PackageManager.FEATURE_PICTURE_IN_PICTURE; import static android.content.pm.PackageManager.MATCH_SYSTEM_ONLY; import static android.view.MotionEvent.ACTION_CANCEL; import static android.view.MotionEvent.ACTION_DOWN; @@ -65,6 +64,7 @@ import android.view.accessibility.AccessibilityManager; import androidx.annotation.NonNull; import com.android.internal.accessibility.dialog.AccessibilityButtonChooserActivity; +import com.android.internal.annotations.VisibleForTesting; import com.android.internal.policy.ScreenDecorationsUtils; import com.android.internal.util.ScreenshotHelper; import com.android.systemui.Dumpable; @@ -77,6 +77,7 @@ import com.android.systemui.navigationbar.NavigationBarView; import com.android.systemui.navigationbar.NavigationModeController; import com.android.systemui.pip.Pip; import com.android.systemui.pip.PipAnimationController; +import com.android.systemui.pip.phone.PipUtils; import com.android.systemui.recents.OverviewProxyService.OverviewProxyListener; import com.android.systemui.settings.CurrentUserTracker; import com.android.systemui.shared.recents.IOverviewProxy; @@ -155,7 +156,8 @@ public class OverviewProxyService extends CurrentUserTracker implements private boolean mSupportsRoundedCornersOnWindows; private int mNavBarMode = NAV_BAR_MODE_3BUTTON; - private ISystemUiProxy mSysUiProxy = new ISystemUiProxy.Stub() { + @VisibleForTesting + public ISystemUiProxy mSysUiProxy = new ISystemUiProxy.Stub() { @Override public void startScreenPinning(int taskId) { @@ -624,7 +626,7 @@ public class OverviewProxyService extends CurrentUserTracker implements super(broadcastDispatcher); mContext = context; mPipOptional = pipOptional; - mHasPipFeature = mContext.getPackageManager().hasSystemFeature(FEATURE_PICTURE_IN_PICTURE); + mHasPipFeature = PipUtils.hasSystemFeature(mContext); mStatusBarOptionalLazy = statusBarOptionalLazy; mHandler = new Handler(); mNavBarControllerLazy = navBarControllerLazy; diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java b/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java index ce125f3fdce07..a2d6ac8f8511f 100644 --- a/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java +++ b/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java @@ -40,6 +40,7 @@ import com.android.systemui.keyguard.ScreenLifecycle; import com.android.systemui.model.SysUiState; import com.android.systemui.navigationbar.NavigationModeController; import com.android.systemui.pip.Pip; +import com.android.systemui.pip.phone.PipUtils; import com.android.systemui.shared.system.ActivityManagerWrapper; import com.android.systemui.shared.system.TaskStackChangeListener; import com.android.systemui.shared.tracing.ProtoTraceable; @@ -57,7 +58,6 @@ import com.android.wm.shell.protolog.ShellProtoLogImpl; import com.android.wm.shell.splitscreen.SplitScreen; import java.io.FileDescriptor; -import java.io.FileOutputStream; import java.io.PrintWriter; import java.util.Arrays; import java.util.Optional; @@ -103,7 +103,6 @@ public final class WMShell extends SystemUI ProtoTracer protoTracer) { super(context); mCommandQueue = commandQueue; - mCommandQueue.addCallback(this); mKeyguardUpdateMonitor = keyguardUpdateMonitor; mActivityManagerWrapper = activityManagerWrapper; mDisplayImeController = displayImeController; @@ -120,6 +119,7 @@ public final class WMShell extends SystemUI @Override public void start() { + mCommandQueue.addCallback(this); // This is to prevent circular init problem by separating registration step out of its // constructor. And make sure the initialization of DisplayImeController won't depend on // specific feature anymore. @@ -131,6 +131,9 @@ public final class WMShell extends SystemUI @VisibleForTesting void initPip(Pip pip) { + if (!PipUtils.hasSystemFeature(mContext)) { + return; + } mCommandQueue.addCallback(new CommandQueue.Callbacks() { @Override public void showPictureInPictureMenu() { diff --git a/packages/SystemUI/tests/src/com/android/systemui/pip/phone/PipControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/pip/phone/PipControllerTest.java new file mode 100644 index 0000000000000..b04349521205a --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/pip/phone/PipControllerTest.java @@ -0,0 +1,115 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.pip.phone; + +import static android.content.pm.PackageManager.FEATURE_PICTURE_IN_PICTURE; + +import static org.mockito.ArgumentMatchers.any; +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.pm.PackageManager; +import android.os.RemoteException; +import android.test.suitebuilder.annotation.SmallTest; +import android.testing.AndroidTestingRunner; +import android.testing.TestableContext; +import android.testing.TestableLooper; + +import com.android.systemui.SysuiTestCase; +import com.android.systemui.broadcast.BroadcastDispatcher; +import com.android.systemui.model.SysUiState; +import com.android.systemui.pip.PipBoundsHandler; +import com.android.systemui.pip.PipSurfaceTransactionHelper; +import com.android.systemui.pip.PipTaskOrganizer; +import com.android.systemui.pip.PipUiEventLogger; +import com.android.systemui.shared.system.ActivityManagerWrapper; +import com.android.systemui.statusbar.policy.ConfigurationController; +import com.android.systemui.util.DeviceConfigProxy; +import com.android.systemui.util.FloatingContentCoordinator; +import com.android.wm.shell.common.DisplayController; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +/** + * Unit tests for {@link PipController} + */ +@SmallTest +@RunWith(AndroidTestingRunner.class) +@TestableLooper.RunWithLooper +public class PipControllerTest extends SysuiTestCase { + private PipController mPipController; + private TestableContext mSpiedContext; + + @Mock private ActivityManagerWrapper mMockActivityManagerWrapper; + @Mock private BroadcastDispatcher mMockBroadcastDispatcher; + @Mock private ConfigurationController mMockConfigurationController; + @Mock private DeviceConfigProxy mMockDeviceConfigProxy; + @Mock private DisplayController mMockdDisplayController; + @Mock private FloatingContentCoordinator mMockFloatingContentCoordinator; + @Mock private PackageManager mPackageManager; + @Mock private PipBoundsHandler mMockPipBoundsHandler; + @Mock private PipSurfaceTransactionHelper mMockPipSurfaceTransactionHelper; + @Mock private PipTaskOrganizer mMockPipTaskOrganizer; + @Mock private PipUiEventLogger mPipUiEventLogger; + @Mock private SysUiState mMockSysUiState; + + @Before + public void setUp() throws RemoteException { + MockitoAnnotations.initMocks(this); + + mSpiedContext = spy(mContext); + + when(mPackageManager.hasSystemFeature(FEATURE_PICTURE_IN_PICTURE)).thenReturn(false); + when(mSpiedContext.getPackageManager()).thenReturn(mPackageManager); + + mPipController = new PipController(mSpiedContext, mMockBroadcastDispatcher, + mMockConfigurationController, mMockDeviceConfigProxy, mMockdDisplayController, + mMockFloatingContentCoordinator, mMockSysUiState, mMockPipBoundsHandler, + mMockPipSurfaceTransactionHelper, mMockPipTaskOrganizer, mPipUiEventLogger); + } + + @Test + public void testNonPipDevice_shouldNotRegisterTaskStackListener() { + verify(mMockActivityManagerWrapper, never()).registerTaskStackListener(any()); + } + + @Test + public void testNonPipDevice_shouldNotRegisterPipTransitionCallback() { + verify(mMockPipTaskOrganizer, never()).registerPipTransitionCallback(any()); + } + + @Test + public void testNonPipDevice_shouldNotAddDisplayChangingController() { + verify(mMockdDisplayController, never()).addDisplayChangingController(any()); + } + + @Test + public void testNonPipDevice_shouldNotAddDisplayWindowListener() { + verify(mMockdDisplayController, never()).addDisplayWindowListener(any()); + } + + @Test + public void testNonPipDevice_shouldNotAddCallback() { + verify(mMockConfigurationController, never()).addCallback(any()); + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/pip/phone/PipTaskOrganizerTest.java b/packages/SystemUI/tests/src/com/android/systemui/pip/phone/PipTaskOrganizerTest.java new file mode 100644 index 0000000000000..b1a7df83fa9f7 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/pip/phone/PipTaskOrganizerTest.java @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.pip.phone; + +import static android.content.pm.PackageManager.FEATURE_PICTURE_IN_PICTURE; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; +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.pm.PackageManager; +import android.os.RemoteException; +import android.test.suitebuilder.annotation.SmallTest; +import android.testing.AndroidTestingRunner; +import android.testing.TestableContext; +import android.testing.TestableLooper; + +import com.android.systemui.SysuiTestCase; +import com.android.systemui.pip.PipBoundsHandler; +import com.android.systemui.pip.PipSurfaceTransactionHelper; +import com.android.systemui.pip.PipTaskOrganizer; +import com.android.systemui.pip.PipUiEventLogger; +import com.android.wm.shell.ShellTaskOrganizer; +import com.android.wm.shell.common.DisplayController; +import com.android.wm.shell.splitscreen.SplitScreen; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +import java.util.Optional; + +/** + * Unit tests for {@link PipTaskOrganizer} + */ +@SmallTest +@RunWith(AndroidTestingRunner.class) +@TestableLooper.RunWithLooper +public class PipTaskOrganizerTest extends SysuiTestCase { + private PipTaskOrganizer mSpiedPipTaskOrganizer; + private TestableContext mSpiedContext; + + @Mock private DisplayController mMockdDisplayController; + @Mock private PackageManager mPackageManager; + @Mock private PipBoundsHandler mMockPipBoundsHandler; + @Mock private PipSurfaceTransactionHelper mMockPipSurfaceTransactionHelper; + @Mock private PipUiEventLogger mMockPipUiEventLogger; + @Mock private Optional mMockOptionalSplitScreen; + @Mock private ShellTaskOrganizer mMockShellTaskOrganizer; + + @Before + public void setUp() throws RemoteException { + MockitoAnnotations.initMocks(this); + + mSpiedContext = spy(mContext); + + when(mPackageManager.hasSystemFeature(FEATURE_PICTURE_IN_PICTURE)).thenReturn(false); + when(mSpiedContext.getPackageManager()).thenReturn(mPackageManager); + + mSpiedPipTaskOrganizer = spy(new PipTaskOrganizer(mSpiedContext, mMockPipBoundsHandler, + mMockPipSurfaceTransactionHelper, mMockOptionalSplitScreen, mMockdDisplayController, + mMockPipUiEventLogger, mMockShellTaskOrganizer)); + } + + @Test + public void testNonPipDevice_shellTaskOrganizer_shouldNotAddListener() { + verify(mMockShellTaskOrganizer, never()).addListener(any(), anyInt()); + } + + @Test + public void testNonPipDevice_displayController_shouldNotAddDisplayWindowListener() { + verify(mMockdDisplayController, never()).addDisplayWindowListener(any()); + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/recents/OverviewProxyServiceTest.java b/packages/SystemUI/tests/src/com/android/systemui/recents/OverviewProxyServiceTest.java new file mode 100644 index 0000000000000..727f91c589dfb --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/recents/OverviewProxyServiceTest.java @@ -0,0 +1,117 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.recents; + +import static android.content.pm.PackageManager.FEATURE_PICTURE_IN_PICTURE; + +import static org.mockito.ArgumentMatchers.any; +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.pm.PackageManager; +import android.os.RemoteException; +import android.test.suitebuilder.annotation.SmallTest; +import android.testing.AndroidTestingRunner; +import android.testing.TestableContext; +import android.testing.TestableLooper; + +import com.android.systemui.SysuiTestCase; +import com.android.systemui.broadcast.BroadcastDispatcher; +import com.android.systemui.model.SysUiState; +import com.android.systemui.navigationbar.NavigationBarController; +import com.android.systemui.navigationbar.NavigationModeController; +import com.android.systemui.pip.Pip; +import com.android.systemui.shared.recents.IPinnedStackAnimationListener; +import com.android.systemui.statusbar.CommandQueue; +import com.android.systemui.statusbar.NotificationShadeWindowController; +import com.android.systemui.statusbar.phone.StatusBar; +import com.android.wm.shell.splitscreen.SplitScreen; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +import java.util.Optional; + +import dagger.Lazy; + +/** + * Unit tests for {@link com.android.systemui.recents.OverviewProxyService} + */ +@SmallTest +@RunWith(AndroidTestingRunner.class) +@TestableLooper.RunWithLooper +public class OverviewProxyServiceTest extends SysuiTestCase { + private OverviewProxyService mSpiedOverviewProxyService; + private TestableContext mSpiedContext; + + @Mock private BroadcastDispatcher mMockBroadcastDispatcher; + @Mock private CommandQueue mMockCommandQueue; + @Mock private Lazy mMockNavBarControllerLazy; + @Mock private IPinnedStackAnimationListener mMockPinnedStackAnimationListener; + @Mock private NavigationModeController mMockNavModeController; + @Mock private NotificationShadeWindowController mMockStatusBarWinController; + @Mock private Optional mMockPipOptional; + @Mock private Optional mMockSplitScreenOptional; + @Mock private Optional> mMockStatusBarOptionalLazy; + @Mock private Optional mMockOneHandedOptional; + @Mock private PackageManager mPackageManager; + @Mock private SysUiState mMockSysUiState; + + @Before + public void setUp() throws RemoteException { + MockitoAnnotations.initMocks(this); + + mSpiedContext = spy(mContext); + + when(mPackageManager.hasSystemFeature(FEATURE_PICTURE_IN_PICTURE)).thenReturn(false); + when(mSpiedContext.getPackageManager()).thenReturn(mPackageManager); + + mSpiedOverviewProxyService = spy(new OverviewProxyService(mSpiedContext, mMockCommandQueue, + mMockNavBarControllerLazy, mMockNavModeController, mMockStatusBarWinController, + mMockSysUiState, mMockPipOptional, mMockSplitScreenOptional, + mMockStatusBarOptionalLazy, mMockOneHandedOptional, + mMockBroadcastDispatcher)); + } + + @Test + public void testNonPipDevice_shouldNotNotifySwipeToHomeFinished() throws RemoteException { + mSpiedOverviewProxyService.mSysUiProxy.notifySwipeToHomeFinished(); + + verify(mMockPipOptional, never()).ifPresent(any()); + } + + @Test + public void testNonPipDevice_shouldNotSetPinnedStackAnimationListener() throws RemoteException { + mSpiedOverviewProxyService.mSysUiProxy.setPinnedStackAnimationListener( + mMockPinnedStackAnimationListener); + + verify(mMockPipOptional, never()).ifPresent(any()); + } + + @Test + public void testNonPipDevice_shouldNotSetShelfHeight() throws RemoteException { + mSpiedOverviewProxyService.mSysUiProxy.setShelfHeight(true /* visible */, + 100 /* shelfHeight */); + + verify(mMockPipOptional, never()).ifPresent(any()); + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/wmshell/WMShellTest.java b/packages/SystemUI/tests/src/com/android/systemui/wmshell/WMShellTest.java index ef4d1078b8b92..280423fca202d 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/wmshell/WMShellTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/wmshell/WMShellTest.java @@ -16,12 +16,17 @@ package com.android.systemui.wmshell; +import static android.content.pm.PackageManager.FEATURE_PICTURE_IN_PICTURE; + import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.times; +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.pm.PackageManager; import android.test.suitebuilder.annotation.SmallTest; +import android.testing.TestableContext; import androidx.test.runner.AndroidJUnit4; @@ -68,6 +73,7 @@ public class WMShellTest extends SysuiTestCase { @Mock OneHanded mOneHanded; @Mock ShellTaskOrganizer mTaskOrganizer; @Mock ProtoTracer mProtoTracer; + @Mock PackageManager mMockPackageManager; @Before public void setUp() { @@ -89,8 +95,23 @@ public class WMShellTest extends SysuiTestCase { public void initPip_registersCommandQueueCallback() { mWMShell.initPip(mPip); - // Once for the shell, once for pip - verify(mCommandQueue, times(2)).addCallback(any(CommandQueue.Callbacks.class)); + verify(mCommandQueue).addCallback(any(CommandQueue.Callbacks.class)); + } + + @Test + public void nonPipDevice_shouldNotInitPip() { + TestableContext spiedContext = spy(mContext); + when(mMockPackageManager.hasSystemFeature(FEATURE_PICTURE_IN_PICTURE)).thenReturn(false); + when(spiedContext.getPackageManager()).thenReturn(mMockPackageManager); + + final WMShell nonPipWMShell = new WMShell(spiedContext, mCommandQueue, + mKeyguardUpdateMonitor, + mActivityManagerWrapper, mDisplayImeController, mNavigationModeController, + mScreenLifecycle, mSysUiState, Optional.of(mPip), Optional.of(mSplitScreen), + Optional.of(mOneHanded), mTaskOrganizer, mProtoTracer); + nonPipWMShell.initPip(mPip); + + verify(mCommandQueue, never()).addCallback(any()); } @Test @@ -108,8 +129,7 @@ public class WMShellTest extends SysuiTestCase { mWMShell.initOneHanded(mOneHanded); verify(mKeyguardUpdateMonitor).registerCallback(any(KeyguardUpdateMonitorCallback.class)); - // Once for the shell, once for the one handed mode - verify(mCommandQueue, times(2)).addCallback(any(CommandQueue.Callbacks.class)); + verify(mCommandQueue).addCallback(any(CommandQueue.Callbacks.class)); verify(mScreenLifecycle).addObserver(any(ScreenLifecycle.Observer.class)); verify(mNavigationModeController).addListener( any(NavigationModeController.ModeChangedListener.class));