summaryrefslogtreecommitdiff
path: root/quickstep/tests
diff options
context:
space:
mode:
Diffstat (limited to 'quickstep/tests')
-rw-r--r--quickstep/tests/OWNERS1
-rw-r--r--quickstep/tests/src/com/android/launcher3/taskbar/FallbackTaskbarUIControllerTest.kt18
-rw-r--r--quickstep/tests/src/com/android/launcher3/taskbar/TaskbarBaseTestCase.kt2
-rw-r--r--quickstep/tests/src/com/android/launcher3/taskbar/TaskbarHoverToolTipControllerTest.java13
-rw-r--r--quickstep/tests/src/com/android/launcher3/taskbar/TaskbarKeyguardControllerTest.kt18
-rw-r--r--quickstep/tests/src/com/android/launcher3/taskbar/navbutton/NavButtonLayoutFactoryTest.kt65
-rw-r--r--quickstep/tests/src/com/android/quickstep/AbstractTaplTestsTaskbar.java6
-rw-r--r--quickstep/tests/src/com/android/quickstep/FallbackRecentsTest.java44
-rw-r--r--quickstep/tests/src/com/android/quickstep/FullscreenDrawParamsTest.kt118
-rw-r--r--quickstep/tests/src/com/android/quickstep/NavigationModeSwitchRule.java2
-rw-r--r--quickstep/tests/src/com/android/quickstep/RecentsAnimationDeviceStateTest.kt144
-rw-r--r--quickstep/tests/src/com/android/quickstep/RecentsModelTest.java173
-rw-r--r--quickstep/tests/src/com/android/quickstep/TaplDigitalWellBeingToastTest.java (renamed from quickstep/tests/src/com/android/quickstep/DigitalWellBeingToastTest.java)17
-rw-r--r--quickstep/tests/src/com/android/quickstep/TaplOverviewIconTest.java112
-rw-r--r--quickstep/tests/src/com/android/quickstep/TaplStartLauncherViaGestureTests.java (renamed from quickstep/tests/src/com/android/quickstep/StartLauncherViaGestureTests.java)12
-rw-r--r--quickstep/tests/src/com/android/quickstep/TaplTestsKeyboardQuickSwitch.java187
-rw-r--r--quickstep/tests/src/com/android/quickstep/TaplTestsPersistentTaskbar.java18
-rw-r--r--quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java183
-rw-r--r--quickstep/tests/src/com/android/quickstep/TaplTestsSplitscreen.java42
-rw-r--r--quickstep/tests/src/com/android/quickstep/TaplTestsTaskbar.java18
-rw-r--r--quickstep/tests/src/com/android/quickstep/TaplTestsTrackpad.java7
-rw-r--r--quickstep/tests/src/com/android/quickstep/TaplTestsTransientTaskbar.java53
-rw-r--r--quickstep/tests/src/com/android/quickstep/TaplViewInflationDuringSwipeUp.java (renamed from quickstep/tests/src/com/android/quickstep/ViewInflationDuringSwipeUp.java)6
-rw-r--r--quickstep/tests/src/com/android/quickstep/TaskThumbnailCacheTest.java95
-rw-r--r--quickstep/tests/src/com/android/quickstep/TaskViewTest.java118
-rw-r--r--quickstep/tests/src/com/android/quickstep/TaskbarModeSwitchRule.java2
-rw-r--r--quickstep/tests/src/com/android/quickstep/taskbar/controllers/TaskbarPinningControllerTest.kt202
-rw-r--r--quickstep/tests/src/com/android/quickstep/util/AppPairsControllerTest.kt147
-rw-r--r--quickstep/tests/src/com/android/quickstep/util/SplitAnimationControllerTest.kt223
-rw-r--r--quickstep/tests/src/com/android/quickstep/util/SplitSelectDataHolderTest.kt16
-rw-r--r--quickstep/tests/src/com/android/quickstep/util/SplitSelectStateControllerTest.kt230
-rw-r--r--quickstep/tests/src/com/android/quickstep/util/TaskGridNavHelperTest.java510
-rw-r--r--quickstep/tests/src/com/android/quickstep/util/TaskKeyByLastActiveTimeCacheTest.java281
-rw-r--r--quickstep/tests/src/com/android/quickstep/util/TaskViewSimulatorTest.java35
-rw-r--r--quickstep/tests/src/com/android/quickstep/util/unfold/PreemptiveUnfoldTransitionProgressProviderTest.kt26
35 files changed, 2642 insertions, 502 deletions
diff --git a/quickstep/tests/OWNERS b/quickstep/tests/OWNERS
index 02e8ebcaba..c271803f21 100644
--- a/quickstep/tests/OWNERS
+++ b/quickstep/tests/OWNERS
@@ -2,3 +2,4 @@ vadimt@google.com
sunnygoyal@google.com
winsonc@google.com
hyunyoungs@google.com
+mateuszc@google.com
diff --git a/quickstep/tests/src/com/android/launcher3/taskbar/FallbackTaskbarUIControllerTest.kt b/quickstep/tests/src/com/android/launcher3/taskbar/FallbackTaskbarUIControllerTest.kt
index 8c13fe3f1e..f3115c6a52 100644
--- a/quickstep/tests/src/com/android/launcher3/taskbar/FallbackTaskbarUIControllerTest.kt
+++ b/quickstep/tests/src/com/android/launcher3/taskbar/FallbackTaskbarUIControllerTest.kt
@@ -24,11 +24,11 @@ import com.android.quickstep.fallback.RecentsState
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
-import org.mockito.ArgumentCaptor
-import org.mockito.Mock
-import org.mockito.Mockito.times
-import org.mockito.Mockito.verify
-import org.mockito.Mockito.`when` as whenever
+import org.mockito.kotlin.argumentCaptor
+import org.mockito.kotlin.mock
+import org.mockito.kotlin.times
+import org.mockito.kotlin.verify
+import org.mockito.kotlin.whenever
@RunWith(AndroidJUnit4::class)
class FallbackTaskbarUIControllerTest : TaskbarBaseTestCase() {
@@ -36,8 +36,8 @@ class FallbackTaskbarUIControllerTest : TaskbarBaseTestCase() {
lateinit var fallbackTaskbarUIController: FallbackTaskbarUIController
lateinit var stateListener: StateManager.StateListener<RecentsState>
- @Mock lateinit var recentsActivity: RecentsActivity
- @Mock lateinit var stateManager: StateManager<RecentsState>
+ private val recentsActivity: RecentsActivity = mock()
+ private val stateManager: StateManager<RecentsState> = mock()
@Before
override fun setup() {
@@ -46,10 +46,10 @@ class FallbackTaskbarUIControllerTest : TaskbarBaseTestCase() {
fallbackTaskbarUIController = FallbackTaskbarUIController(recentsActivity)
// Capture registered state listener to send events to in our tests
- val captor = ArgumentCaptor.forClass(StateManager.StateListener::class.java)
+ val captor = argumentCaptor<StateManager.StateListener<RecentsState>>()
fallbackTaskbarUIController.init(taskbarControllers)
verify(stateManager).addStateListener(captor.capture())
- stateListener = captor.value as StateManager.StateListener<RecentsState>
+ stateListener = captor.lastValue
}
@Test
diff --git a/quickstep/tests/src/com/android/launcher3/taskbar/TaskbarBaseTestCase.kt b/quickstep/tests/src/com/android/launcher3/taskbar/TaskbarBaseTestCase.kt
index 2c16c15caf..15b1e532bd 100644
--- a/quickstep/tests/src/com/android/launcher3/taskbar/TaskbarBaseTestCase.kt
+++ b/quickstep/tests/src/com/android/launcher3/taskbar/TaskbarBaseTestCase.kt
@@ -55,7 +55,7 @@ abstract class TaskbarBaseTestCase {
@Mock lateinit var taskbarOverlayController: TaskbarOverlayController
@Mock lateinit var taskbarEduTooltipController: TaskbarEduTooltipController
@Mock lateinit var keyboardQuickSwitchController: KeyboardQuickSwitchController
- @Mock lateinit var taskbarPinningController: TaskbarDividerPopupController
+ @Mock lateinit var taskbarPinningController: TaskbarPinningController
@Mock lateinit var optionalBubbleControllers: Optional<BubbleControllers>
lateinit var taskbarControllers: TaskbarControllers
diff --git a/quickstep/tests/src/com/android/launcher3/taskbar/TaskbarHoverToolTipControllerTest.java b/quickstep/tests/src/com/android/launcher3/taskbar/TaskbarHoverToolTipControllerTest.java
index 6c0d44da6c..9ed39066dd 100644
--- a/quickstep/tests/src/com/android/launcher3/taskbar/TaskbarHoverToolTipControllerTest.java
+++ b/quickstep/tests/src/com/android/launcher3/taskbar/TaskbarHoverToolTipControllerTest.java
@@ -18,7 +18,6 @@ package com.android.launcher3.taskbar;
import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
import static com.android.launcher3.taskbar.TaskbarAutohideSuspendController.FLAG_AUTOHIDE_SUSPEND_HOVERING_ICONS;
-import static com.android.launcher3.taskbar.TaskbarHoverToolTipController.HOVER_TOOL_TIP_REVEAL_START_DELAY;
import static com.google.common.truth.Truth.assertThat;
@@ -27,7 +26,6 @@ import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -128,14 +126,11 @@ public class TaskbarHoverToolTipControllerTest extends TaskbarBaseTestCase {
boolean hoverHandled =
mTaskbarHoverToolTipController.onHover(mHoverBubbleTextView, mMotionEvent);
-
- // Verify fullscreen is not set until the delayed runnable to reveal the tooltip has run
- verify(taskbarActivityContext, never()).setTaskbarWindowFullscreen(true);
waitForIdleSync();
+
assertThat(hoverHandled).isTrue();
verify(taskbarActivityContext).setAutohideSuspendFlag(FLAG_AUTOHIDE_SUSPEND_HOVERING_ICONS,
true);
- verify(taskbarActivityContext).setTaskbarWindowFullscreen(true);
}
@Test
@@ -159,14 +154,11 @@ public class TaskbarHoverToolTipControllerTest extends TaskbarBaseTestCase {
boolean hoverHandled =
mTaskbarHoverToolTipController.onHover(mHoverFolderIcon, mMotionEvent);
-
- // Verify fullscreen is not set until the delayed runnable to reveal the tooltip has run
- verify(taskbarActivityContext, never()).setTaskbarWindowFullscreen(true);
waitForIdleSync();
+
assertThat(hoverHandled).isTrue();
verify(taskbarActivityContext).setAutohideSuspendFlag(FLAG_AUTOHIDE_SUSPEND_HOVERING_ICONS,
true);
- verify(taskbarActivityContext).setTaskbarWindowFullscreen(true);
}
@Test
@@ -222,7 +214,6 @@ public class TaskbarHoverToolTipControllerTest extends TaskbarBaseTestCase {
}
private void waitForIdleSync() {
- mTestableLooper.moveTimeForward(HOVER_TOOL_TIP_REVEAL_START_DELAY + 1);
mTestableLooper.processAllMessages();
}
}
diff --git a/quickstep/tests/src/com/android/launcher3/taskbar/TaskbarKeyguardControllerTest.kt b/quickstep/tests/src/com/android/launcher3/taskbar/TaskbarKeyguardControllerTest.kt
index 148e36cde5..ed88c29b6a 100644
--- a/quickstep/tests/src/com/android/launcher3/taskbar/TaskbarKeyguardControllerTest.kt
+++ b/quickstep/tests/src/com/android/launcher3/taskbar/TaskbarKeyguardControllerTest.kt
@@ -23,17 +23,17 @@ import com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_STATUS_B
import com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING_OCCLUDED
import org.junit.Before
import org.junit.Test
-import org.mockito.Mock
-import org.mockito.Mockito.anyBoolean
-import org.mockito.Mockito.never
-import org.mockito.Mockito.times
-import org.mockito.Mockito.verify
-import org.mockito.Mockito.`when` as whenever
+import org.mockito.kotlin.any
+import org.mockito.kotlin.mock
+import org.mockito.kotlin.never
+import org.mockito.kotlin.times
+import org.mockito.kotlin.verify
+import org.mockito.kotlin.whenever
class TaskbarKeyguardControllerTest : TaskbarBaseTestCase() {
- @Mock lateinit var baseDragLayer: TaskbarDragLayer
- @Mock lateinit var keyguardManager: KeyguardManager
+ private val baseDragLayer: TaskbarDragLayer = mock()
+ private val keyguardManager: KeyguardManager = mock()
@Before
override fun setup() {
@@ -50,7 +50,7 @@ class TaskbarKeyguardControllerTest : TaskbarBaseTestCase() {
@Test
fun uninterestingFlags_noActions() {
setFlags(0)
- verify(navbarButtonsViewController, never()).setKeyguardVisible(anyBoolean(), anyBoolean())
+ verify(navbarButtonsViewController, never()).setKeyguardVisible(any(), any())
}
@Test
diff --git a/quickstep/tests/src/com/android/launcher3/taskbar/navbutton/NavButtonLayoutFactoryTest.kt b/quickstep/tests/src/com/android/launcher3/taskbar/navbutton/NavButtonLayoutFactoryTest.kt
index 3920b08030..9c7f0144c1 100644
--- a/quickstep/tests/src/com/android/launcher3/taskbar/navbutton/NavButtonLayoutFactoryTest.kt
+++ b/quickstep/tests/src/com/android/launcher3/taskbar/navbutton/NavButtonLayoutFactoryTest.kt
@@ -12,35 +12,37 @@ import android.widget.LinearLayout
import androidx.test.runner.AndroidJUnit4
import com.android.launcher3.DeviceProfile
import com.android.launcher3.R
+import com.android.launcher3.config.FeatureFlags.ENABLE_TASKBAR_NAVBAR_UNIFICATION
import com.android.launcher3.taskbar.TaskbarManager
+import com.android.systemui.shared.rotation.RotationButton
import java.lang.IllegalStateException
import org.junit.Assume.assumeTrue
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
-import org.mockito.Mock
-import org.mockito.Mockito.`when` as whenever
-import org.mockito.MockitoAnnotations
+import org.mockito.kotlin.mock
+import org.mockito.kotlin.whenever
@RunWith(AndroidJUnit4::class)
class NavButtonLayoutFactoryTest {
- @Mock lateinit var mockDeviceProfile: DeviceProfile
- @Mock lateinit var mockParentButtonContainer: FrameLayout
- @Mock lateinit var mockNavLayout: LinearLayout
- @Mock lateinit var mockStartContextualLayout: ViewGroup
- @Mock lateinit var mockEndContextualLayout: ViewGroup
- @Mock lateinit var mockResources: Resources
- @Mock lateinit var mockBackButton: ImageView
- @Mock lateinit var mockRecentsButton: ImageView
- @Mock lateinit var mockHomeButton: ImageView
+ private val mockDeviceProfile: DeviceProfile = mock()
+ private val mockParentButtonContainer: FrameLayout = mock()
+ private val mockNavLayout: LinearLayout = mock()
+ private val mockStartContextualLayout: ViewGroup = mock()
+ private val mockEndContextualLayout: ViewGroup = mock()
+ private val mockResources: Resources = mock()
+ private val mockBackButton: ImageView = mock()
+ private val mockRecentsButton: ImageView = mock()
+ private val mockHomeButton: ImageView = mock()
+ private val mockImeSwitcher: ImageView = mock()
+ private val mockRotationButton: RotationButton = mock()
+ private val mockA11yButton: ImageView = mock()
private var surfaceRotation = Surface.ROTATION_0
@Before
fun setup() {
- MockitoAnnotations.initMocks(this)
-
// Init end nav buttons
whenever(mockNavLayout.childCount).thenReturn(3)
whenever(mockNavLayout.findViewById<View>(R.id.back)).thenReturn(mockBackButton)
@@ -58,7 +60,7 @@ class NavButtonLayoutFactoryTest {
@Test
fun getKidsLayoutter() {
- assumeTrue(TaskbarManager.FLAG_HIDE_NAVBAR_WINDOW)
+ assumeTrue(ENABLE_TASKBAR_NAVBAR_UNIFICATION)
mockDeviceProfile.isTaskbarPresent = true
val layoutter: NavButtonLayoutFactory.NavButtonLayoutter =
getLayoutter(
@@ -73,7 +75,7 @@ class NavButtonLayoutFactoryTest {
@Test
fun getSetupLayoutter() {
- assumeTrue(TaskbarManager.FLAG_HIDE_NAVBAR_WINDOW)
+ assumeTrue(ENABLE_TASKBAR_NAVBAR_UNIFICATION)
mockDeviceProfile.isTaskbarPresent = true
val layoutter: NavButtonLayoutFactory.NavButtonLayoutter =
getLayoutter(
@@ -88,7 +90,7 @@ class NavButtonLayoutFactoryTest {
@Test
fun getTaskbarNavLayoutter() {
- assumeTrue(TaskbarManager.FLAG_HIDE_NAVBAR_WINDOW)
+ assumeTrue(ENABLE_TASKBAR_NAVBAR_UNIFICATION)
mockDeviceProfile.isTaskbarPresent = true
val layoutter: NavButtonLayoutFactory.NavButtonLayoutter =
getLayoutter(
@@ -103,7 +105,7 @@ class NavButtonLayoutFactoryTest {
@Test(expected = IllegalStateException::class)
fun noValidLayoutForLargeScreenTaskbarNotPresent() {
- assumeTrue(TaskbarManager.FLAG_HIDE_NAVBAR_WINDOW)
+ assumeTrue(ENABLE_TASKBAR_NAVBAR_UNIFICATION)
mockDeviceProfile.isTaskbarPresent = false
getLayoutter(
isKidsMode = false,
@@ -116,7 +118,7 @@ class NavButtonLayoutFactoryTest {
@Test
fun getTaskbarPortraitLayoutter() {
- assumeTrue(TaskbarManager.FLAG_HIDE_NAVBAR_WINDOW)
+ assumeTrue(ENABLE_TASKBAR_NAVBAR_UNIFICATION)
mockDeviceProfile.isTaskbarPresent = false
val layoutter: NavButtonLayoutFactory.NavButtonLayoutter =
getLayoutter(
@@ -131,7 +133,7 @@ class NavButtonLayoutFactoryTest {
@Test
fun getTaskbarLandscapeLayoutter() {
- assumeTrue(TaskbarManager.FLAG_HIDE_NAVBAR_WINDOW)
+ assumeTrue(ENABLE_TASKBAR_NAVBAR_UNIFICATION)
mockDeviceProfile.isTaskbarPresent = false
setDeviceProfileLandscape()
val layoutter: NavButtonLayoutFactory.NavButtonLayoutter =
@@ -147,23 +149,23 @@ class NavButtonLayoutFactoryTest {
@Test
fun getTaskbarSeascapeLayoutter() {
- assumeTrue(TaskbarManager.FLAG_HIDE_NAVBAR_WINDOW)
+ assumeTrue(ENABLE_TASKBAR_NAVBAR_UNIFICATION)
mockDeviceProfile.isTaskbarPresent = false
setDeviceProfileLandscape()
val layoutter: NavButtonLayoutFactory.NavButtonLayoutter =
- getLayoutter(
- isKidsMode = false,
- isInSetup = false,
- isThreeButtonNav = true,
- phoneMode = true,
- surfaceRotation = ROTATION_270
- )
+ getLayoutter(
+ isKidsMode = false,
+ isInSetup = false,
+ isThreeButtonNav = true,
+ phoneMode = true,
+ surfaceRotation = ROTATION_270
+ )
assert(layoutter is PhoneSeascapeNavLayoutter)
}
@Test(expected = IllegalStateException::class)
fun noValidLayoutForPhoneGestureNav() {
- assumeTrue(TaskbarManager.FLAG_HIDE_NAVBAR_WINDOW)
+ assumeTrue(ENABLE_TASKBAR_NAVBAR_UNIFICATION)
mockDeviceProfile.isTaskbarPresent = false
getLayoutter(
isKidsMode = false,
@@ -196,7 +198,10 @@ class NavButtonLayoutFactoryTest {
isInSetup = isInSetup,
isThreeButtonNav = isThreeButtonNav,
phoneMode = phoneMode,
- surfaceRotation = surfaceRotation
+ surfaceRotation = surfaceRotation,
+ imeSwitcher = mockImeSwitcher,
+ rotationButton = mockRotationButton,
+ a11yButton = mockA11yButton
)
}
}
diff --git a/quickstep/tests/src/com/android/quickstep/AbstractTaplTestsTaskbar.java b/quickstep/tests/src/com/android/quickstep/AbstractTaplTestsTaskbar.java
index 9c6c93d74a..fc757b44c9 100644
--- a/quickstep/tests/src/com/android/quickstep/AbstractTaplTestsTaskbar.java
+++ b/quickstep/tests/src/com/android/quickstep/AbstractTaplTestsTaskbar.java
@@ -25,7 +25,6 @@ import android.content.Intent;
import com.android.launcher3.tapl.LauncherInstrumentation;
import com.android.launcher3.tapl.Taskbar;
import com.android.launcher3.ui.AbstractLauncherUiTest;
-import com.android.launcher3.ui.TaplTestsLauncher3;
import com.android.launcher3.util.DisplayController;
import com.android.launcher3.util.LauncherLayoutBuilder;
import com.android.launcher3.util.TestUtil;
@@ -37,7 +36,6 @@ import java.util.List;
public class AbstractTaplTestsTaskbar extends AbstractQuickStepTest {
- protected static final String TEST_APP_NAME = "LauncherTestApp";
protected static final String TEST_APP_PACKAGE =
getInstrumentation().getContext().getPackageName();
protected static final String CALCULATOR_APP_PACKAGE =
@@ -56,7 +54,7 @@ public class AbstractTaplTestsTaskbar extends AbstractQuickStepTest {
"com.google.android.apps.nexuslauncher.tests",
"com.android.launcher3.testcomponent.BaseTestingActivity");
mLauncherLayout = TestUtil.setLauncherDefaultLayout(mTargetContext, layoutBuilder);
- TaplTestsLauncher3.initialize(this);
+ AbstractLauncherUiTest.initialize(this);
startAppFast(CALCULATOR_APP_PACKAGE);
mLauncher.enableBlockTimeout(true);
mLauncher.showTaskbarIfHidden();
@@ -95,6 +93,6 @@ public class AbstractTaplTestsTaskbar extends AbstractQuickStepTest {
launcher.enableTransientTaskbar(expectTransientTaskbar);
launcher.recreateTaskbar();
launcher.checkForAnomaly(true, true);
- AbstractLauncherUiTest.checkDetectedLeaks(launcher);
+ AbstractLauncherUiTest.checkDetectedLeaks(launcher, true);
}
}
diff --git a/quickstep/tests/src/com/android/quickstep/FallbackRecentsTest.java b/quickstep/tests/src/com/android/quickstep/FallbackRecentsTest.java
index a67d787842..8d54dce8ef 100644
--- a/quickstep/tests/src/com/android/quickstep/FallbackRecentsTest.java
+++ b/quickstep/tests/src/com/android/quickstep/FallbackRecentsTest.java
@@ -32,8 +32,6 @@ import static com.android.launcher3.ui.TaplTestsLauncher3.getAppPackageName;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import static com.android.launcher3.util.rule.ShellCommandRule.disableHeadsUpNotification;
import static com.android.launcher3.util.rule.ShellCommandRule.getLauncherCommand;
-import static com.android.launcher3.util.rule.TestStabilityRule.LOCAL;
-import static com.android.launcher3.util.rule.TestStabilityRule.PLATFORM_POSTSUBMIT;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
@@ -57,10 +55,12 @@ import com.android.launcher3.tapl.LauncherInstrumentation;
import com.android.launcher3.tapl.OverviewTask;
import com.android.launcher3.tapl.TestHelpers;
import com.android.launcher3.testcomponent.TestCommandReceiver;
+import com.android.launcher3.ui.AbstractLauncherUiTest;
import com.android.launcher3.util.Wait;
import com.android.launcher3.util.rule.FailureWatcher;
import com.android.launcher3.util.rule.SamplerRule;
import com.android.launcher3.util.rule.ScreenRecordRule;
+import com.android.launcher3.util.rule.TestIsolationRule;
import com.android.launcher3.util.rule.TestStabilityRule;
import com.android.launcher3.util.rule.ViewCaptureRule;
import com.android.quickstep.views.RecentsView;
@@ -94,9 +94,6 @@ public class FallbackRecentsTest {
public final TestRule mDisableHeadsUpNotification = disableHeadsUpNotification();
@Rule
- public final TestRule mSetLauncherCommand;
-
- @Rule
public final TestRule mOrderSensitiveRules;
@Rule
@@ -107,7 +104,7 @@ public class FallbackRecentsTest {
Context context = instrumentation.getContext();
mDevice = UiDevice.getInstance(instrumentation);
mDevice.setOrientationNatural();
- mLauncher = new LauncherInstrumentation();
+ mLauncher = AbstractLauncherUiTest.createLauncherInstrumentation();
mLauncher.enableDebugTracing();
// b/143488140
//mLauncher.enableCheckEventsForSuccessfulGestures();
@@ -116,19 +113,7 @@ public class FallbackRecentsTest {
Utilities.enableRunningInTestHarnessForTests();
}
- final ViewCaptureRule viewCaptureRule = new ViewCaptureRule(
- RecentsActivity.ACTIVITY_TRACKER::getCreatedActivity);
- mOrderSensitiveRules = RuleChain
- .outerRule(new SamplerRule())
- .around(new NavigationModeSwitchRule(mLauncher))
- .around(new FailureWatcher(mLauncher, viewCaptureRule::getViewCaptureData))
- .around(viewCaptureRule);
-
- mOtherLauncherActivity = context.getPackageManager().queryIntentActivities(
- getHomeIntentInPackage(context),
- MATCH_DISABLED_COMPONENTS).get(0).activityInfo;
-
- mSetLauncherCommand = (base, desc) -> new Statement() {
+ final TestRule setLauncherCommand = (base, desc) -> new Statement() {
@Override
public void evaluate() throws Throwable {
TestCommandReceiver.callCommand(TestCommandReceiver.ENABLE_TEST_LAUNCHER);
@@ -151,6 +136,22 @@ public class FallbackRecentsTest {
}
}
};
+
+ final ViewCaptureRule viewCaptureRule = new ViewCaptureRule(
+ RecentsActivity.ACTIVITY_TRACKER::getCreatedActivity);
+ mOrderSensitiveRules = RuleChain
+ .outerRule(new SamplerRule())
+ .around(new TestStabilityRule())
+ .around(new NavigationModeSwitchRule(mLauncher))
+ .around(new FailureWatcher(mLauncher, viewCaptureRule::getViewCaptureData))
+ // .around(viewCaptureRule) b/315482167
+ .around(new TestIsolationRule(mLauncher, false))
+ .around(setLauncherCommand);
+
+ mOtherLauncherActivity = context.getPackageManager().queryIntentActivities(
+ getHomeIntentInPackage(context),
+ MATCH_DISABLED_COMPONENTS).get(0).activityInfo;
+
if (TestHelpers.isInLauncherProcess()) {
mLauncher.setSystemHealthSupplier(startTime -> TestCommandReceiver.callCommand(
TestCommandReceiver.GET_SYSTEM_HEALTH_MESSAGE, startTime.toString()).
@@ -161,13 +162,14 @@ public class FallbackRecentsTest {
@Before
public void setUp() {
mLauncher.onTestStart();
+ AbstractLauncherUiTest.onTestStart();
}
@After
public void tearDown() {
try {
// Limits UI tests affecting tests running after them.
- AbstractQuickStepTest.checkDetectedLeaks(mLauncher);
+ AbstractQuickStepTest.checkDetectedLeaks(mLauncher, true);
} finally {
mLauncher.onTestFinish();
}
@@ -175,7 +177,6 @@ public class FallbackRecentsTest {
// b/143488140
//@NavigationModeSwitch
- @TestStabilityRule.Stability(flavors = LOCAL | PLATFORM_POSTSUBMIT) // b/266606727
@Test
public void goToOverviewFromHome() {
mDevice.pressHome();
@@ -223,7 +224,6 @@ public class FallbackRecentsTest {
// b/143488140
//@NavigationModeSwitch
- @TestStabilityRule.Stability(flavors = LOCAL | PLATFORM_POSTSUBMIT) // b/266606727
@Test
public void testOverview() {
startAppFast(getAppPackageName());
diff --git a/quickstep/tests/src/com/android/quickstep/FullscreenDrawParamsTest.kt b/quickstep/tests/src/com/android/quickstep/FullscreenDrawParamsTest.kt
index bb1afdf02d..db06b6bd7d 100644
--- a/quickstep/tests/src/com/android/quickstep/FullscreenDrawParamsTest.kt
+++ b/quickstep/tests/src/com/android/quickstep/FullscreenDrawParamsTest.kt
@@ -16,17 +16,13 @@
package com.android.quickstep
import android.content.Context
-import android.graphics.Rect
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.launcher3.FakeInvariantDeviceProfileTest
import com.android.quickstep.util.TaskCornerRadius
import com.android.quickstep.views.TaskView.FullscreenDrawParams
-import com.android.systemui.shared.recents.model.ThumbnailData
-import com.android.systemui.shared.recents.utilities.PreviewPositionHelper
import com.android.systemui.shared.system.QuickStepContract
import com.google.common.truth.Truth.assertThat
-import kotlin.math.roundToInt
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@@ -39,10 +35,6 @@ import org.mockito.Mockito.spy
@RunWith(AndroidJUnit4::class)
class FullscreenDrawParamsTest : FakeInvariantDeviceProfileTest() {
- private val TASK_SCALE = 0.7f
- private var mThumbnailData: ThumbnailData = mock(ThumbnailData::class.java)
-
- private val mPreviewPositionHelper = PreviewPositionHelper()
private lateinit var params: FullscreenDrawParams
@Before
@@ -53,32 +45,11 @@ class FullscreenDrawParamsTest : FakeInvariantDeviceProfileTest() {
@Test
fun setStartProgress_correctCornerRadiusForTablet() {
initializeVarsForTablet()
- val dp = newDP()
- val previewRect = Rect(0, 0, 100, 100)
- val canvasWidth = (dp.widthPx * TASK_SCALE).roundToInt()
- val canvasHeight = (dp.heightPx * TASK_SCALE).roundToInt()
- val currentRotation = 0
- val isRtl = false
- mPreviewPositionHelper.updateThumbnailMatrix(
- previewRect,
- mThumbnailData,
- canvasWidth,
- canvasHeight,
- dp.widthPx,
- dp.heightPx,
- dp.taskbarHeight,
- dp.isTablet,
- currentRotation,
- isRtl
- )
params.setProgress(
/* fullscreenProgress= */ 0f,
/* parentScale= */ 1.0f,
- /* taskViewScale= */ 1.0f,
- /* previewWidth= */ 0,
- dp,
- mPreviewPositionHelper
+ /* taskViewScale= */ 1.0f
)
val expectedRadius = TaskCornerRadius.get(context)
@@ -88,32 +59,11 @@ class FullscreenDrawParamsTest : FakeInvariantDeviceProfileTest() {
@Test
fun setFullProgress_correctCornerRadiusForTablet() {
initializeVarsForTablet()
- val dp = newDP()
- val previewRect = Rect(0, 0, 100, 100)
- val canvasWidth = (dp.widthPx * TASK_SCALE).roundToInt()
- val canvasHeight = (dp.heightPx * TASK_SCALE).roundToInt()
- val currentRotation = 0
- val isRtl = false
- mPreviewPositionHelper.updateThumbnailMatrix(
- previewRect,
- mThumbnailData,
- canvasWidth,
- canvasHeight,
- dp.widthPx,
- dp.heightPx,
- dp.taskbarHeight,
- dp.isTablet,
- currentRotation,
- isRtl
- )
params.setProgress(
/* fullscreenProgress= */ 1.0f,
/* parentScale= */ 1.0f,
- /* taskViewScale= */ 1.0f,
- /* previewWidth= */ 0,
- dp,
- mPreviewPositionHelper
+ /* taskViewScale= */ 1.0f
)
val expectedRadius = QuickStepContract.getWindowCornerRadius(context)
@@ -123,32 +73,11 @@ class FullscreenDrawParamsTest : FakeInvariantDeviceProfileTest() {
@Test
fun setStartProgress_correctCornerRadiusForPhone() {
initializeVarsForPhone()
- val dp = newDP()
- val previewRect = Rect(0, 0, 100, 100)
- val canvasWidth = (dp.widthPx * TASK_SCALE).roundToInt()
- val canvasHeight = (dp.heightPx * TASK_SCALE).roundToInt()
- val currentRotation = 0
- val isRtl = false
- mPreviewPositionHelper.updateThumbnailMatrix(
- previewRect,
- mThumbnailData,
- canvasWidth,
- canvasHeight,
- dp.widthPx,
- dp.heightPx,
- dp.taskbarHeight,
- dp.isTablet,
- currentRotation,
- isRtl
- )
params.setProgress(
/* fullscreenProgress= */ 0f,
/* parentScale= */ 1.0f,
- /* taskViewScale= */ 1.0f,
- /* previewWidth= */ 0,
- dp,
- mPreviewPositionHelper
+ /* taskViewScale= */ 1.0f
)
val expectedRadius = TaskCornerRadius.get(context)
@@ -158,32 +87,11 @@ class FullscreenDrawParamsTest : FakeInvariantDeviceProfileTest() {
@Test
fun setFullProgress_correctCornerRadiusForPhone() {
initializeVarsForPhone()
- val dp = newDP()
- val previewRect = Rect(0, 0, 100, 100)
- val canvasWidth = (dp.widthPx * TASK_SCALE).roundToInt()
- val canvasHeight = (dp.heightPx * TASK_SCALE).roundToInt()
- val currentRotation = 0
- val isRtl = false
- mPreviewPositionHelper.updateThumbnailMatrix(
- previewRect,
- mThumbnailData,
- canvasWidth,
- canvasHeight,
- dp.widthPx,
- dp.heightPx,
- dp.taskbarHeight,
- dp.isTablet,
- currentRotation,
- isRtl
- )
params.setProgress(
/* fullscreenProgress= */ 1.0f,
/* parentScale= */ 1.0f,
- /* taskViewScale= */ 1.0f,
- /* previewWidth= */ 0,
- dp,
- mPreviewPositionHelper
+ /* taskViewScale= */ 1.0f
)
val expectedRadius = QuickStepContract.getWindowCornerRadius(context)
@@ -207,10 +115,7 @@ class FullscreenDrawParamsTest : FakeInvariantDeviceProfileTest() {
spyParams.setProgress(
/* fullscreenProgress= */ 0f,
/* parentScale= */ 1.0f,
- /* taskViewScale= */ 1.0f,
- /* unused previewWidth= */ -1,
- /* unusedDp= */ null,
- /* unused previewPositionHelper= */ null
+ /* taskViewScale= */ 1.0f
)
assertThat(spyParams.mCurrentDrawnCornerRadius).isEqualTo(display1TaskRadius)
@@ -218,10 +123,7 @@ class FullscreenDrawParamsTest : FakeInvariantDeviceProfileTest() {
spyParams.setProgress(
/* fullscreenProgress= */ 0f,
/* parentScale= */ 1.0f,
- /* taskViewScale= */ 1.0f,
- /* unused previewWidth= */ -1,
- /* unusedDp= */ null,
- /* unused previewPositionHelper= */ null
+ /* taskViewScale= */ 1.0f
)
assertThat(spyParams.mCurrentDrawnCornerRadius).isEqualTo(display2TaskRadius)
}
@@ -243,10 +145,7 @@ class FullscreenDrawParamsTest : FakeInvariantDeviceProfileTest() {
spyParams.setProgress(
/* fullscreenProgress= */ 1.0f,
/* parentScale= */ 1.0f,
- /* taskViewScale= */ 1.0f,
- /* unused previewWidth= */ -1,
- /* unusedDp= */ null,
- /* unused previewPositionHelper= */ null
+ /* taskViewScale= */ 1.0f
)
assertThat(spyParams.mCurrentDrawnCornerRadius).isEqualTo(display1WindowRadius)
@@ -255,9 +154,6 @@ class FullscreenDrawParamsTest : FakeInvariantDeviceProfileTest() {
/* fullscreenProgress= */ 1.0f,
/* parentScale= */ 1.0f,
/* taskViewScale= */ 1.0f,
- /* unused previewWidth= */ -1,
- /* unusedDp= */ null,
- /* unused previewPositionHelper= */ null
)
assertThat(spyParams.mCurrentDrawnCornerRadius).isEqualTo(display2WindowRadius)
}
diff --git a/quickstep/tests/src/com/android/quickstep/NavigationModeSwitchRule.java b/quickstep/tests/src/com/android/quickstep/NavigationModeSwitchRule.java
index eded1c961f..df88726f68 100644
--- a/quickstep/tests/src/com/android/quickstep/NavigationModeSwitchRule.java
+++ b/quickstep/tests/src/com/android/quickstep/NavigationModeSwitchRule.java
@@ -185,7 +185,7 @@ public class NavigationModeSwitchRule implements TestRule {
+ launcher.getNavigationModeMismatchError(false),
() -> launcher.getNavigationModeMismatchError(false) == null,
WAIT_TIME_MS, launcher);
- AbstractLauncherUiTest.checkDetectedLeaks(launcher);
+ AbstractLauncherUiTest.checkDetectedLeaks(launcher, false);
return true;
}
diff --git a/quickstep/tests/src/com/android/quickstep/RecentsAnimationDeviceStateTest.kt b/quickstep/tests/src/com/android/quickstep/RecentsAnimationDeviceStateTest.kt
new file mode 100644
index 0000000000..53bc2a23f2
--- /dev/null
+++ b/quickstep/tests/src/com/android/quickstep/RecentsAnimationDeviceStateTest.kt
@@ -0,0 +1,144 @@
+package com.android.quickstep
+
+import android.content.Context
+import android.testing.AndroidTestingRunner
+import android.view.Display
+import android.view.IWindowManager
+import androidx.test.core.app.ApplicationProvider
+import androidx.test.filters.SmallTest
+import com.android.launcher3.util.DisplayController.CHANGE_DENSITY
+import com.android.launcher3.util.DisplayController.CHANGE_NAVIGATION_MODE
+import com.android.launcher3.util.DisplayController.CHANGE_ROTATION
+import com.android.launcher3.util.DisplayController.Info
+import com.android.launcher3.util.Executors
+import com.android.launcher3.util.NavigationMode
+import com.android.launcher3.util.window.WindowManagerProxy
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.Mockito.reset
+import org.mockito.Mockito.verify
+import org.mockito.MockitoAnnotations
+import org.mockito.kotlin.verifyZeroInteractions
+import org.mockito.kotlin.whenever
+
+/** Unit test for [RecentsAnimationDeviceState]. */
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+class RecentsAnimationDeviceStateTest {
+
+ @Mock private lateinit var windowManager: IWindowManager
+ @Mock private lateinit var windowManagerProxy: WindowManagerProxy
+ @Mock private lateinit var info: Info
+
+ private val context = ApplicationProvider.getApplicationContext() as Context
+ private lateinit var underTest: RecentsAnimationDeviceState
+
+ @Before
+ fun setup() {
+ MockitoAnnotations.initMocks(this)
+ underTest = RecentsAnimationDeviceState(context, windowManager)
+ }
+
+ @Test
+ fun registerExclusionListener_success() {
+ underTest.registerExclusionListener()
+
+ awaitTasksCompleted()
+ verify(windowManager)
+ .registerSystemGestureExclusionListener(
+ underTest.mGestureExclusionListener,
+ Display.DEFAULT_DISPLAY
+ )
+ }
+
+ @Test
+ fun registerExclusionListener_again_fail() {
+ underTest.registerExclusionListener()
+ awaitTasksCompleted()
+ reset(windowManager)
+
+ underTest.registerExclusionListener()
+
+ awaitTasksCompleted()
+ verifyZeroInteractions(windowManager)
+ }
+
+ @Test
+ fun unregisterExclusionListener_success() {
+ underTest.registerExclusionListener()
+ awaitTasksCompleted()
+ reset(windowManager)
+
+ underTest.unregisterExclusionListener()
+
+ awaitTasksCompleted()
+ verify(windowManager)
+ .unregisterSystemGestureExclusionListener(
+ underTest.mGestureExclusionListener,
+ Display.DEFAULT_DISPLAY
+ )
+ }
+
+ @Test
+ fun unregisterExclusionListener_again_fail() {
+ underTest.registerExclusionListener()
+ underTest.unregisterExclusionListener()
+ awaitTasksCompleted()
+ reset(windowManager)
+
+ underTest.unregisterExclusionListener()
+
+ awaitTasksCompleted()
+ verifyZeroInteractions(windowManager)
+ }
+
+ @Test
+ fun onDisplayInfoChanged_noButton_registerExclusionListener() {
+ whenever(windowManagerProxy.getNavigationMode(context)).thenReturn(NavigationMode.NO_BUTTON)
+
+ underTest.onDisplayInfoChanged(context, info, CHANGE_ROTATION or CHANGE_NAVIGATION_MODE)
+
+ awaitTasksCompleted()
+ verify(windowManager)
+ .registerSystemGestureExclusionListener(
+ underTest.mGestureExclusionListener,
+ Display.DEFAULT_DISPLAY
+ )
+ }
+
+ @Test
+ fun onDisplayInfoChanged_twoButton_unregisterExclusionListener() {
+ underTest.registerExclusionListener()
+ awaitTasksCompleted()
+ whenever(info.getNavigationMode()).thenReturn(NavigationMode.TWO_BUTTONS)
+ reset(windowManager)
+
+ underTest.onDisplayInfoChanged(context, info, CHANGE_ROTATION or CHANGE_NAVIGATION_MODE)
+
+ awaitTasksCompleted()
+ verify(windowManager)
+ .unregisterSystemGestureExclusionListener(
+ underTest.mGestureExclusionListener,
+ Display.DEFAULT_DISPLAY
+ )
+ }
+
+ @Test
+ fun onDisplayInfoChanged_changeDensity_noOp() {
+ underTest.registerExclusionListener()
+ awaitTasksCompleted()
+ whenever(info.getNavigationMode()).thenReturn(NavigationMode.NO_BUTTON)
+ reset(windowManager)
+
+ underTest.onDisplayInfoChanged(context, info, CHANGE_DENSITY)
+
+ awaitTasksCompleted()
+ verifyZeroInteractions(windowManager)
+ }
+
+ private fun awaitTasksCompleted() {
+ Executors.UI_HELPER_EXECUTOR.submit<Any> { null }.get()
+ }
+}
diff --git a/quickstep/tests/src/com/android/quickstep/RecentsModelTest.java b/quickstep/tests/src/com/android/quickstep/RecentsModelTest.java
new file mode 100644
index 0000000000..648fa932a6
--- /dev/null
+++ b/quickstep/tests/src/com/android/quickstep/RecentsModelTest.java
@@ -0,0 +1,173 @@
+/*
+ * Copyright (C) 2023 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.quickstep;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.ActivityManager;
+import android.content.Context;
+import android.content.res.Resources;
+import android.platform.test.flag.junit.SetFlagsRule;
+
+import androidx.test.annotation.UiThreadTest;
+import androidx.test.filters.SmallTest;
+
+import com.android.launcher3.Flags;
+import com.android.launcher3.R;
+import com.android.launcher3.icons.IconProvider;
+import com.android.quickstep.util.GroupTask;
+import com.android.systemui.shared.recents.model.Task;
+import com.android.systemui.shared.system.TaskStackChangeListeners;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.ArrayList;
+import java.util.function.Consumer;
+
+@SmallTest
+public class RecentsModelTest {
+ @Mock
+ private Context mContext;
+
+ @Mock
+ private TaskThumbnailCache mThumbnailCache;
+
+ @Mock
+ private RecentTasksList mTasksList;
+
+ @Mock
+ private TaskThumbnailCache.HighResLoadingState mHighResLoadingState;
+
+ private RecentsModel mRecentsModel;
+
+ private RecentTasksList.TaskLoadResult mTaskResult;
+
+ private Resources mResource;
+
+ @Rule
+ public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
+
+ @Before
+ public void setup() throws NoSuchFieldException {
+ MockitoAnnotations.initMocks(this);
+ mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_GRID_ONLY_OVERVIEW);
+ mTaskResult = getTaskResult();
+ doAnswer(invocation-> {
+ Consumer<ArrayList<GroupTask>> callback = invocation.getArgument(1);
+ callback.accept(mTaskResult);
+ return null;
+ }).when(mTasksList).getTaskKeys(anyInt(), any());
+
+ when(mHighResLoadingState.isEnabled()).thenReturn(true);
+ when(mThumbnailCache.getHighResLoadingState()).thenReturn(mHighResLoadingState);
+ when(mThumbnailCache.isPreloadingEnabled()).thenReturn(true);
+
+ mRecentsModel = new RecentsModel(mContext, mTasksList, mock(TaskIconCache.class),
+ mThumbnailCache, mock(IconProvider.class), mock(TaskStackChangeListeners.class));
+
+ mResource = mock(Resources.class);
+ when(mResource.getInteger((R.integer.recentsThumbnailCacheSize))).thenReturn(3);
+ when(mContext.getResources()).thenReturn(mResource);
+ }
+
+ @Test
+ @UiThreadTest
+ public void preloadOnHighResolutionEnabled() {
+ mRecentsModel.preloadCacheIfNeeded();
+
+ ArgumentCaptor<Task> taskArgs = ArgumentCaptor.forClass(Task.class);
+ verify(mRecentsModel.getThumbnailCache(), times(2))
+ .updateThumbnailInCache(taskArgs.capture(), /* lowResolution= */ eq(false));
+
+ GroupTask expectedGroupTask = mTaskResult.get(0);
+ assertThat(taskArgs.getAllValues().get(0)).isEqualTo(
+ expectedGroupTask.task1);
+ assertThat(taskArgs.getAllValues().get(1)).isEqualTo(
+ expectedGroupTask.task2);
+ }
+
+ @Test
+ public void notPreloadOnHighResolutionDisabled() {
+ when(mHighResLoadingState.isEnabled()).thenReturn(false);
+ when(mThumbnailCache.isPreloadingEnabled()).thenReturn(true);
+ mRecentsModel.preloadCacheIfNeeded();
+ verify(mRecentsModel.getThumbnailCache(), never())
+ .updateThumbnailInCache(any(), anyBoolean());
+ }
+
+ @Test
+ public void notPreloadOnPreloadDisabled() {
+ when(mThumbnailCache.isPreloadingEnabled()).thenReturn(false);
+ mRecentsModel.preloadCacheIfNeeded();
+ verify(mRecentsModel.getThumbnailCache(), never())
+ .updateThumbnailInCache(any(), anyBoolean());
+
+ }
+
+ @Test
+ public void increaseCacheSizeAndPreload() {
+ // Mock to return preload is needed
+ when(mThumbnailCache.updateCacheSizeAndRemoveExcess()).thenReturn(true);
+ // Update cache size
+ mRecentsModel.updateCacheSizeAndPreloadIfNeeded();
+ // Assert update cache is called
+ verify(mRecentsModel.getThumbnailCache(), times(2))
+ .updateThumbnailInCache(any(), /* lowResolution= */ eq(false));
+ }
+
+ @Test
+ public void decreaseCacheSizeAndNotPreload() {
+ // Mock to return preload is not needed
+ when(mThumbnailCache.updateCacheSizeAndRemoveExcess()).thenReturn(false);
+ // Update cache size
+ mRecentsModel.updateCacheSizeAndPreloadIfNeeded();
+ // Assert update cache is never called
+ verify(mRecentsModel.getThumbnailCache(), never())
+ .updateThumbnailInCache(any(), anyBoolean());
+ }
+
+ private RecentTasksList.TaskLoadResult getTaskResult() {
+ RecentTasksList.TaskLoadResult allTasks = new RecentTasksList.TaskLoadResult(0, false, 1);
+ ActivityManager.RecentTaskInfo taskInfo1 = new ActivityManager.RecentTaskInfo();
+ Task.TaskKey taskKey1 = new Task.TaskKey(taskInfo1);
+ Task task1 = Task.from(taskKey1, taskInfo1, false);
+
+ ActivityManager.RecentTaskInfo taskInfo2 = new ActivityManager.RecentTaskInfo();
+ Task.TaskKey taskKey2 = new Task.TaskKey(taskInfo2);
+ Task task2 = Task.from(taskKey2, taskInfo2, false);
+
+ allTasks.add(new GroupTask(task1, task2, null));
+ return allTasks;
+ }
+}
diff --git a/quickstep/tests/src/com/android/quickstep/DigitalWellBeingToastTest.java b/quickstep/tests/src/com/android/quickstep/TaplDigitalWellBeingToastTest.java
index 1129a337e3..728fe6741d 100644
--- a/quickstep/tests/src/com/android/quickstep/DigitalWellBeingToastTest.java
+++ b/quickstep/tests/src/com/android/quickstep/TaplDigitalWellBeingToastTest.java
@@ -1,3 +1,18 @@
+/*
+ * Copyright (C) 2023 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.quickstep;
import static androidx.test.InstrumentationRegistry.getInstrumentation;
@@ -27,7 +42,7 @@ import java.time.Duration;
@LargeTest
@RunWith(AndroidJUnit4.class)
-public class DigitalWellBeingToastTest extends AbstractQuickStepTest {
+public class TaplDigitalWellBeingToastTest extends AbstractQuickStepTest {
private static final String CALCULATOR_PACKAGE =
resolveSystemApp(Intent.CATEGORY_APP_CALCULATOR);
diff --git a/quickstep/tests/src/com/android/quickstep/TaplOverviewIconTest.java b/quickstep/tests/src/com/android/quickstep/TaplOverviewIconTest.java
new file mode 100644
index 0000000000..3f806d1764
--- /dev/null
+++ b/quickstep/tests/src/com/android/quickstep/TaplOverviewIconTest.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2023 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.quickstep;
+
+import static com.android.launcher3.ui.AbstractLauncherUiTest.initialize;
+import static com.android.launcher3.util.rule.TestStabilityRule.LOCAL;
+import static com.android.launcher3.util.rule.TestStabilityRule.PLATFORM_POSTSUBMIT;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import android.content.Intent;
+import android.platform.test.annotations.PlatinumTest;
+
+import com.android.launcher3.tapl.OverviewTaskMenu;
+import com.android.launcher3.ui.AbstractLauncherUiTest;
+import com.android.launcher3.util.rule.TestStabilityRule;
+
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * This test run in both Out of process (Oop) and in-process (Ipc).
+ * Tests the app Icon in overview.
+ */
+public class TaplOverviewIconTest extends AbstractLauncherUiTest {
+
+ private static final String CALCULATOR_APP_PACKAGE =
+ resolveSystemApp(Intent.CATEGORY_APP_CALCULATOR);
+
+ @Before
+ public void setUp() throws Exception {
+ super.setUp();
+ initialize(this);
+ }
+
+ @PlatinumTest(focusArea = "launcher")
+ @Test
+ public void testOverviewActionsMenu() {
+ startTestAppsWithCheck();
+
+ OverviewTaskMenu menu = mLauncher.goHome().switchToOverview().getCurrentTask().tapMenu();
+
+ assertNotNull("Tapping App info menu item returned null", menu.tapAppInfoMenuItem());
+ executeOnLauncher(launcher -> assertTrue(
+ "Launcher activity is the top activity; expecting another activity to be the top",
+ isInLaunchedApp(launcher)));
+ }
+
+ private void startTestAppsWithCheck() {
+ startTestApps();
+ executeOnLauncher(launcher -> assertTrue(
+ "Launcher activity is the top activity; expecting another activity to be the top "
+ + "one",
+ isInLaunchedApp(launcher)));
+ }
+
+ private void startTestApps() {
+ startAppFast(getAppPackageName());
+ startAppFast(CALCULATOR_APP_PACKAGE);
+ startTestActivity(2);
+ }
+
+ @Test
+ @TestStabilityRule.Stability(flavors = LOCAL | PLATFORM_POSTSUBMIT) // b/288939273
+ public void testSplitTaskTapBothIconMenus() {
+ createAndLaunchASplitPair();
+
+ OverviewTaskMenu taskMenu =
+ mLauncher.goHome().switchToOverview().getCurrentTask().tapMenu();
+ assertTrue("App info item not appearing in expanded task menu.",
+ taskMenu.hasMenuItem("App info"));
+ taskMenu.touchOutsideTaskMenuToDismiss();
+
+ OverviewTaskMenu splitMenu =
+ mLauncher.goHome().switchToOverview().getCurrentTask().tapSplitTaskMenu();
+ assertTrue("App info item not appearing in expanded split task's menu.",
+ splitMenu.hasMenuItem("App info"));
+ splitMenu.touchOutsideTaskMenuToDismiss();
+ }
+
+ private void createAndLaunchASplitPair() {
+ startTestActivity(2);
+ startTestActivity(3);
+
+ if (mLauncher.isTablet() && !mLauncher.isGridOnlyOverviewEnabled()) {
+ mLauncher.goHome().switchToOverview().getOverviewActions()
+ .clickSplit()
+ .getTestActivityTask(2)
+ .open();
+ } else {
+ mLauncher.goHome().switchToOverview().getCurrentTask()
+ .tapMenu()
+ .tapSplitMenuItem()
+ .getCurrentTask()
+ .open();
+ }
+ }
+}
diff --git a/quickstep/tests/src/com/android/quickstep/StartLauncherViaGestureTests.java b/quickstep/tests/src/com/android/quickstep/TaplStartLauncherViaGestureTests.java
index 20aa410f8f..7e274e8833 100644
--- a/quickstep/tests/src/com/android/quickstep/StartLauncherViaGestureTests.java
+++ b/quickstep/tests/src/com/android/quickstep/TaplStartLauncherViaGestureTests.java
@@ -22,7 +22,7 @@ import static com.android.launcher3.util.rule.TestStabilityRule.PLATFORM_POSTSUB
import androidx.test.filters.LargeTest;
import androidx.test.runner.AndroidJUnit4;
-import com.android.launcher3.ui.TaplTestsLauncher3;
+import com.android.launcher3.ui.AbstractLauncherUiTest;
import com.android.launcher3.util.rule.TestStabilityRule.Stability;
import com.android.quickstep.NavigationModeSwitchRule.NavigationModeSwitch;
@@ -32,7 +32,7 @@ import org.junit.runner.RunWith;
@LargeTest
@RunWith(AndroidJUnit4.class)
-public class StartLauncherViaGestureTests extends AbstractQuickStepTest {
+public class TaplStartLauncherViaGestureTests extends AbstractQuickStepTest {
static final int STRESS_REPEAT_COUNT = 10;
@@ -40,7 +40,7 @@ public class StartLauncherViaGestureTests extends AbstractQuickStepTest {
@Before
public void setUp() throws Exception {
super.setUp();
- TaplTestsLauncher3.initialize(this);
+ AbstractLauncherUiTest.initialize(this);
// b/143488140
mLauncher.goHome();
// Start an activity where the gestures start.
@@ -49,7 +49,8 @@ public class StartLauncherViaGestureTests extends AbstractQuickStepTest {
@Test
@NavigationModeSwitch
- @Stability(flavors = LOCAL | PLATFORM_POSTSUBMIT) // b/187761685
+ // Stress tests are long. We permanently demote them from presubmit to match the presubmit SLO.
+ @Stability(flavors = LOCAL | PLATFORM_POSTSUBMIT)
public void testStressPressHome() {
for (int i = 0; i < STRESS_REPEAT_COUNT; ++i) {
// Destroy Launcher activity.
@@ -62,7 +63,8 @@ public class StartLauncherViaGestureTests extends AbstractQuickStepTest {
@Test
@NavigationModeSwitch
- @Stability(flavors = LOCAL | PLATFORM_POSTSUBMIT) // b/187761685
+ // Stress tests are long. We permanently demote them from presubmit to match the presubmit SLO.
+ @Stability(flavors = LOCAL | PLATFORM_POSTSUBMIT)
public void testStressSwipeToOverview() {
for (int i = 0; i < STRESS_REPEAT_COUNT; ++i) {
// Destroy Launcher activity.
diff --git a/quickstep/tests/src/com/android/quickstep/TaplTestsKeyboardQuickSwitch.java b/quickstep/tests/src/com/android/quickstep/TaplTestsKeyboardQuickSwitch.java
new file mode 100644
index 0000000000..829e54bdff
--- /dev/null
+++ b/quickstep/tests/src/com/android/quickstep/TaplTestsKeyboardQuickSwitch.java
@@ -0,0 +1,187 @@
+/*
+ * Copyright (C) 2023 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.quickstep;
+
+import android.content.Intent;
+
+import androidx.annotation.NonNull;
+import androidx.test.filters.LargeTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.launcher3.tapl.KeyboardQuickSwitch;
+import com.android.launcher3.ui.AbstractLauncherUiTest;
+
+import org.junit.Assume;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@LargeTest
+@RunWith(AndroidJUnit4.class)
+public class TaplTestsKeyboardQuickSwitch extends AbstractQuickStepTest {
+
+ private enum TestSurface {
+ HOME, LAUNCHED_APP, HOME_ALL_APPS, WIDGETS,
+ }
+
+ private enum TestCase {
+ DISMISS(0),
+ LAUNCH_LAST_APP(0),
+ LAUNCH_SELECTED_APP(1),
+ LAUNCH_OVERVIEW(5);
+
+ private final int mNumAdditionalRunningTasks;
+
+ TestCase(int numAdditionalRunningTasks) {
+ mNumAdditionalRunningTasks = numAdditionalRunningTasks;
+ }
+ }
+
+ private static final String CALCULATOR_APP_PACKAGE =
+ resolveSystemApp(Intent.CATEGORY_APP_CALCULATOR);
+
+ @Override
+ public void setUp() throws Exception {
+ Assume.assumeTrue(mLauncher.isTablet());
+ super.setUp();
+ AbstractLauncherUiTest.initialize(this);
+ startAppFast(CALCULATOR_APP_PACKAGE);
+ startTestActivity(2);
+ }
+
+ @Test
+ public void testDismiss_fromHome() {
+ runTest(TestSurface.HOME, TestCase.DISMISS);
+ }
+
+ @Test
+ public void testDismiss_fromApp() {
+ runTest(TestSurface.LAUNCHED_APP, TestCase.DISMISS);
+ }
+
+ @Test
+ public void testDismiss_fromHomeAllApps() {
+ runTest(TestSurface.HOME_ALL_APPS, TestCase.DISMISS);
+ }
+
+ @Test
+ public void testDismiss_fromWidgets() {
+ runTest(TestSurface.WIDGETS, TestCase.DISMISS);
+ }
+
+ @Test
+ public void testLaunchLastTask_fromHome() {
+ runTest(TestSurface.HOME, TestCase.LAUNCH_LAST_APP);
+ }
+
+ @Test
+ public void testLaunchLastTask_fromApp() {
+ runTest(TestSurface.LAUNCHED_APP, TestCase.LAUNCH_LAST_APP);
+ }
+
+ @Test
+ public void testLaunchLastTask_fromHomeAllApps() {
+ runTest(TestSurface.HOME_ALL_APPS, TestCase.LAUNCH_LAST_APP);
+ }
+
+ @Test
+ public void testLaunchLastTask_fromWidgets() {
+ runTest(TestSurface.WIDGETS, TestCase.LAUNCH_LAST_APP);
+ }
+
+ @Test
+ public void testLaunchSelectedTask_fromHome() {
+ runTest(TestSurface.HOME, TestCase.LAUNCH_SELECTED_APP);
+ }
+
+ @Test
+ public void testLaunchSelectedTask_fromApp() {
+ runTest(TestSurface.LAUNCHED_APP, TestCase.LAUNCH_SELECTED_APP);
+ }
+
+ @Test
+ public void testLaunchSelectedTask_fromHomeAllApps() {
+ runTest(TestSurface.HOME_ALL_APPS, TestCase.LAUNCH_SELECTED_APP);
+ }
+
+ @Test
+ public void testLaunchSelectedTask_fromWidgets() {
+ runTest(TestSurface.WIDGETS, TestCase.LAUNCH_SELECTED_APP);
+ }
+
+ @Test
+ public void testLaunchOverviewTask_fromHome() {
+ runTest(TestSurface.HOME, TestCase.LAUNCH_OVERVIEW);
+ }
+
+ @Test
+ public void testLaunchOverviewTask_fromApp() {
+ runTest(TestSurface.LAUNCHED_APP, TestCase.LAUNCH_OVERVIEW);
+ }
+
+ @Test
+ public void testLaunchOverviewTask_fromHomeAllApps() {
+ runTest(TestSurface.HOME_ALL_APPS, TestCase.LAUNCH_OVERVIEW);
+ }
+
+ @Test
+ public void testLaunchOverviewTask_fromWidgets() {
+ runTest(TestSurface.WIDGETS, TestCase.LAUNCH_OVERVIEW);
+ }
+
+ private void runTest(@NonNull TestSurface testSurface, @NonNull TestCase testCase) {
+ for (int i = 0; i < testCase.mNumAdditionalRunningTasks; i++) {
+ startTestActivity(3 + i);
+ }
+
+ KeyboardQuickSwitch kqs;
+ switch (testSurface) {
+ case HOME:
+ kqs = mLauncher.goHome().showQuickSwitchView();
+ break;
+ case LAUNCHED_APP:
+ mLauncher.setIgnoreTaskbarVisibility(true);
+ kqs = mLauncher.getLaunchedAppState().showQuickSwitchView();
+ break;
+ case HOME_ALL_APPS:
+ kqs = mLauncher.goHome().switchToAllApps().showQuickSwitchView();
+ break;
+ case WIDGETS:
+ kqs = mLauncher.goHome().openAllWidgets().showQuickSwitchView();
+ break;
+ default:
+ throw new IllegalStateException(
+ "KeyboardQuickSwitch could not be initialized for test surface: "
+ + testSurface);
+ }
+
+ switch (testCase) {
+ case DISMISS:
+ kqs.dismiss();
+ break;
+ case LAUNCH_LAST_APP:
+ kqs.launchFocusedAppTask(CALCULATOR_APP_PACKAGE);
+ break;
+ case LAUNCH_SELECTED_APP:
+ kqs.moveFocusForward().launchFocusedAppTask(CALCULATOR_APP_PACKAGE);
+ break;
+ case LAUNCH_OVERVIEW:
+ kqs.moveFocusBackward().moveFocusBackward().launchFocusedOverviewTask();
+ break;
+ default:
+ throw new IllegalStateException("Cannot run test case: " + testCase);
+ }
+ }
+}
diff --git a/quickstep/tests/src/com/android/quickstep/TaplTestsPersistentTaskbar.java b/quickstep/tests/src/com/android/quickstep/TaplTestsPersistentTaskbar.java
index 1b5313bad0..c9e536a737 100644
--- a/quickstep/tests/src/com/android/quickstep/TaplTestsPersistentTaskbar.java
+++ b/quickstep/tests/src/com/android/quickstep/TaplTestsPersistentTaskbar.java
@@ -20,6 +20,8 @@ import static com.android.quickstep.TaskbarModeSwitchRule.Mode.PERSISTENT;
import androidx.test.filters.LargeTest;
import androidx.test.runner.AndroidJUnit4;
+import com.android.launcher3.ui.PortraitLandscapeRunner.PortraitLandscape;
+import com.android.quickstep.NavigationModeSwitchRule.NavigationModeSwitch;
import com.android.quickstep.TaskbarModeSwitchRule.TaskbarModeSwitch;
import org.junit.Test;
@@ -31,16 +33,10 @@ public class TaplTestsPersistentTaskbar extends AbstractTaplTestsTaskbar {
@Test
@TaskbarModeSwitch(mode = PERSISTENT)
- public void testHideShowTaskbar() {
- getTaskbar().hide();
- mLauncher.getLaunchedAppState().showTaskbar();
- }
-
- @Test
- @TaskbarModeSwitch(mode = PERSISTENT)
- public void testHideTaskbarPersistsOnRecreate() {
- getTaskbar().hide();
- mLauncher.recreateTaskbar();
- mLauncher.getLaunchedAppState().assertTaskbarHidden();
+ @PortraitLandscape
+ @NavigationModeSwitch
+ public void testTaskbarFillsWidth() {
+ // Width check is performed inside TAPL whenever getTaskbar() is called.
+ getTaskbar();
}
}
diff --git a/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java b/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
index 25f90caa3e..6cbe1712e0 100644
--- a/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
+++ b/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
@@ -16,11 +16,9 @@
package com.android.quickstep;
-import static com.android.launcher3.testing.shared.TestProtocol.FLAKY_QUICK_SWITCH_TO_PREVIOUS_APP;
-import static com.android.launcher3.ui.TaplTestsLauncher3.getAppPackageName;
import static com.android.launcher3.util.rule.TestStabilityRule.LOCAL;
import static com.android.launcher3.util.rule.TestStabilityRule.PLATFORM_POSTSUBMIT;
-import static com.android.quickstep.TaskbarModeSwitchRule.Mode.PERSISTENT;
+import static com.android.quickstep.TaskbarModeSwitchRule.Mode.TRANSIENT;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
@@ -29,8 +27,8 @@ import static org.junit.Assume.assumeFalse;
import static org.junit.Assume.assumeTrue;
import android.content.Intent;
+import android.content.res.Configuration;
import android.platform.test.annotations.PlatinumTest;
-import android.util.Log;
import androidx.test.filters.LargeTest;
import androidx.test.platform.app.InstrumentationRegistry;
@@ -46,10 +44,8 @@ import com.android.launcher3.tapl.LauncherInstrumentation.NavigationModel;
import com.android.launcher3.tapl.Overview;
import com.android.launcher3.tapl.OverviewActions;
import com.android.launcher3.tapl.OverviewTask;
-import com.android.launcher3.tapl.OverviewTaskMenu;
+import com.android.launcher3.ui.AbstractLauncherUiTest;
import com.android.launcher3.ui.PortraitLandscapeRunner.PortraitLandscape;
-import com.android.launcher3.ui.TaplTestsLauncher3;
-import com.android.launcher3.util.DisplayController;
import com.android.launcher3.util.Wait;
import com.android.launcher3.util.rule.ScreenRecordRule.ScreenRecord;
import com.android.launcher3.util.rule.TestStabilityRule;
@@ -67,7 +63,6 @@ import org.junit.runner.RunWith;
@RunWith(AndroidJUnit4.class)
public class TaplTestsQuickstep extends AbstractQuickStepTest {
- private static final String APP_NAME = "LauncherTestApp";
private static final String CALCULATOR_APP_PACKAGE =
resolveSystemApp(Intent.CATEGORY_APP_CALCULATOR);
private static final String READ_DEVICE_CONFIG_PERMISSION =
@@ -76,7 +71,7 @@ public class TaplTestsQuickstep extends AbstractQuickStepTest {
@Before
public void setUp() throws Exception {
super.setUp();
- TaplTestsLauncher3.initialize(this);
+ AbstractLauncherUiTest.initialize(this);
executeOnLauncher(launcher -> {
RecentsView recentsView = launcher.getOverviewPanel();
recentsView.getPagedViewOrientedState().forceAllowRotationForTesting(true);
@@ -85,7 +80,7 @@ public class TaplTestsQuickstep extends AbstractQuickStepTest {
@After
public void tearDown() {
- executeOnLauncher(launcher -> {
+ executeOnLauncherInTearDown(launcher -> {
RecentsView recentsView = launcher.getOverviewPanel();
recentsView.getPagedViewOrientedState().forceAllowRotationForTesting(false);
});
@@ -108,7 +103,6 @@ public class TaplTestsQuickstep extends AbstractQuickStepTest {
@Test
@NavigationModeSwitch
@PortraitLandscape
- @PlatinumTest(focusArea = "launcher")
public void testWorkspaceSwitchToAllApps() {
assertNotNull("switchToAllApps() returned null",
mLauncher.getWorkspace().switchToAllApps());
@@ -185,8 +179,9 @@ public class TaplTestsQuickstep extends AbstractQuickStepTest {
@Test
@NavigationModeSwitch
@PortraitLandscape
- @PlatinumTest(focusArea = "launcher")
public void testOverviewActions() throws Exception {
+ assumeFalse("Skipping Overview Actions tests for grid only overview",
+ mLauncher.isTablet() && mLauncher.isGridOnlyOverviewEnabled());
// Experimenting for b/165029151:
final Overview overview = mLauncher.goHome().switchToOverview();
if (overview.hasTasks()) overview.dismissAllTasks();
@@ -199,19 +194,6 @@ public class TaplTestsQuickstep extends AbstractQuickStepTest {
actionsView.clickAndDismissScreenshot();
}
-
- @Test
- public void testOverviewActionsMenu() throws Exception {
- startTestAppsWithCheck();
-
- OverviewTaskMenu menu = mLauncher.goHome().switchToOverview().getCurrentTask().tapMenu();
-
- assertNotNull("Tapping App info menu item returned null", menu.tapAppInfoMenuItem());
- executeOnLauncher(launcher -> assertTrue(
- "Launcher activity is the top activity; expecting another activity to be the top",
- isInLaunchedApp(launcher)));
- }
-
private int getCurrentOverviewPage(Launcher launcher) {
return launcher.<RecentsView>getOverviewPanel().getCurrentPage();
}
@@ -233,7 +215,6 @@ public class TaplTestsQuickstep extends AbstractQuickStepTest {
@NavigationModeSwitch
@PortraitLandscape
@ScreenRecord // b/238461765
- @PlatinumTest(focusArea = "launcher")
public void testSwitchToOverview() throws Exception {
startTestAppsWithCheck();
assertNotNull("Workspace.switchToOverview() returned null",
@@ -242,11 +223,23 @@ public class TaplTestsQuickstep extends AbstractQuickStepTest {
isInState(() -> LauncherState.OVERVIEW));
}
+ @Test
+ @TaskbarModeSwitch(mode = TRANSIENT)
+ public void testSwitchToOverviewWithStashedTaskbar() throws Exception {
+ try {
+ startTestAppsWithCheck();
+ // Set ignoreTaskbarVisibility, as transient taskbar will be stashed after app launch.
+ mLauncher.setIgnoreTaskbarVisibility(true);
+ mLauncher.getLaunchedAppState().switchToOverview();
+ } finally {
+ mLauncher.setIgnoreTaskbarVisibility(false);
+ }
+ }
+
@Ignore
@Test
@NavigationModeSwitch
@PortraitLandscape
- @PlatinumTest(focusArea = "launcher")
public void testBackground() throws Exception {
startAppFast(CALCULATOR_APP_PACKAGE);
final LaunchedAppState launchedAppState = getAndAssertLaunchedApp();
@@ -271,27 +264,8 @@ public class TaplTestsQuickstep extends AbstractQuickStepTest {
}
@Test
- @PortraitLandscape
- public void testAllAppsFromHome() throws Exception {
- // Test opening all apps
- assertNotNull("switchToAllApps() returned null",
- mLauncher.getWorkspace().switchToAllApps());
-
- TaplTestsLauncher3.runAllAppsTest(this, mLauncher.getAllApps());
-
- // Testing pressHome.
- assertTrue("Launcher internal state is not All Apps",
- isInState(() -> LauncherState.ALL_APPS));
- assertNotNull("pressHome returned null", mLauncher.goHome());
- assertTrue("Launcher internal state is not Home",
- isInState(() -> LauncherState.NORMAL));
- assertNotNull("getHome returned null", mLauncher.getWorkspace());
- }
-
- @Test
@NavigationModeSwitch
@PortraitLandscape
- @PlatinumTest(focusArea = "launcher")
public void testQuickSwitchFromApp() throws Exception {
startTestActivity(2);
startTestActivity(3);
@@ -320,9 +294,8 @@ public class TaplTestsQuickstep extends AbstractQuickStepTest {
}
@Test
- @ScreenRecord // b/242163205
- @PlatinumTest(focusArea = "launcher")
- @TestStabilityRule.Stability(flavors = LOCAL | PLATFORM_POSTSUBMIT) // b/286084688
+ @TaskbarModeSwitch
+ @Ignore // b/314873201
public void testQuickSwitchToPreviousAppForTablet() throws Exception {
assumeTrue(mLauncher.isTablet());
startTestActivity(2);
@@ -331,33 +304,43 @@ public class TaplTestsQuickstep extends AbstractQuickStepTest {
// Set ignoreTaskbarVisibility to true to verify the task bar visibility explicitly.
mLauncher.setIgnoreTaskbarVisibility(true);
- // Expect task bar invisible when the launched app was the IME activity.
- LaunchedAppState launchedAppState = getAndAssertLaunchedApp();
- launchedAppState.assertTaskbarHidden();
- // Quick-switch to the test app with swiping to right.
- quickSwitchToPreviousAppAndAssert(true /* toRight */);
+ try {
+ boolean isTransientTaskbar = mLauncher.isTransientTaskbar();
+ // Expect task bar invisible when the launched app was the IME activity.
+ LaunchedAppState launchedAppState = getAndAssertLaunchedApp();
+ if (!isTransientTaskbar && isHardwareKeyboard()) {
+ launchedAppState.assertTaskbarVisible();
+ } else {
+ launchedAppState.assertTaskbarHidden();
+ }
+
+ // Quick-switch to the test app with swiping to right.
+ quickSwitchToPreviousAppAndAssert(true /* toRight */);
- assertTestActivityIsRunning(2,
- "The first app we should have quick switched to is not running");
- // Expect task bar visible when the launched app was the test activity.
- launchedAppState = getAndAssertLaunchedApp();
-
- Log.e(FLAKY_QUICK_SWITCH_TO_PREVIOUS_APP,
- "is Taskbar Transient : " + DisplayController.isTransientTaskbar(mTargetContext));
- // TODO(b/286084688): Remove this branching check after test corruption is resolved.
- // Branching this check because of test corruption.
- if (DisplayController.isTransientTaskbar(mTargetContext)) {
- launchedAppState.assertTaskbarHidden();
- } else {
- launchedAppState.assertTaskbarVisible();
+ assertTestActivityIsRunning(2,
+ "The first app we should have quick switched to is not running");
+ launchedAppState = getAndAssertLaunchedApp();
+ if (isTransientTaskbar) {
+ launchedAppState.assertTaskbarHidden();
+ } else {
+ // Expect taskbar visible when the launched app was the test activity.
+ launchedAppState.assertTaskbarVisible();
+ }
+ } finally {
+ // Reset ignoreTaskbarVisibility to ensure other tests still verify it.
+ mLauncher.setIgnoreTaskbarVisibility(false);
}
}
+ private boolean isHardwareKeyboard() {
+ return Configuration.KEYBOARD_QWERTY
+ == mTargetContext.getResources().getConfiguration().keyboard;
+ }
+
@Test
@NavigationModeSwitch
@PortraitLandscape
- @PlatinumTest(focusArea = "launcher")
public void testQuickSwitchFromHome() throws Exception {
startTestActivity(2);
mLauncher.goHome().quickSwitchToPreviousApp();
@@ -369,10 +352,11 @@ public class TaplTestsQuickstep extends AbstractQuickStepTest {
@Test
@PortraitLandscape
@NavigationModeSwitch
- @PlatinumTest(focusArea = "launcher")
public void testPressBack() throws Exception {
InstrumentationRegistry.getInstrumentation().getUiAutomation().adoptShellPermissionIdentity(
READ_DEVICE_CONFIG_PERMISSION);
+ // Debug if we need to goHome to prevent wrong previous state b/315525621
+ mLauncher.goHome();
assumeFalse(FeatureFlags.ENABLE_BACK_SWIPE_LAUNCHER_ANIMATION.get());
mLauncher.getWorkspace().switchToAllApps();
mLauncher.pressBack();
@@ -387,8 +371,10 @@ public class TaplTestsQuickstep extends AbstractQuickStepTest {
@Test
@PortraitLandscape
- @TaskbarModeSwitch(mode = PERSISTENT)
+ @TaskbarModeSwitch()
@PlatinumTest(focusArea = "launcher")
+ @TestStabilityRule.Stability(flavors = LOCAL | PLATFORM_POSTSUBMIT) // b/309820115
+ @ScreenRecord // b/309820115
public void testOverviewForTablet() throws Exception {
assumeTrue(mLauncher.isTablet());
@@ -411,7 +397,9 @@ public class TaplTestsQuickstep extends AbstractQuickStepTest {
// Test opening the task.
overview.getCurrentTask().open();
assertTrue("Test activity didn't open from Overview",
- mDevice.wait(Until.hasObject(By.pkg(getAppPackageName()).text("TestActivity10")),
+ mDevice.wait(Until.hasObject(By.pkg(getAppPackageName()).text(
+ mLauncher.isGridOnlyOverviewEnabled() ? "TestActivity12"
+ : "TestActivity13")),
DEFAULT_UI_TIMEOUT));
// Scroll the task offscreen as it is now first
@@ -432,16 +420,17 @@ public class TaplTestsQuickstep extends AbstractQuickStepTest {
(Math.abs(getTopRowTaskCountForTablet(launcher) - getBottomRowTaskCountForTablet(
launcher)) <= 1)));
- // Test dismissing more tasks.
- assertTrue("Launcher internal state didn't remain in Overview",
- isInState(() -> LauncherState.OVERVIEW));
- overview.getCurrentTask().dismiss();
- assertTrue("Launcher internal state didn't remain in Overview",
- isInState(() -> LauncherState.OVERVIEW));
- overview.getCurrentTask().dismiss();
- executeOnLauncher(launcher -> assertTrue("Grid did not rebalance after multiple dismissals",
- (Math.abs(getTopRowTaskCountForTablet(launcher) - getBottomRowTaskCountForTablet(
- launcher)) <= 1)));
+ // TODO(b/308841019): Re-enable after fixing Overview jank when dismiss
+// // Test dismissing more tasks.
+// assertTrue("Launcher internal state didn't remain in Overview",
+// isInState(() -> LauncherState.OVERVIEW));
+// overview.getCurrentTask().dismiss();
+// assertTrue("Launcher internal state didn't remain in Overview",
+// isInState(() -> LauncherState.OVERVIEW));
+// overview.getCurrentTask().dismiss();
+// executeOnLauncher(launcher -> assertTrue("Grid did not rebalance after multiple dismissals",
+// (Math.abs(getTopRowTaskCountForTablet(launcher) - getBottomRowTaskCountForTablet(
+// launcher)) <= 1)));
// Test dismissing all tasks.
mLauncher.goHome().switchToOverview().dismissAllTasks();
@@ -478,6 +467,7 @@ public class TaplTestsQuickstep extends AbstractQuickStepTest {
@Test
@PortraitLandscape
+ @TaskbarModeSwitch
public void testTaskbarDeadzonesForTablet() throws Exception {
assumeTrue(mLauncher.isTablet());
@@ -490,19 +480,32 @@ public class TaplTestsQuickstep extends AbstractQuickStepTest {
launcher -> assertTrue("Should have at least 3 tasks",
getTaskCount(launcher) >= 3));
- // On persistent taskbar, it should not dismiss when tapping the taskbar
- overview.touchTaskbarBottomCorner(/* tapRight= */ false);
- assertTrue("Launcher internal state should be Overview",
- isInState(() -> LauncherState.OVERVIEW));
+ if (mLauncher.isTransientTaskbar()) {
+ // On transient taskbar, it should dismiss when tapping outside taskbar bounds.
+ overview.touchTaskbarBottomCorner(/* tapRight= */ false);
+ assertTrue("Launcher internal state should be Normal",
+ isInState(() -> LauncherState.NORMAL));
- // On persistent taskbar, it should not dismiss when tapping the taskbar
- overview.touchTaskbarBottomCorner(/* tapRight= */ true);
- assertTrue("Launcher internal state should be Overview",
- isInState(() -> LauncherState.OVERVIEW));
+ overview = mLauncher.getWorkspace().switchToOverview();
+
+ // On transient taskbar, it should dismiss when tapping outside taskbar bounds.
+ overview.touchTaskbarBottomCorner(/* tapRight= */ true);
+ assertTrue("Launcher internal state should be Normal",
+ isInState(() -> LauncherState.NORMAL));
+ } else {
+ // On persistent taskbar, it should not dismiss when tapping the taskbar
+ overview.touchTaskbarBottomCorner(/* tapRight= */ false);
+ assertTrue("Launcher internal state should be Overview",
+ isInState(() -> LauncherState.OVERVIEW));
+
+ // On persistent taskbar, it should not dismiss when tapping the taskbar
+ overview.touchTaskbarBottomCorner(/* tapRight= */ true);
+ assertTrue("Launcher internal state should be Overview",
+ isInState(() -> LauncherState.OVERVIEW));
+ }
}
@Test
- @ScreenRecord // b/242163205
public void testDisableRotationCheckForPhone() throws Exception {
assumeFalse(mLauncher.isTablet());
try {
diff --git a/quickstep/tests/src/com/android/quickstep/TaplTestsSplitscreen.java b/quickstep/tests/src/com/android/quickstep/TaplTestsSplitscreen.java
index 92b598b626..1e33635a23 100644
--- a/quickstep/tests/src/com/android/quickstep/TaplTestsSplitscreen.java
+++ b/quickstep/tests/src/com/android/quickstep/TaplTestsSplitscreen.java
@@ -29,11 +29,14 @@ import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.LargeTest;
import androidx.test.platform.app.InstrumentationRegistry;
-import com.android.launcher3.config.FeatureFlags;
+import com.android.launcher3.tapl.Overview;
+import com.android.launcher3.tapl.Taskbar;
+import com.android.launcher3.tapl.TaskbarAppIcon;
+import com.android.launcher3.ui.AbstractLauncherUiTest;
import com.android.launcher3.ui.PortraitLandscapeRunner.PortraitLandscape;
-import com.android.launcher3.ui.TaplTestsLauncher3;
import com.android.launcher3.util.rule.TestStabilityRule;
import com.android.quickstep.TaskbarModeSwitchRule.TaskbarModeSwitch;
+import com.android.wm.shell.Flags;
import org.junit.After;
import org.junit.Before;
@@ -54,7 +57,7 @@ public class TaplTestsSplitscreen extends AbstractQuickStepTest {
@Before
public void setUp() throws Exception {
super.setUp();
- TaplTestsLauncher3.initialize(this);
+ AbstractLauncherUiTest.initialize(this);
if (mLauncher.isTablet()) {
mLauncher.enableBlockTimeout(true);
@@ -108,7 +111,8 @@ public class TaplTestsSplitscreen extends AbstractQuickStepTest {
@Test
public void testSaveAppPairMenuItemExistsOnSplitPair() throws Exception {
- assumeTrue(FeatureFlags.ENABLE_APP_PAIRS.get());
+ assumeTrue("App pairs feature is currently not enabled, no test needed",
+ Flags.enableAppPairs());
createAndLaunchASplitPair();
@@ -122,7 +126,8 @@ public class TaplTestsSplitscreen extends AbstractQuickStepTest {
@Test
public void testSaveAppPairMenuItemDoesNotExistOnSingleTask() throws Exception {
- assumeTrue(FeatureFlags.ENABLE_APP_PAIRS.get());
+ assumeTrue("App pairs feature is currently not enabled, no test needed",
+ Flags.enableAppPairs());
startAppFast(CALCULATOR_APP_PACKAGE);
@@ -134,11 +139,36 @@ public class TaplTestsSplitscreen extends AbstractQuickStepTest {
.hasMenuItem("Save app pair"));
}
+ @Test
+ public void testSplitSingleTaskFromTaskbar() {
+ // Currently only tablets have Taskbar in Overview, so test is only active on tablets
+ assumeTrue(mLauncher.isTablet());
+
+ if (!mLauncher.getRecentTasks().isEmpty()) {
+ // Clear all recent tasks
+ mLauncher.goHome().switchToOverview().dismissAllTasks();
+ }
+
+ startAppFast(getAppPackageName());
+
+ Overview overview = mLauncher.goHome().switchToOverview();
+ if (mLauncher.isGridOnlyOverviewEnabled()) {
+ overview.getCurrentTask().tapMenu().tapSplitMenuItem();
+ } else {
+ overview.getOverviewActions().clickSplit();
+ }
+
+ Taskbar taskbar = overview.getTaskbar();
+ String firstAppName = taskbar.getIconNames().get(0);
+ TaskbarAppIcon firstApp = taskbar.getAppIcon(firstAppName);
+ firstApp.launchIntoSplitScreen();
+ }
+
private void createAndLaunchASplitPair() {
startTestActivity(2);
startTestActivity(3);
- if (mLauncher.isTablet()) {
+ if (mLauncher.isTablet() && !mLauncher.isGridOnlyOverviewEnabled()) {
mLauncher.goHome().switchToOverview().getOverviewActions()
.clickSplit()
.getTestActivityTask(2)
diff --git a/quickstep/tests/src/com/android/quickstep/TaplTestsTaskbar.java b/quickstep/tests/src/com/android/quickstep/TaplTestsTaskbar.java
index 4ff2f9c721..f0683f9082 100644
--- a/quickstep/tests/src/com/android/quickstep/TaplTestsTaskbar.java
+++ b/quickstep/tests/src/com/android/quickstep/TaplTestsTaskbar.java
@@ -15,13 +15,13 @@
*/
package com.android.quickstep;
+import static com.android.launcher3.util.TestConstants.AppNames.TEST_APP_NAME;
import static com.android.quickstep.TaplTestsTaskbar.TaskbarMode.PERSISTENT;
import static com.android.quickstep.TaplTestsTaskbar.TaskbarMode.TRANSIENT;
import androidx.test.filters.LargeTest;
import com.android.launcher3.ui.PortraitLandscapeRunner.PortraitLandscape;
-import com.android.launcher3.util.rule.ScreenRecordRule.ScreenRecord;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -89,7 +89,6 @@ public class TaplTestsTaskbar extends AbstractTaplTestsTaskbar {
}
@Test
- @ScreenRecord // b/231615831
@PortraitLandscape
public void testLaunchAppInSplitscreen() {
getTaskbar().getAppIcon(TEST_APP_NAME).dragToSplitscreen(
@@ -103,7 +102,6 @@ public class TaplTestsTaskbar extends AbstractTaplTestsTaskbar {
}
@Test
- @ScreenRecord // b/231615831
@PortraitLandscape
public void testLaunchShortcutInSplitscreen() {
getTaskbar().getAppIcon(TEST_APP_NAME)
@@ -132,7 +130,6 @@ public class TaplTestsTaskbar extends AbstractTaplTestsTaskbar {
}
@Test
- @ScreenRecord // b/231615831
@PortraitLandscape
public void testLaunchAppInSplitscreen_fromTaskbarAllApps() {
getTaskbar().openAllApps()
@@ -141,7 +138,6 @@ public class TaplTestsTaskbar extends AbstractTaplTestsTaskbar {
}
@Test
- @ScreenRecord // b/231615831
@PortraitLandscape
public void testLaunchShortcutInSplitscreen_fromTaskbarAllApps() {
getTaskbar().openAllApps()
@@ -151,6 +147,18 @@ public class TaplTestsTaskbar extends AbstractTaplTestsTaskbar {
.dragToSplitscreen(TEST_APP_PACKAGE, CALCULATOR_APP_PACKAGE);
}
+ @Test
+ @PortraitLandscape
+ public void testDismissAllAppsByTappingOutsideSheet() {
+ getTaskbar().openAllApps().dismissByTappingOutsideForTablet(/* tapRight= */ true);
+ getTaskbar().openAllApps().dismissByTappingOutsideForTablet(/* tapRight= */ false);
+ }
+
+ @Test
+ public void testOpenMenuViaRightClick() {
+ getTaskbar().getAppIcon(TEST_APP_NAME).openDeepShortcutMenuWithRightClick();
+ }
+
private boolean isTaskbarTestModeTransient() {
return TRANSIENT == mTaskbarMode;
}
diff --git a/quickstep/tests/src/com/android/quickstep/TaplTestsTrackpad.java b/quickstep/tests/src/com/android/quickstep/TaplTestsTrackpad.java
index 907dbccb91..3465f23476 100644
--- a/quickstep/tests/src/com/android/quickstep/TaplTestsTrackpad.java
+++ b/quickstep/tests/src/com/android/quickstep/TaplTestsTrackpad.java
@@ -19,7 +19,6 @@ package com.android.quickstep;
import static com.android.quickstep.NavigationModeSwitchRule.Mode.ZERO_BUTTON;
import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeFalse;
import static org.junit.Assume.assumeTrue;
@@ -32,8 +31,8 @@ import androidx.test.runner.AndroidJUnit4;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.tapl.LauncherInstrumentation.TrackpadGestureType;
import com.android.launcher3.tapl.Workspace;
+import com.android.launcher3.ui.AbstractLauncherUiTest;
import com.android.launcher3.ui.PortraitLandscapeRunner.PortraitLandscape;
-import com.android.launcher3.ui.TaplTestsLauncher3;
import com.android.quickstep.NavigationModeSwitchRule.NavigationModeSwitch;
import org.junit.After;
@@ -51,7 +50,7 @@ public class TaplTestsTrackpad extends AbstractQuickStepTest {
@Before
public void setUp() throws Exception {
super.setUp();
- TaplTestsLauncher3.initialize(this);
+ AbstractLauncherUiTest.initialize(this);
}
@After
@@ -87,7 +86,7 @@ public class TaplTestsTrackpad extends AbstractQuickStepTest {
mLauncher.setTrackpadGestureType(TrackpadGestureType.THREE_FINGER);
startTestActivity(2);
- mLauncher.pressBack();
+ mLauncher.getLaunchedAppState().pressBackToWorkspace();
} finally {
instrumentation.getUiAutomation().dropShellPermissionIdentity();
}
diff --git a/quickstep/tests/src/com/android/quickstep/TaplTestsTransientTaskbar.java b/quickstep/tests/src/com/android/quickstep/TaplTestsTransientTaskbar.java
index 3869bf7642..7109bbff54 100644
--- a/quickstep/tests/src/com/android/quickstep/TaplTestsTransientTaskbar.java
+++ b/quickstep/tests/src/com/android/quickstep/TaplTestsTransientTaskbar.java
@@ -15,13 +15,16 @@
*/
package com.android.quickstep;
-import static com.android.launcher3.config.FeatureFlags.ENABLE_CURSOR_HOVER_STATES;
+import static com.android.launcher3.Flags.enableCursorHoverStates;
+import static com.android.launcher3.util.TestConstants.AppNames.TEST_APP_NAME;
import static com.android.quickstep.TaskbarModeSwitchRule.Mode.TRANSIENT;
+import static org.junit.Assume.assumeTrue;
+
import androidx.test.filters.LargeTest;
import androidx.test.runner.AndroidJUnit4;
-import com.android.launcher3.util.TestUtil;
+import com.android.launcher3.ui.PortraitLandscapeRunner.PortraitLandscape;
import com.android.quickstep.TaskbarModeSwitchRule.TaskbarModeSwitch;
import org.junit.Test;
@@ -34,44 +37,40 @@ public class TaplTestsTransientTaskbar extends AbstractTaplTestsTaskbar {
@Test
@TaskbarModeSwitch(mode = TRANSIENT)
public void testShowTaskbarUnstashHintOnHover() {
- try (AutoCloseable flag = TestUtil.overrideFlag(ENABLE_CURSOR_HOVER_STATES, true)) {
- getTaskbar().getAppIcon(TEST_APP_NAME).launch(TEST_APP_PACKAGE);
- mLauncher.getLaunchedAppState().hoverToShowTaskbarUnstashHint();
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
+ assumeTrue(enableCursorHoverStates());
+ getTaskbar().getAppIcon(TEST_APP_NAME).launch(TEST_APP_PACKAGE);
+ mLauncher.getLaunchedAppState().hoverToShowTaskbarUnstashHint();
}
@Test
@TaskbarModeSwitch(mode = TRANSIENT)
public void testUnstashTaskbarOnScreenBottomEdgeHover() {
- try (AutoCloseable flag = TestUtil.overrideFlag(ENABLE_CURSOR_HOVER_STATES, true)) {
- getTaskbar().getAppIcon(TEST_APP_NAME).launch(TEST_APP_PACKAGE);
- mLauncher.getLaunchedAppState().hoverScreenBottomEdgeToUnstashTaskbar();
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
+ assumeTrue(enableCursorHoverStates());
+ getTaskbar().getAppIcon(TEST_APP_NAME).launch(TEST_APP_PACKAGE);
+ mLauncher.getLaunchedAppState().hoverScreenBottomEdgeToUnstashTaskbar();
}
@Test
@TaskbarModeSwitch(mode = TRANSIENT)
public void testHoverBelowHintedTaskbarToUnstash() {
- try (AutoCloseable flag = TestUtil.overrideFlag(ENABLE_CURSOR_HOVER_STATES, true)) {
- getTaskbar().getAppIcon(TEST_APP_NAME).launch(TEST_APP_PACKAGE);
- mLauncher.getLaunchedAppState().hoverBelowHintedTaskbarToUnstash();
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
+ assumeTrue(enableCursorHoverStates());
+ getTaskbar().getAppIcon(TEST_APP_NAME).launch(TEST_APP_PACKAGE);
+ mLauncher.getLaunchedAppState().hoverBelowHintedTaskbarToUnstash();
+ }
+
+ @Test
+ @TaskbarModeSwitch(mode = TRANSIENT)
+ public void testClickHoveredTaskbarToGoHome() throws Exception {
+ assumeTrue(enableCursorHoverStates());
+ getTaskbar().getAppIcon(TEST_APP_NAME).launch(TEST_APP_PACKAGE);
+ mLauncher.getLaunchedAppState().clickStashedTaskbarToGoHome();
}
@Test
@TaskbarModeSwitch(mode = TRANSIENT)
- public void testClickHoveredTaskbarToGoHome() {
- try (AutoCloseable flag = TestUtil.overrideFlag(ENABLE_CURSOR_HOVER_STATES, true)) {
- getTaskbar().getAppIcon(TEST_APP_NAME).launch(TEST_APP_PACKAGE);
- mLauncher.getLaunchedAppState().clickStashedTaskbarToGoHome();
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
+ @PortraitLandscape
+ public void testSwipeToStashAndUnstash() {
+ getTaskbar().swipeDownToStash();
+ mLauncher.getLaunchedAppState().swipeUpToUnstashTaskbar();
}
}
diff --git a/quickstep/tests/src/com/android/quickstep/ViewInflationDuringSwipeUp.java b/quickstep/tests/src/com/android/quickstep/TaplViewInflationDuringSwipeUp.java
index 8cc84875e0..f76e17aa27 100644
--- a/quickstep/tests/src/com/android/quickstep/ViewInflationDuringSwipeUp.java
+++ b/quickstep/tests/src/com/android/quickstep/TaplViewInflationDuringSwipeUp.java
@@ -56,7 +56,7 @@ import com.android.launcher3.tapl.LaunchedAppState;
import com.android.launcher3.testcomponent.ListViewService;
import com.android.launcher3.testcomponent.ListViewService.SimpleViewsFactory;
import com.android.launcher3.testcomponent.TestCommandReceiver;
-import com.android.launcher3.ui.TaplTestsLauncher3;
+import com.android.launcher3.ui.AbstractLauncherUiTest;
import com.android.launcher3.ui.TestViewHelpers;
import com.android.launcher3.util.Executors;
import com.android.launcher3.widget.LauncherAppWidgetProviderInfo;
@@ -85,7 +85,7 @@ import java.util.function.IntConsumer;
*/
@LargeTest
@RunWith(AndroidJUnit4.class)
-public class ViewInflationDuringSwipeUp extends AbstractQuickStepTest {
+public class TaplViewInflationDuringSwipeUp extends AbstractQuickStepTest {
private SparseArray<ViewConfiguration> mConfigMap;
private InitTracker mInitTracker;
@@ -102,7 +102,7 @@ public class ViewInflationDuringSwipeUp extends AbstractQuickStepTest {
// is started only after starting another app.
startAppFast(resolveSystemApp(Intent.CATEGORY_APP_CALCULATOR));
- TaplTestsLauncher3.initialize(this);
+ AbstractLauncherUiTest.initialize(this);
mModel = LauncherAppState.getInstance(mTargetContext).getModel();
Executors.MODEL_EXECUTOR.submit(mModel.getModelDbController()::createEmptyDB).get();
diff --git a/quickstep/tests/src/com/android/quickstep/TaskThumbnailCacheTest.java b/quickstep/tests/src/com/android/quickstep/TaskThumbnailCacheTest.java
new file mode 100644
index 0000000000..4e04261e5c
--- /dev/null
+++ b/quickstep/tests/src/com/android/quickstep/TaskThumbnailCacheTest.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2023 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.quickstep;
+
+import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertTrue;
+
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.content.res.Resources;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.launcher3.R;
+import com.android.quickstep.util.TaskKeyCache;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.concurrent.Executor;
+
+@SmallTest
+public class TaskThumbnailCacheTest {
+ @Mock
+ private Context mContext;
+
+ @Mock
+ private Resources mResource;
+
+ @Mock
+ private TaskKeyCache mTaskKeyCache;
+
+ @Before
+ public void setup() throws NoSuchFieldException {
+ MockitoAnnotations.initMocks(this);
+ when(mContext.getResources()).thenReturn(mResource);
+ }
+
+ @Test
+ public void increaseCacheSize() {
+ // Mock a cache size increase from 3 to 8
+ when(mTaskKeyCache.getMaxSize()).thenReturn(3);
+ when(mResource.getInteger((R.integer.recentsThumbnailCacheSize))).thenReturn(8);
+ TaskThumbnailCache thumbnailCache = new TaskThumbnailCache(mContext, mock(Executor.class),
+ mTaskKeyCache);
+
+ // Preload is needed when increasing size
+ assertTrue(thumbnailCache.updateCacheSizeAndRemoveExcess());
+ verify(mTaskKeyCache, times(1)).updateCacheSizeAndRemoveExcess(8);
+ }
+
+ @Test
+ public void decreaseCacheSize() {
+ // Mock a cache size decrease from 8 to 3
+ when(mTaskKeyCache.getMaxSize()).thenReturn(8);
+ when(mResource.getInteger((R.integer.recentsThumbnailCacheSize))).thenReturn(3);
+ TaskThumbnailCache thumbnailCache = new TaskThumbnailCache(mContext, mock(Executor.class),
+ mTaskKeyCache);
+ // Preload is not needed when decreasing size
+ assertFalse(thumbnailCache.updateCacheSizeAndRemoveExcess());
+ verify(mTaskKeyCache, times(1)).updateCacheSizeAndRemoveExcess(3);
+ }
+
+ @Test
+ public void keepSameCacheSize() {
+ when(mTaskKeyCache.getMaxSize()).thenReturn(3);
+ when(mResource.getInteger((R.integer.recentsThumbnailCacheSize))).thenReturn(3);
+ TaskThumbnailCache thumbnailCache = new TaskThumbnailCache(mContext, mock(Executor.class),
+ mTaskKeyCache);
+ // Preload is not needed when it has the same cache size
+ assertFalse(thumbnailCache.updateCacheSizeAndRemoveExcess());
+ verify(mTaskKeyCache, never()).updateCacheSizeAndRemoveExcess(anyInt());
+ }
+}
diff --git a/quickstep/tests/src/com/android/quickstep/TaskViewTest.java b/quickstep/tests/src/com/android/quickstep/TaskViewTest.java
new file mode 100644
index 0000000000..d744194d42
--- /dev/null
+++ b/quickstep/tests/src/com/android/quickstep/TaskViewTest.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2023 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.quickstep;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.pm.ApplicationInfo;
+import android.content.res.Configuration;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.graphics.Rect;
+import android.util.DisplayMetrics;
+import android.view.MotionEvent;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.launcher3.statemanager.StatefulActivity;
+import com.android.quickstep.util.BorderAnimator;
+import com.android.quickstep.views.TaskView;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+@SmallTest
+public class TaskViewTest {
+
+ @Mock
+ private StatefulActivity mContext;
+ @Mock
+ private Resources mResource;
+ @Mock
+ private BorderAnimator mHoverAnimator;
+ @Mock
+ private BorderAnimator mFocusAnimator;
+ private TaskView mTaskView;
+
+ @Before
+ public void setup() {
+ MockitoAnnotations.initMocks(this);
+ when(mResource.getDisplayMetrics()).thenReturn(mock(DisplayMetrics.class));
+ when(mResource.getConfiguration()).thenReturn(new Configuration());
+
+ when(mContext.getResources()).thenReturn(mResource);
+ when(mContext.getTheme()).thenReturn(mock(Resources.Theme.class));
+ when(mContext.getApplicationInfo()).thenReturn(mock(ApplicationInfo.class));
+ when(mContext.obtainStyledAttributes(any(), any(), anyInt(), anyInt())).thenReturn(
+ mock(TypedArray.class));
+
+ mTaskView = new TaskView(mContext, null, 0, 0, mFocusAnimator, mHoverAnimator);
+ }
+
+ @Test
+ public void notShowBorderOnBorderDisabled() {
+ mTaskView.setBorderEnabled(/* enabled= */ false);
+ MotionEvent event = MotionEvent.obtain(0, 0, MotionEvent.ACTION_HOVER_ENTER, 0.0f, 0.0f, 0);
+ mTaskView.onHoverEvent(MotionEvent.obtain(event));
+ verify(mHoverAnimator, never()).setBorderVisibility(/* visible= */ true, /* animated= */
+ true);
+
+ mTaskView.onFocusChanged(false, 0, new Rect());
+ verify(mFocusAnimator, never()).setBorderVisibility(/* visible= */ true, /* animated= */
+ true);
+ }
+
+ @Test
+ public void showBorderOnBorderEnabled() {
+ mTaskView.setBorderEnabled(/* enabled= */ true);
+ MotionEvent event = MotionEvent.obtain(0, 0, MotionEvent.ACTION_HOVER_ENTER, 0.0f, 0.0f, 0);
+ mTaskView.onHoverEvent(MotionEvent.obtain(event));
+ verify(mHoverAnimator, times(1)).setBorderVisibility(/* visible= */ true, /* animated= */
+ true);
+ mTaskView.onFocusChanged(true, 0, new Rect());
+ verify(mFocusAnimator, times(1)).setBorderVisibility(/* visible= */ true, /* animated= */
+ true);
+ }
+
+ @Test
+ public void hideBorderOnBorderDisabled() {
+ mTaskView.setBorderEnabled(/* enabled= */ false);
+ verify(mHoverAnimator, times(1)).setBorderVisibility(/* visible= */ false, /* animated= */
+ true);
+ verify(mFocusAnimator, times(1)).setBorderVisibility(/* visible= */ false, /* animated= */
+ true);
+ }
+
+ @Test
+ public void notShowBorderByDefault() {
+ MotionEvent event = MotionEvent.obtain(0, 0, MotionEvent.ACTION_HOVER_ENTER, 0.0f, 0.0f, 0);
+ mTaskView.onHoverEvent(MotionEvent.obtain(event));
+ verify(mHoverAnimator, never()).setBorderVisibility(/* visible= */ false, /* animated= */
+ true);
+ mTaskView.onFocusChanged(true, 0, new Rect());
+ verify(mHoverAnimator, never()).setBorderVisibility(/* visible= */ false, /* animated= */
+ true);
+ }
+}
diff --git a/quickstep/tests/src/com/android/quickstep/TaskbarModeSwitchRule.java b/quickstep/tests/src/com/android/quickstep/TaskbarModeSwitchRule.java
index 9e41f74186..e5657fb644 100644
--- a/quickstep/tests/src/com/android/quickstep/TaskbarModeSwitchRule.java
+++ b/quickstep/tests/src/com/android/quickstep/TaskbarModeSwitchRule.java
@@ -123,7 +123,7 @@ public class TaskbarModeSwitchRule implements TestRule {
assertTrue(launcher, "Couldn't set taskbar=" + expectTransientTaskbar,
isTaskbarTransientMode(context) == expectTransientTaskbar, description);
- AbstractLauncherUiTest.checkDetectedLeaks(launcher);
+ AbstractLauncherUiTest.checkDetectedLeaks(launcher, true);
}
private static void assertTrue(LauncherInstrumentation launcher, String message,
diff --git a/quickstep/tests/src/com/android/quickstep/taskbar/controllers/TaskbarPinningControllerTest.kt b/quickstep/tests/src/com/android/quickstep/taskbar/controllers/TaskbarPinningControllerTest.kt
new file mode 100644
index 0000000000..dbe4624e45
--- /dev/null
+++ b/quickstep/tests/src/com/android/quickstep/taskbar/controllers/TaskbarPinningControllerTest.kt
@@ -0,0 +1,202 @@
+/*
+ * Copyright (C) 2023 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.quickstep.taskbar.controllers
+
+import android.animation.AnimatorSet
+import android.animation.ObjectAnimator
+import android.view.View
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.launcher3.LauncherPrefs
+import com.android.launcher3.LauncherPrefs.Companion.TASKBAR_PINNING
+import com.android.launcher3.logging.StatsLogManager
+import com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASKBAR_DIVIDER_MENU_CLOSE
+import com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASKBAR_DIVIDER_MENU_OPEN
+import com.android.launcher3.taskbar.TaskbarActivityContext
+import com.android.launcher3.taskbar.TaskbarBaseTestCase
+import com.android.launcher3.taskbar.TaskbarDividerPopupView
+import com.android.launcher3.taskbar.TaskbarDragLayer
+import com.android.launcher3.taskbar.TaskbarPinningController
+import com.android.launcher3.taskbar.TaskbarPinningController.Companion.PINNING_PERSISTENT
+import com.android.launcher3.taskbar.TaskbarPinningController.Companion.PINNING_TRANSIENT
+import com.android.launcher3.taskbar.TaskbarSharedState
+import com.google.common.truth.Truth.assertThat
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.kotlin.any
+import org.mockito.kotlin.argumentCaptor
+import org.mockito.kotlin.doNothing
+import org.mockito.kotlin.doReturn
+import org.mockito.kotlin.mock
+import org.mockito.kotlin.never
+import org.mockito.kotlin.spy
+import org.mockito.kotlin.times
+import org.mockito.kotlin.verify
+import org.mockito.kotlin.whenever
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class TaskbarPinningControllerTest : TaskbarBaseTestCase() {
+ private val taskbarDragLayer = mock<TaskbarDragLayer>()
+ private val taskbarSharedState = mock<TaskbarSharedState>()
+ private val launcherPrefs = mock<LauncherPrefs> { on { get(TASKBAR_PINNING) } doReturn false }
+ private val statsLogger = mock<StatsLogManager.StatsLogger>()
+ private val statsLogManager = mock<StatsLogManager> { on { logger() } doReturn statsLogger }
+ private lateinit var pinningController: TaskbarPinningController
+
+ @Before
+ override fun setup() {
+ super.setup()
+ whenever(taskbarActivityContext.launcherPrefs).thenReturn(launcherPrefs)
+ whenever(taskbarActivityContext.dragLayer).thenReturn(taskbarDragLayer)
+ whenever(taskbarActivityContext.statsLogManager).thenReturn(statsLogManager)
+ pinningController = spy(TaskbarPinningController(taskbarActivityContext))
+ pinningController.init(taskbarControllers, taskbarSharedState)
+ }
+
+ @Test
+ fun testOnCloseCallback_whenClosingPopupView_shouldLogStatsForClosingPopupMenu() {
+ pinningController.onCloseCallback(false)
+ verify(statsLogger, times(1)).log(LAUNCHER_TASKBAR_DIVIDER_MENU_CLOSE)
+ }
+
+ @Test
+ fun testOnCloseCallback_whenClosingPopupView_shouldPostVisibilityChangedToDragLayer() {
+ val argumentCaptor = argumentCaptor<Runnable>()
+ pinningController.onCloseCallback(false)
+ verify(taskbarDragLayer, times(1)).post(argumentCaptor.capture())
+
+ val runnable = argumentCaptor.lastValue
+ assertThat(runnable).isNotNull()
+
+ runnable.run()
+ verify(taskbarActivityContext, times(1)).onPopupVisibilityChanged(false)
+ }
+
+ @Test
+ fun testOnCloseCallback_whenPreferenceUnchanged_shouldNotAnimateTaskbarPinning() {
+ pinningController.onCloseCallback(false)
+ verify(taskbarSharedState, never()).taskbarWasPinned = true
+ verify(pinningController, never()).animateTaskbarPinning(any())
+ }
+
+ @Test
+ fun testOnCloseCallback_whenPreferenceChanged_shouldAnimateToPinnedTaskbar() {
+ whenever(launcherPrefs.get(TASKBAR_PINNING)).thenReturn(false)
+ doNothing().whenever(pinningController).animateTaskbarPinning(any())
+
+ pinningController.onCloseCallback(true)
+
+ verify(taskbarSharedState, times(1)).taskbarWasPinned = false
+ verify(pinningController, times(1)).animateTaskbarPinning(PINNING_PERSISTENT)
+ }
+
+ @Test
+ fun testOnCloseCallback_whenPreferenceChanged_shouldAnimateToTransientTaskbar() {
+ whenever(launcherPrefs.get(TASKBAR_PINNING)).thenReturn(true)
+ doNothing().whenever(pinningController).animateTaskbarPinning(any())
+
+ pinningController.onCloseCallback(true)
+
+ verify(taskbarSharedState, times(1)).taskbarWasPinned = true
+ verify(pinningController, times(1)).animateTaskbarPinning(PINNING_TRANSIENT)
+ }
+
+ @Test
+ fun testShowPinningView_whenShowingPinningView_shouldSetTaskbarWindowFullscreenAndPostRunnableToView() {
+ val popupView =
+ mock<TaskbarDividerPopupView<TaskbarActivityContext>> {
+ on { requestFocus() } doReturn true
+ }
+ val view = mock<View>()
+ val argumentCaptor = argumentCaptor<Runnable>()
+ doReturn(popupView).whenever(pinningController).getPopupView(view)
+
+ pinningController.showPinningView(view)
+
+ verify(view, times(1)).post(argumentCaptor.capture())
+
+ val runnable = argumentCaptor.lastValue
+ assertThat(runnable).isNotNull()
+ runnable.run()
+
+ verify(pinningController, times(1)).getPopupView(view)
+ verify(popupView, times(1)).requestFocus()
+ verify(popupView, times(1)).onCloseCallback = any()
+ verify(taskbarActivityContext, times(1)).onPopupVisibilityChanged(true)
+ verify(popupView, times(1)).show()
+ verify(statsLogger, times(1)).log(LAUNCHER_TASKBAR_DIVIDER_MENU_OPEN)
+ }
+
+ @Test
+ fun testAnimateTaskbarPinning_whenAnimationEnds_shouldInvokeCallbackDoOnEnd() {
+ val animatorSet = spy(AnimatorSet())
+ doReturn(animatorSet)
+ .whenever(pinningController)
+ .getAnimatorSetForTaskbarPinningAnimation(PINNING_PERSISTENT)
+ doNothing().whenever(animatorSet).start()
+ pinningController.animateTaskbarPinning(PINNING_PERSISTENT)
+ animatorSet.listeners[0].onAnimationEnd(ObjectAnimator())
+ verify(pinningController, times(1)).recreateTaskbarAndUpdatePinningValue()
+ }
+
+ @Test
+ fun testAnimateTaskbarPinning_whenAnimatingToPersistentTaskbar_shouldAnimateToPinnedTaskbar() {
+ val animatorSet = spy(AnimatorSet())
+ doReturn(animatorSet)
+ .whenever(pinningController)
+ .getAnimatorSetForTaskbarPinningAnimation(PINNING_PERSISTENT)
+ doNothing().whenever(animatorSet).start()
+ pinningController.animateTaskbarPinning(PINNING_PERSISTENT)
+
+ verify(taskbarOverlayController, times(1)).hideWindow()
+ verify(pinningController, times(1))
+ .getAnimatorSetForTaskbarPinningAnimation(PINNING_PERSISTENT)
+ verify(taskbarViewController, times(1))
+ .animateAwayNotificationDotsDuringTaskbarPinningAnimation()
+ verify(taskbarDragLayer, times(1)).setAnimatingTaskbarPinning(true)
+ assertThat(pinningController.isAnimatingTaskbarPinning).isTrue()
+ assertThat(animatorSet.listeners).isNotNull()
+ }
+
+ @Test
+ fun testAnimateTaskbarPinning_whenAnimatingToTransientTaskbar_shouldAnimateToTransientTaskbar() {
+ val animatorSet = spy(AnimatorSet())
+ doReturn(animatorSet)
+ .whenever(pinningController)
+ .getAnimatorSetForTaskbarPinningAnimation(PINNING_TRANSIENT)
+ doNothing().whenever(animatorSet).start()
+ pinningController.animateTaskbarPinning(PINNING_TRANSIENT)
+
+ verify(taskbarOverlayController, times(1)).hideWindow()
+ verify(pinningController, times(1))
+ .getAnimatorSetForTaskbarPinningAnimation(PINNING_TRANSIENT)
+ verify(taskbarDragLayer, times(1)).setAnimatingTaskbarPinning(true)
+ assertThat(pinningController.isAnimatingTaskbarPinning).isTrue()
+ verify(taskbarViewController, times(1))
+ .animateAwayNotificationDotsDuringTaskbarPinningAnimation()
+ assertThat(animatorSet.listeners).isNotNull()
+ }
+
+ @Test
+ fun testRecreateTaskbarAndUpdatePinningValue_whenAnimationEnds_shouldUpdateTaskbarPinningLauncherPref() {
+ pinningController.recreateTaskbarAndUpdatePinningValue()
+ verify(taskbarDragLayer, times(1)).setAnimatingTaskbarPinning(false)
+ assertThat(pinningController.isAnimatingTaskbarPinning).isFalse()
+ verify(launcherPrefs, times(1)).put(TASKBAR_PINNING, true)
+ }
+}
diff --git a/quickstep/tests/src/com/android/quickstep/util/AppPairsControllerTest.kt b/quickstep/tests/src/com/android/quickstep/util/AppPairsControllerTest.kt
new file mode 100644
index 0000000000..1723844843
--- /dev/null
+++ b/quickstep/tests/src/com/android/quickstep/util/AppPairsControllerTest.kt
@@ -0,0 +1,147 @@
+/*
+ * Copyright (C) 2023 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.quickstep.util
+
+import android.content.Context
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.android.launcher3.logging.StatsLogManager
+import com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_BOTTOM_OR_RIGHT
+import com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_TOP_OR_LEFT
+import com.android.wm.shell.common.split.SplitScreenConstants.SNAP_TO_30_70
+import com.android.wm.shell.common.split.SplitScreenConstants.SNAP_TO_50_50
+import com.android.wm.shell.common.split.SplitScreenConstants.SNAP_TO_70_30
+import org.junit.Assert.assertEquals
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.MockitoAnnotations
+
+@RunWith(AndroidJUnit4::class)
+class AppPairsControllerTest {
+ @Mock lateinit var context: Context
+ @Mock lateinit var splitSelectStateController: SplitSelectStateController
+ @Mock lateinit var statsLogManager: StatsLogManager
+
+ private lateinit var appPairsController: AppPairsController
+
+ private val left30: Int by lazy {
+ appPairsController.encodeRank(STAGE_POSITION_TOP_OR_LEFT, SNAP_TO_30_70)
+ }
+ private val left50: Int by lazy {
+ appPairsController.encodeRank(STAGE_POSITION_TOP_OR_LEFT, SNAP_TO_50_50)
+ }
+ private val left70: Int by lazy {
+ appPairsController.encodeRank(STAGE_POSITION_TOP_OR_LEFT, SNAP_TO_70_30)
+ }
+ private val right30: Int by lazy {
+ appPairsController.encodeRank(STAGE_POSITION_BOTTOM_OR_RIGHT, SNAP_TO_30_70)
+ }
+ private val right50: Int by lazy {
+ appPairsController.encodeRank(STAGE_POSITION_BOTTOM_OR_RIGHT, SNAP_TO_50_50)
+ }
+ private val right70: Int by lazy {
+ appPairsController.encodeRank(STAGE_POSITION_BOTTOM_OR_RIGHT, SNAP_TO_70_30)
+ }
+
+ @Before
+ fun setup() {
+ MockitoAnnotations.initMocks(this)
+ appPairsController =
+ AppPairsController(context, splitSelectStateController, statsLogManager)
+ }
+
+ @Test
+ fun shouldEncodeRankCorrectly() {
+ assertEquals("left + 30-70 should encode as 0 (0b0)", 0, left30)
+ assertEquals("left + 50-50 should encode as 1 (0b1)", 1, left50)
+ assertEquals("left + 70-30 should encode as 2 (0b10)", 2, left70)
+ // See AppPairsController#BITMASK_SIZE and BITMASK_FOR_SNAP_POSITION for context
+ assertEquals("right + 30-70 should encode as 1 followed by 16 0s", 1 shl 16, right30)
+ assertEquals("right + 50-50 should encode as the above value + 1", (1 shl 16) + 1, right50)
+ assertEquals("right + 70-30 should encode as the above value + 2", (1 shl 16) + 2, right70)
+ }
+
+ @Test
+ fun shouldDecodeRankCorrectly() {
+ assertEquals(
+ "left + 30-70 should decode to left",
+ STAGE_POSITION_TOP_OR_LEFT,
+ AppPairsController.convertRankToStagePosition(left30),
+ )
+ assertEquals(
+ "left + 30-70 should decode to 30-70",
+ SNAP_TO_30_70,
+ AppPairsController.convertRankToSnapPosition(left30),
+ )
+
+ assertEquals(
+ "left + 50-50 should decode to left",
+ STAGE_POSITION_TOP_OR_LEFT,
+ AppPairsController.convertRankToStagePosition(left50),
+ )
+ assertEquals(
+ "left + 50-50 should decode to 50-50",
+ SNAP_TO_50_50,
+ AppPairsController.convertRankToSnapPosition(left50),
+ )
+
+ assertEquals(
+ "left + 70-30 should decode to left",
+ STAGE_POSITION_TOP_OR_LEFT,
+ AppPairsController.convertRankToStagePosition(left70),
+ )
+ assertEquals(
+ "left + 70-30 should decode to 70-30",
+ SNAP_TO_70_30,
+ AppPairsController.convertRankToSnapPosition(left70),
+ )
+
+ assertEquals(
+ "right + 30-70 should decode to right",
+ STAGE_POSITION_BOTTOM_OR_RIGHT,
+ AppPairsController.convertRankToStagePosition(right30),
+ )
+ assertEquals(
+ "right + 30-70 should decode to 30-70",
+ SNAP_TO_30_70,
+ AppPairsController.convertRankToSnapPosition(right30),
+ )
+
+ assertEquals(
+ "right + 50-50 should decode to right",
+ STAGE_POSITION_BOTTOM_OR_RIGHT,
+ AppPairsController.convertRankToStagePosition(right50),
+ )
+ assertEquals(
+ "right + 50-50 should decode to 50-50",
+ SNAP_TO_50_50,
+ AppPairsController.convertRankToSnapPosition(right50),
+ )
+
+ assertEquals(
+ "right + 70-30 should decode to right",
+ STAGE_POSITION_BOTTOM_OR_RIGHT,
+ AppPairsController.convertRankToStagePosition(right70),
+ )
+ assertEquals(
+ "right + 70-30 should decode to 70-30",
+ SNAP_TO_70_30,
+ AppPairsController.convertRankToSnapPosition(right70),
+ )
+ }
+}
diff --git a/quickstep/tests/src/com/android/quickstep/util/SplitAnimationControllerTest.kt b/quickstep/tests/src/com/android/quickstep/util/SplitAnimationControllerTest.kt
index 7e07b813a7..86018b1783 100644
--- a/quickstep/tests/src/com/android/quickstep/util/SplitAnimationControllerTest.kt
+++ b/quickstep/tests/src/com/android/quickstep/util/SplitAnimationControllerTest.kt
@@ -19,8 +19,13 @@ package com.android.quickstep.util
import android.graphics.Bitmap
import android.graphics.drawable.Drawable
+import android.view.SurfaceControl.Transaction
import android.view.View
+import android.window.TransitionInfo
import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.android.launcher3.apppairs.AppPairIcon
+import com.android.launcher3.statehandlers.DepthController
+import com.android.launcher3.statemanager.StateManager
import com.android.launcher3.util.SplitConfigurationOptions
import com.android.quickstep.views.GroupedTaskView
import com.android.quickstep.views.IconView
@@ -32,39 +37,48 @@ import org.junit.Assert.assertEquals
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
-import org.mockito.Mock
-import org.mockito.MockitoAnnotations
-import org.mockito.Mockito.`when` as whenever
+import org.mockito.kotlin.any
+import org.mockito.kotlin.doNothing
+import org.mockito.kotlin.mock
+import org.mockito.kotlin.spy
+import org.mockito.kotlin.verify
+import org.mockito.kotlin.whenever
@RunWith(AndroidJUnit4::class)
class SplitAnimationControllerTest {
private val taskId = 9
+ private val taskId2 = 10
- @Mock lateinit var mockSplitSelectStateController: SplitSelectStateController
+ private val mockSplitSelectStateController: SplitSelectStateController = mock()
// TaskView
- @Mock lateinit var mockTaskView: TaskView
- @Mock lateinit var mockThumbnailView: TaskThumbnailView
- @Mock lateinit var mockBitmap: Bitmap
- @Mock lateinit var mockIconView: IconView
- @Mock lateinit var mockTaskViewDrawable: Drawable
+ private val mockTaskView: TaskView = mock()
+ private val mockThumbnailView: TaskThumbnailView = mock()
+ private val mockBitmap: Bitmap = mock()
+ private val mockIconView: IconView = mock()
+ private val mockTaskViewDrawable: Drawable = mock()
// GroupedTaskView
- @Mock lateinit var mockGroupedTaskView: GroupedTaskView
- @Mock lateinit var mockTask: Task
- @Mock lateinit var mockTaskKey: Task.TaskKey
- @Mock lateinit var mockTaskIdAttributeContainer: TaskIdAttributeContainer
+ private val mockGroupedTaskView: GroupedTaskView = mock()
+ private val mockTask: Task = mock()
+ private val mockTaskKey: Task.TaskKey = mock()
+ private val mockTaskIdAttributeContainer: TaskIdAttributeContainer = mock()
+ // AppPairIcon
+ private val mockAppPairIcon: AppPairIcon = mock()
// SplitSelectSource
- @Mock lateinit var splitSelectSource: SplitConfigurationOptions.SplitSelectSource
- @Mock lateinit var mockSplitSourceDrawable: Drawable
- @Mock lateinit var mockSplitSourceView: View
+ private val splitSelectSource: SplitConfigurationOptions.SplitSelectSource = mock()
+ private val mockSplitSourceDrawable: Drawable = mock()
+ private val mockSplitSourceView: View = mock()
+
+ private val stateManager: StateManager<*> = mock()
+ private val depthController: DepthController = mock()
+ private val transitionInfo: TransitionInfo = mock()
+ private val transaction: Transaction = mock()
lateinit var splitAnimationController: SplitAnimationController
@Before
fun setup() {
- MockitoAnnotations.initMocks(this)
-
whenever(mockTaskView.thumbnail).thenReturn(mockThumbnailView)
whenever(mockThumbnailView.thumbnail).thenReturn(mockBitmap)
whenever(mockTaskView.iconView).thenReturn(mockIconView)
@@ -85,12 +99,14 @@ class SplitAnimationControllerTest {
// Missing taskView icon
whenever(mockIconView.drawable).thenReturn(null)
- val splitAnimInitProps : SplitAnimationController.Companion.SplitAnimInitProps =
- splitAnimationController.getFirstAnimInitViews(
- { mockTaskView }, { splitSelectSource })
+ val splitAnimInitProps: SplitAnimationController.Companion.SplitAnimInitProps =
+ splitAnimationController.getFirstAnimInitViews({ mockTaskView }, { splitSelectSource })
- assertEquals("Did not fallback to use splitSource icon drawable",
- mockSplitSourceDrawable, splitAnimInitProps.iconDrawable)
+ assertEquals(
+ "Did not fallback to use splitSource icon drawable",
+ mockSplitSourceDrawable,
+ splitAnimInitProps.iconDrawable
+ )
}
@Test
@@ -99,12 +115,14 @@ class SplitAnimationControllerTest {
whenever(mockSplitSelectStateController.isAnimateCurrentTaskDismissal).thenReturn(true)
whenever(mockSplitSelectStateController.isDismissingFromSplitPair).thenReturn(false)
- val splitAnimInitProps : SplitAnimationController.Companion.SplitAnimInitProps =
- splitAnimationController.getFirstAnimInitViews(
- { mockTaskView }, { splitSelectSource })
+ val splitAnimInitProps: SplitAnimationController.Companion.SplitAnimInitProps =
+ splitAnimationController.getFirstAnimInitViews({ mockTaskView }, { splitSelectSource })
- assertEquals("Did not use taskView icon drawable", mockTaskViewDrawable,
- splitAnimInitProps.iconDrawable)
+ assertEquals(
+ "Did not use taskView icon drawable",
+ mockTaskViewDrawable,
+ splitAnimInitProps.iconDrawable
+ )
}
@Test
@@ -116,12 +134,14 @@ class SplitAnimationControllerTest {
// Set split source to null
whenever(splitSelectSource.drawable).thenReturn(null)
- val splitAnimInitProps : SplitAnimationController.Companion.SplitAnimInitProps =
- splitAnimationController.getFirstAnimInitViews(
- { mockTaskView }, { splitSelectSource })
+ val splitAnimInitProps: SplitAnimationController.Companion.SplitAnimInitProps =
+ splitAnimationController.getFirstAnimInitViews({ mockTaskView }, { splitSelectSource })
- assertEquals("Did not use taskView icon drawable", mockTaskViewDrawable,
- splitAnimInitProps.iconDrawable)
+ assertEquals(
+ "Did not use taskView icon drawable",
+ mockTaskViewDrawable,
+ splitAnimInitProps.iconDrawable
+ )
}
@Test
@@ -130,12 +150,14 @@ class SplitAnimationControllerTest {
whenever(mockSplitSelectStateController.isAnimateCurrentTaskDismissal).thenReturn(false)
whenever(mockSplitSelectStateController.isDismissingFromSplitPair).thenReturn(false)
- val splitAnimInitProps : SplitAnimationController.Companion.SplitAnimInitProps =
- splitAnimationController.getFirstAnimInitViews(
- { mockTaskView }, { splitSelectSource })
+ val splitAnimInitProps: SplitAnimationController.Companion.SplitAnimInitProps =
+ splitAnimationController.getFirstAnimInitViews({ mockTaskView }, { splitSelectSource })
- assertEquals("Did not use splitSource icon drawable", mockSplitSourceDrawable,
- splitAnimInitProps.iconDrawable)
+ assertEquals(
+ "Did not use splitSource icon drawable",
+ mockSplitSourceDrawable,
+ splitAnimInitProps.iconDrawable
+ )
}
@Test
@@ -154,12 +176,123 @@ class SplitAnimationControllerTest {
whenever(mockTaskKey.getId()).thenReturn(taskId)
whenever(mockSplitSelectStateController.initialTaskId).thenReturn(taskId)
whenever(mockGroupedTaskView.taskIdAttributeContainers)
- .thenReturn(Array(1) { mockTaskIdAttributeContainer })
- val splitAnimInitProps : SplitAnimationController.Companion.SplitAnimInitProps =
- splitAnimationController.getFirstAnimInitViews(
- { mockGroupedTaskView }, { splitSelectSource })
+ .thenReturn(Array(1) { mockTaskIdAttributeContainer })
+ val splitAnimInitProps: SplitAnimationController.Companion.SplitAnimInitProps =
+ splitAnimationController.getFirstAnimInitViews(
+ { mockGroupedTaskView },
+ { splitSelectSource }
+ )
+
+ assertEquals(
+ "Did not use splitSource icon drawable",
+ mockSplitSourceDrawable,
+ splitAnimInitProps.iconDrawable
+ )
+ }
+
+ @Test
+ fun playsAppropriateSplitLaunchAnimation_playsLegacyLaunchCorrectly() {
+ val spySplitAnimationController = spy(splitAnimationController)
+ doNothing()
+ .whenever(spySplitAnimationController)
+ .composeRecentsSplitLaunchAnimatorLegacy(
+ any(), any(), any(), any(), any(), any(), any(), any(), any())
+
+ spySplitAnimationController.playSplitLaunchAnimation(
+ mockGroupedTaskView,
+ null /* launchingIconView */,
+ taskId,
+ taskId2,
+ arrayOf() /* apps */,
+ arrayOf() /* wallpapers */,
+ arrayOf() /* nonApps */,
+ stateManager,
+ depthController,
+ null /* info */,
+ null /* t */,
+ {} /* finishCallback */
+ )
+
+ verify(spySplitAnimationController)
+ .composeRecentsSplitLaunchAnimatorLegacy(
+ any(), any(), any(), any(), any(), any(), any(), any(), any())
+ }
+
+ @Test
+ fun playsAppropriateSplitLaunchAnimation_playsRecentsLaunchCorrectly() {
+ val spySplitAnimationController = spy(splitAnimationController)
+ doNothing()
+ .whenever(spySplitAnimationController)
+ .composeRecentsSplitLaunchAnimator(any(), any(), any(), any(), any(), any())
+
+ spySplitAnimationController.playSplitLaunchAnimation(
+ mockGroupedTaskView,
+ null /* launchingIconView */,
+ taskId,
+ taskId2,
+ null /* apps */,
+ null /* wallpapers */,
+ null /* nonApps */,
+ stateManager,
+ depthController,
+ transitionInfo,
+ transaction,
+ {} /* finishCallback */
+ )
+
+ verify(spySplitAnimationController)
+ .composeRecentsSplitLaunchAnimator(any(), any(), any(), any(), any(), any())
+ }
+
+ @Test
+ fun playsAppropriateSplitLaunchAnimation_playsIconLaunchCorrectly() {
+ val spySplitAnimationController = spy(splitAnimationController)
+ doNothing()
+ .whenever(spySplitAnimationController)
+ .composeIconSplitLaunchAnimator(any(), any(), any(), any(), any(), any())
+
+ spySplitAnimationController.playSplitLaunchAnimation(
+ null /* launchingTaskView */,
+ mockAppPairIcon,
+ taskId,
+ taskId2,
+ null /* apps */,
+ null /* wallpapers */,
+ null /* nonApps */,
+ stateManager,
+ depthController,
+ transitionInfo,
+ transaction,
+ {} /* finishCallback */
+ )
+
+ verify(spySplitAnimationController)
+ .composeIconSplitLaunchAnimator(any(), any(), any(), any(), any(), any())
+ }
+
+ @Test
+ fun playsAppropriateSplitLaunchAnimation_playsFadeInLaunchCorrectly() {
+ val spySplitAnimationController = spy(splitAnimationController)
+ doNothing()
+ .whenever(spySplitAnimationController)
+ .composeFadeInSplitLaunchAnimator(any(), any(), any(), any(), any())
+
+ spySplitAnimationController.playSplitLaunchAnimation(
+ null /* launchingTaskView */,
+ null /* launchingIconView */,
+ taskId,
+ taskId2,
+ null /* apps */,
+ null /* wallpapers */,
+ null /* nonApps */,
+ stateManager,
+ depthController,
+ transitionInfo,
+ transaction,
+ {} /* finishCallback */
+ )
- assertEquals("Did not use splitSource icon drawable", mockSplitSourceDrawable,
- splitAnimInitProps.iconDrawable)
+ verify(spySplitAnimationController)
+ .composeFadeInSplitLaunchAnimator(any(), any(), any(), any(), any())
}
-} \ No newline at end of file
+}
diff --git a/quickstep/tests/src/com/android/quickstep/util/SplitSelectDataHolderTest.kt b/quickstep/tests/src/com/android/quickstep/util/SplitSelectDataHolderTest.kt
index fc767fae72..c6c5be4c60 100644
--- a/quickstep/tests/src/com/android/quickstep/util/SplitSelectDataHolderTest.kt
+++ b/quickstep/tests/src/com/android/quickstep/util/SplitSelectDataHolderTest.kt
@@ -381,7 +381,7 @@ class SplitSelectDataHolderTest {
}
@Test
- fun clearState() {
+ fun clearState_task() {
splitSelectDataHolder.setInitialTaskSelect(
sampleTaskInfo,
STAGE_POSITION_TOP_OR_LEFT,
@@ -392,4 +392,18 @@ class SplitSelectDataHolderTest {
splitSelectDataHolder.resetState()
assertFalse(splitSelectDataHolder.isSplitSelectActive())
}
+
+ @Test
+ fun clearState_intent() {
+ splitSelectDataHolder.setInitialTaskSelect(
+ sampleIntent,
+ STAGE_POSITION_TOP_OR_LEFT,
+ sampleItemInfo,
+ null,
+ INVALID_TASK_ID
+ )
+ splitSelectDataHolder.setSecondTask(sampleIntent, sampleUser)
+ splitSelectDataHolder.resetState()
+ assertFalse(splitSelectDataHolder.isSplitSelectActive())
+ }
}
diff --git a/quickstep/tests/src/com/android/quickstep/util/SplitSelectStateControllerTest.kt b/quickstep/tests/src/com/android/quickstep/util/SplitSelectStateControllerTest.kt
index 69109c2c45..f41ac4809b 100644
--- a/quickstep/tests/src/com/android/quickstep/util/SplitSelectStateControllerTest.kt
+++ b/quickstep/tests/src/com/android/quickstep/util/SplitSelectStateControllerTest.kt
@@ -20,7 +20,6 @@ package com.android.quickstep.util
import android.app.ActivityManager
import android.app.PendingIntent
import android.content.ComponentName
-import android.content.Context
import android.content.Intent
import android.graphics.Rect
import android.os.Handler
@@ -31,12 +30,13 @@ import com.android.launcher3.logging.StatsLogManager
import com.android.launcher3.model.data.ItemInfo
import com.android.launcher3.statehandlers.DepthController
import com.android.launcher3.statemanager.StateManager
+import com.android.launcher3.statemanager.StatefulActivity
import com.android.launcher3.util.ComponentKey
import com.android.launcher3.util.SplitConfigurationOptions
-import com.android.launcher3.util.withArgCaptor
import com.android.quickstep.RecentsModel
import com.android.quickstep.SystemUiProxy
import com.android.systemui.shared.recents.model.Task
+import com.android.wm.shell.common.split.SplitScreenConstants.SNAP_TO_50_50
import java.util.function.Consumer
import org.junit.Assert.assertEquals
import org.junit.Assert.assertFalse
@@ -45,22 +45,22 @@ import org.junit.Assert.assertTrue
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
-import org.mockito.Mock
-import org.mockito.Mockito.verify
-import org.mockito.Mockito.`when`
-import org.mockito.MockitoAnnotations
+import org.mockito.kotlin.argumentCaptor
+import org.mockito.kotlin.mock
+import org.mockito.kotlin.verify
+import org.mockito.kotlin.whenever
@RunWith(AndroidJUnit4::class)
class SplitSelectStateControllerTest {
- @Mock lateinit var systemUiProxy: SystemUiProxy
- @Mock lateinit var depthController: DepthController
- @Mock lateinit var statsLogManager: StatsLogManager
- @Mock lateinit var stateManager: StateManager<LauncherState>
- @Mock lateinit var handler: Handler
- @Mock lateinit var context: Context
- @Mock lateinit var recentsModel: RecentsModel
- @Mock lateinit var pendingIntent: PendingIntent
+ private val systemUiProxy: SystemUiProxy = mock()
+ private val depthController: DepthController = mock()
+ private val statsLogManager: StatsLogManager = mock()
+ private val stateManager: StateManager<LauncherState> = mock()
+ private val handler: Handler = mock()
+ private val context: StatefulActivity<*> = mock()
+ private val recentsModel: RecentsModel = mock()
+ private val pendingIntent: PendingIntent = mock()
lateinit var splitSelectStateController: SplitSelectStateController
@@ -68,11 +68,12 @@ class SplitSelectStateControllerTest {
private val nonPrimaryUserHandle = UserHandle(ActivityManager.RunningTaskInfo().userId + 10)
private var taskIdCounter = 0
- private fun getUniqueId(): Int { return ++taskIdCounter }
+ private fun getUniqueId(): Int {
+ return ++taskIdCounter
+ }
@Before
fun setup() {
- MockitoAnnotations.initMocks(this)
splitSelectStateController =
SplitSelectStateController(
context,
@@ -81,7 +82,8 @@ class SplitSelectStateControllerTest {
depthController,
statsLogManager,
systemUiProxy,
- recentsModel
+ recentsModel,
+ null /*activityBackCallback*/
)
}
@@ -109,13 +111,15 @@ class SplitSelectStateControllerTest {
// Capture callback from recentsModel#getTasks()
val consumer =
- withArgCaptor<Consumer<ArrayList<GroupTask>>> {
- splitSelectStateController.findLastActiveTasksAndRunCallback(
- listOf(nonMatchingComponent),
- taskConsumer
- )
- verify(recentsModel).getTasks(capture())
- }
+ argumentCaptor<Consumer<ArrayList<GroupTask>>> {
+ splitSelectStateController.findLastActiveTasksAndRunCallback(
+ listOf(nonMatchingComponent),
+ false /* findExactPairMatch */,
+ taskConsumer
+ )
+ verify(recentsModel).getTasks(capture())
+ }
+ .lastValue
// Send our mocked tasks
consumer.accept(tasks)
@@ -160,13 +164,15 @@ class SplitSelectStateControllerTest {
// Capture callback from recentsModel#getTasks()
val consumer =
- withArgCaptor<Consumer<ArrayList<GroupTask>>> {
- splitSelectStateController.findLastActiveTasksAndRunCallback(
- listOf(matchingComponent),
- taskConsumer
- )
- verify(recentsModel).getTasks(capture())
- }
+ argumentCaptor<Consumer<ArrayList<GroupTask>>> {
+ splitSelectStateController.findLastActiveTasksAndRunCallback(
+ listOf(matchingComponent),
+ false /* findExactPairMatch */,
+ taskConsumer
+ )
+ verify(recentsModel).getTasks(capture())
+ }
+ .lastValue
// Send our mocked tasks
consumer.accept(tasks)
@@ -199,13 +205,15 @@ class SplitSelectStateControllerTest {
// Capture callback from recentsModel#getTasks()
val consumer =
- withArgCaptor<Consumer<ArrayList<GroupTask>>> {
- splitSelectStateController.findLastActiveTasksAndRunCallback(
- listOf(nonPrimaryUserComponent),
- taskConsumer
- )
- verify(recentsModel).getTasks(capture())
- }
+ argumentCaptor<Consumer<ArrayList<GroupTask>>> {
+ splitSelectStateController.findLastActiveTasksAndRunCallback(
+ listOf(nonPrimaryUserComponent),
+ false /* findExactPairMatch */,
+ taskConsumer
+ )
+ verify(recentsModel).getTasks(capture())
+ }
+ .lastValue
// Send our mocked tasks
consumer.accept(tasks)
@@ -253,13 +261,15 @@ class SplitSelectStateControllerTest {
// Capture callback from recentsModel#getTasks()
val consumer =
- withArgCaptor<Consumer<ArrayList<GroupTask>>> {
- splitSelectStateController.findLastActiveTasksAndRunCallback(
- listOf(nonPrimaryUserComponent),
- taskConsumer
- )
- verify(recentsModel).getTasks(capture())
- }
+ argumentCaptor<Consumer<ArrayList<GroupTask>>> {
+ splitSelectStateController.findLastActiveTasksAndRunCallback(
+ listOf(nonPrimaryUserComponent),
+ false /* findExactPairMatch */,
+ taskConsumer
+ )
+ verify(recentsModel).getTasks(capture())
+ }
+ .lastValue
// Send our mocked tasks
consumer.accept(tasks)
@@ -304,13 +314,15 @@ class SplitSelectStateControllerTest {
// Capture callback from recentsModel#getTasks()
val consumer =
- withArgCaptor<Consumer<ArrayList<GroupTask>>> {
- splitSelectStateController.findLastActiveTasksAndRunCallback(
- listOf(matchingComponent),
- taskConsumer
- )
- verify(recentsModel).getTasks(capture())
- }
+ argumentCaptor<Consumer<ArrayList<GroupTask>>> {
+ splitSelectStateController.findLastActiveTasksAndRunCallback(
+ listOf(matchingComponent),
+ false /* findExactPairMatch */,
+ taskConsumer
+ )
+ verify(recentsModel).getTasks(capture())
+ }
+ .lastValue
// Send our mocked tasks
consumer.accept(tasks)
@@ -325,10 +337,7 @@ class SplitSelectStateControllerTest {
ComponentKey(ComponentName(matchingPackage, matchingClass), primaryUserHandle)
val groupTask1 =
- generateGroupTask(
- ComponentName("hotdog", "pie"),
- ComponentName("pumpkin", "pie")
- )
+ generateGroupTask(ComponentName("hotdog", "pie"), ComponentName("pumpkin", "pie"))
val groupTask2 =
generateGroupTask(
ComponentName("pomegranate", "juice"),
@@ -359,13 +368,15 @@ class SplitSelectStateControllerTest {
// Capture callback from recentsModel#getTasks()
val consumer =
- withArgCaptor<Consumer<ArrayList<GroupTask>>> {
- splitSelectStateController.findLastActiveTasksAndRunCallback(
- listOf(nonMatchingComponent, matchingComponent),
- taskConsumer
- )
- verify(recentsModel).getTasks(capture())
- }
+ argumentCaptor<Consumer<ArrayList<GroupTask>>> {
+ splitSelectStateController.findLastActiveTasksAndRunCallback(
+ listOf(nonMatchingComponent, matchingComponent),
+ false /* findExactPairMatch */,
+ taskConsumer
+ )
+ verify(recentsModel).getTasks(capture())
+ }
+ .lastValue
// Send our mocked tasks
consumer.accept(tasks)
@@ -379,10 +390,7 @@ class SplitSelectStateControllerTest {
ComponentKey(ComponentName(matchingPackage, matchingClass), primaryUserHandle)
val groupTask1 =
- generateGroupTask(
- ComponentName("hotdog", "pie"),
- ComponentName("pumpkin", "pie")
- )
+ generateGroupTask(ComponentName("hotdog", "pie"), ComponentName("pumpkin", "pie"))
val groupTask2 =
generateGroupTask(
ComponentName("pomegranate", "juice"),
@@ -413,13 +421,15 @@ class SplitSelectStateControllerTest {
// Capture callback from recentsModel#getTasks()
val consumer =
- withArgCaptor<Consumer<ArrayList<GroupTask>>> {
- splitSelectStateController.findLastActiveTasksAndRunCallback(
- listOf(matchingComponent, matchingComponent),
- taskConsumer
- )
- verify(recentsModel).getTasks(capture())
- }
+ argumentCaptor<Consumer<ArrayList<GroupTask>>> {
+ splitSelectStateController.findLastActiveTasksAndRunCallback(
+ listOf(matchingComponent, matchingComponent),
+ false /* findExactPairMatch */,
+ taskConsumer
+ )
+ verify(recentsModel).getTasks(capture())
+ }
+ .lastValue
// Send our mocked tasks
consumer.accept(tasks)
@@ -477,14 +487,68 @@ class SplitSelectStateControllerTest {
// Capture callback from recentsModel#getTasks()
val consumer =
- withArgCaptor<Consumer<ArrayList<GroupTask>>> {
- splitSelectStateController.findLastActiveTasksAndRunCallback(
- listOf(matchingComponent, matchingComponent),
- taskConsumer
- )
- verify(recentsModel).getTasks(capture())
+ argumentCaptor<Consumer<ArrayList<GroupTask>>> {
+ splitSelectStateController.findLastActiveTasksAndRunCallback(
+ listOf(matchingComponent, matchingComponent),
+ false /* findExactPairMatch */,
+ taskConsumer
+ )
+ verify(recentsModel).getTasks(capture())
+ }
+ .lastValue
+
+ // Send our mocked tasks
+ consumer.accept(tasks)
+ }
+
+ @Test
+ fun activeTasks_multipleSearchShouldFindExactPairMatch() {
+ val matchingPackage = "hotdog"
+ val matchingClass = "juice"
+ val matchingComponent =
+ ComponentKey(ComponentName(matchingPackage, matchingClass), primaryUserHandle)
+ val matchingPackage2 = "pomegranate"
+ val matchingClass2 = "juice"
+ val matchingComponent2 =
+ ComponentKey(ComponentName(matchingPackage2, matchingClass2), primaryUserHandle)
+
+ val groupTask1 =
+ generateGroupTask(ComponentName("hotdog", "pie"), ComponentName("pumpkin", "pie"))
+ val groupTask2 =
+ generateGroupTask(
+ ComponentName(matchingPackage2, matchingClass2),
+ ComponentName(matchingPackage, matchingClass)
+ )
+ val groupTask3 =
+ generateGroupTask(
+ ComponentName("hotdog", "pie"),
+ ComponentName(matchingPackage, matchingClass)
+ )
+ val tasks: ArrayList<GroupTask> = ArrayList()
+ tasks.add(groupTask3)
+ tasks.add(groupTask2)
+ tasks.add(groupTask1)
+
+ // Assertions happen in the callback we get from what we pass into
+ // #findLastActiveTasksAndRunCallback
+ val taskConsumer =
+ Consumer<List<Task>> {
+ assertEquals("Expected array length 1", 1, it.size)
+ assertEquals("Found wrong task", it[0], groupTask2.task1)
}
+ // Capture callback from recentsModel#getTasks()
+ val consumer =
+ argumentCaptor<Consumer<ArrayList<GroupTask>>> {
+ splitSelectStateController.findLastActiveTasksAndRunCallback(
+ listOf(matchingComponent2, matchingComponent),
+ true /* findExactPairMatch */,
+ taskConsumer
+ )
+ verify(recentsModel).getTasks(capture())
+ }
+ .lastValue
+
// Send our mocked tasks
consumer.accept(tasks)
}
@@ -529,7 +593,7 @@ class SplitSelectStateControllerTest {
@Test
fun secondPendingIntentSet() {
val itemInfo = ItemInfo()
- `when`(pendingIntent.creatorUserHandle).thenReturn(primaryUserHandle)
+ whenever(pendingIntent.creatorUserHandle).thenReturn(primaryUserHandle)
splitSelectStateController.setInitialTaskSelect(null, 0, itemInfo, null, 1)
splitSelectStateController.setSecondTask(pendingIntent)
assertTrue(splitSelectStateController.isBothSplitAppsConfirmed)
@@ -558,7 +622,7 @@ class SplitSelectStateControllerTest {
return GroupTask(
task1,
task2,
- SplitConfigurationOptions.SplitBounds(Rect(), Rect(), -1, -1)
+ SplitConfigurationOptions.SplitBounds(Rect(), Rect(), -1, -1, SNAP_TO_50_50)
)
}
@@ -590,7 +654,7 @@ class SplitSelectStateControllerTest {
return GroupTask(
task1,
task2,
- SplitConfigurationOptions.SplitBounds(Rect(), Rect(), -1, -1)
+ SplitConfigurationOptions.SplitBounds(Rect(), Rect(), -1, -1, SNAP_TO_50_50)
)
}
}
diff --git a/quickstep/tests/src/com/android/quickstep/util/TaskGridNavHelperTest.java b/quickstep/tests/src/com/android/quickstep/util/TaskGridNavHelperTest.java
new file mode 100644
index 0000000000..7ef4910ce5
--- /dev/null
+++ b/quickstep/tests/src/com/android/quickstep/util/TaskGridNavHelperTest.java
@@ -0,0 +1,510 @@
+/*
+ * Copyright (C) 2023 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.quickstep.util;
+
+import static com.android.quickstep.util.TaskGridNavHelper.CLEAR_ALL_PLACEHOLDER_ID;
+import static com.android.quickstep.util.TaskGridNavHelper.INVALID_FOCUSED_TASK_ID;
+
+import static org.junit.Assert.assertEquals;
+
+import com.android.launcher3.util.IntArray;
+
+import org.junit.Test;
+
+public class TaskGridNavHelperTest {
+
+ @Test
+ public void equalLengthRows_noFocused_onTop_pressDown_goesToBottom() {
+ IntArray topIds = IntArray.wrap(1, 3, 5);
+ IntArray bottomIds = IntArray.wrap(2, 4, 6);
+ int currentPageTaskViewId = 1;
+ int delta = 1;
+ @TaskGridNavHelper.TASK_NAV_DIRECTION int direction = TaskGridNavHelper.DIRECTION_DOWN;
+ boolean cycle = true;
+ TaskGridNavHelper taskGridNavHelper =
+ new TaskGridNavHelper(topIds, bottomIds, INVALID_FOCUSED_TASK_ID);
+
+ int nextGridPage =
+ taskGridNavHelper.getNextGridPage(currentPageTaskViewId, delta, direction, cycle);
+
+ assertEquals("Wrong next page returned.", 2, nextGridPage);
+ }
+
+ @Test
+ public void equalLengthRows_noFocused_onTop_pressUp_goesToBottom() {
+ IntArray topIds = IntArray.wrap(1, 3, 5);
+ IntArray bottomIds = IntArray.wrap(2, 4, 6);
+ int currentPageTaskViewId = 1;
+ int delta = 1;
+ @TaskGridNavHelper.TASK_NAV_DIRECTION int direction = TaskGridNavHelper.DIRECTION_UP;
+ boolean cycle = true;
+ TaskGridNavHelper taskGridNavHelper =
+ new TaskGridNavHelper(topIds, bottomIds, INVALID_FOCUSED_TASK_ID);
+
+ int nextGridPage =
+ taskGridNavHelper.getNextGridPage(currentPageTaskViewId, delta, direction, cycle);
+
+ assertEquals("Wrong next page returned.", 2, nextGridPage);
+ }
+
+ @Test
+ public void equalLengthRows_noFocused_onBottom_pressDown_goesToTop() {
+ IntArray topIds = IntArray.wrap(1, 3, 5);
+ IntArray bottomIds = IntArray.wrap(2, 4, 6);
+ int currentPageTaskViewId = 2;
+ int delta = 1;
+ @TaskGridNavHelper.TASK_NAV_DIRECTION int direction = TaskGridNavHelper.DIRECTION_DOWN;
+ boolean cycle = true;
+ TaskGridNavHelper taskGridNavHelper =
+ new TaskGridNavHelper(topIds, bottomIds, INVALID_FOCUSED_TASK_ID);
+
+ int nextGridPage =
+ taskGridNavHelper.getNextGridPage(currentPageTaskViewId, delta, direction, cycle);
+
+ assertEquals("Wrong next page returned.", 1, nextGridPage);
+ }
+
+ @Test
+ public void equalLengthRows_noFocused_onBottom_pressUp_goesToTop() {
+ IntArray topIds = IntArray.wrap(1, 3, 5);
+ IntArray bottomIds = IntArray.wrap(2, 4, 6);
+ int currentPageTaskViewId = 2;
+ int delta = 1;
+ @TaskGridNavHelper.TASK_NAV_DIRECTION int direction = TaskGridNavHelper.DIRECTION_UP;
+ boolean cycle = true;
+ TaskGridNavHelper taskGridNavHelper =
+ new TaskGridNavHelper(topIds, bottomIds, INVALID_FOCUSED_TASK_ID);
+
+ int nextGridPage =
+ taskGridNavHelper.getNextGridPage(currentPageTaskViewId, delta, direction, cycle);
+
+ assertEquals("Wrong next page returned.", 1, nextGridPage);
+ }
+
+ @Test
+ public void equalLengthRows_noFocused_onTop_pressLeft_goesLeft() {
+ IntArray topIds = IntArray.wrap(1, 3, 5);
+ IntArray bottomIds = IntArray.wrap(2, 4, 6);
+ int currentPageTaskViewId = 1;
+ int delta = 1;
+ @TaskGridNavHelper.TASK_NAV_DIRECTION int direction = TaskGridNavHelper.DIRECTION_LEFT;
+ boolean cycle = true;
+ TaskGridNavHelper taskGridNavHelper =
+ new TaskGridNavHelper(topIds, bottomIds, INVALID_FOCUSED_TASK_ID);
+
+ int nextGridPage =
+ taskGridNavHelper.getNextGridPage(currentPageTaskViewId, delta, direction, cycle);
+
+ assertEquals("Wrong next page returned.", 3, nextGridPage);
+ }
+
+ @Test
+ public void equalLengthRows_noFocused_onBottom_pressLeft_goesLeft() {
+ IntArray topIds = IntArray.wrap(1, 3, 5);
+ IntArray bottomIds = IntArray.wrap(2, 4, 6);
+ int currentPageTaskViewId = 2;
+ int delta = 1;
+ @TaskGridNavHelper.TASK_NAV_DIRECTION int direction = TaskGridNavHelper.DIRECTION_LEFT;
+ boolean cycle = true;
+ TaskGridNavHelper taskGridNavHelper =
+ new TaskGridNavHelper(topIds, bottomIds, INVALID_FOCUSED_TASK_ID);
+
+ int nextGridPage =
+ taskGridNavHelper.getNextGridPage(currentPageTaskViewId, delta, direction, cycle);
+
+ assertEquals("Wrong next page returned.", 4, nextGridPage);
+ }
+
+ @Test
+ public void equalLengthRows_noFocused_onTop_secondItem_pressRight_goesRight() {
+ IntArray topIds = IntArray.wrap(1, 3, 5);
+ IntArray bottomIds = IntArray.wrap(2, 4, 6);
+ int currentPageTaskViewId = 3;
+ int delta = -1;
+ @TaskGridNavHelper.TASK_NAV_DIRECTION int direction = TaskGridNavHelper.DIRECTION_RIGHT;
+ boolean cycle = true;
+ TaskGridNavHelper taskGridNavHelper =
+ new TaskGridNavHelper(topIds, bottomIds, INVALID_FOCUSED_TASK_ID);
+
+ int nextGridPage =
+ taskGridNavHelper.getNextGridPage(currentPageTaskViewId, delta, direction, cycle);
+
+ assertEquals("Wrong next page returned.", 1, nextGridPage);
+ }
+
+ @Test
+ public void equalLengthRows_noFocused_onBottom_secondItem_pressRight_goesRight() {
+ IntArray topIds = IntArray.wrap(1, 3, 5);
+ IntArray bottomIds = IntArray.wrap(2, 4, 6);
+ int currentPageTaskViewId = 4;
+ int delta = -1;
+ @TaskGridNavHelper.TASK_NAV_DIRECTION int direction = TaskGridNavHelper.DIRECTION_RIGHT;
+ boolean cycle = true;
+ TaskGridNavHelper taskGridNavHelper =
+ new TaskGridNavHelper(topIds, bottomIds, INVALID_FOCUSED_TASK_ID);
+
+ int nextGridPage =
+ taskGridNavHelper.getNextGridPage(currentPageTaskViewId, delta, direction, cycle);
+
+ assertEquals("Wrong next page returned.", 2, nextGridPage);
+ }
+
+ @Test
+ public void equalLengthRows_noFocused_onTop_pressRight_cycleToClearAll() {
+ IntArray topIds = IntArray.wrap(1, 3, 5);
+ IntArray bottomIds = IntArray.wrap(2, 4, 6);
+ int currentPageTaskViewId = 1;
+ int delta = -1;
+ @TaskGridNavHelper.TASK_NAV_DIRECTION int direction = TaskGridNavHelper.DIRECTION_RIGHT;
+ boolean cycle = true;
+ TaskGridNavHelper taskGridNavHelper =
+ new TaskGridNavHelper(topIds, bottomIds, INVALID_FOCUSED_TASK_ID);
+
+ int nextGridPage =
+ taskGridNavHelper.getNextGridPage(currentPageTaskViewId, delta, direction, cycle);
+
+ assertEquals("Wrong next page returned.", CLEAR_ALL_PLACEHOLDER_ID, nextGridPage);
+ }
+
+ @Test
+ public void equalLengthRows_noFocused_onBottom_pressRight_cycleToClearAll() {
+ IntArray topIds = IntArray.wrap(1, 3, 5);
+ IntArray bottomIds = IntArray.wrap(2, 4, 6);
+ int currentPageTaskViewId = 2;
+ int delta = -1;
+ @TaskGridNavHelper.TASK_NAV_DIRECTION int direction = TaskGridNavHelper.DIRECTION_RIGHT;
+ boolean cycle = true;
+ TaskGridNavHelper taskGridNavHelper =
+ new TaskGridNavHelper(topIds, bottomIds, INVALID_FOCUSED_TASK_ID);
+
+ int nextGridPage =
+ taskGridNavHelper.getNextGridPage(currentPageTaskViewId, delta, direction, cycle);
+
+ assertEquals("Wrong next page returned.", CLEAR_ALL_PLACEHOLDER_ID, nextGridPage);
+ }
+
+ @Test
+ public void equalLengthRows_noFocused_onTop_lastItem_pressLeft_toClearAll() {
+ IntArray topIds = IntArray.wrap(1, 3, 5);
+ IntArray bottomIds = IntArray.wrap(2, 4, 6);
+ int currentPageTaskViewId = 5;
+ int delta = 1;
+ @TaskGridNavHelper.TASK_NAV_DIRECTION int direction = TaskGridNavHelper.DIRECTION_LEFT;
+ boolean cycle = true;
+ TaskGridNavHelper taskGridNavHelper =
+ new TaskGridNavHelper(topIds, bottomIds, INVALID_FOCUSED_TASK_ID);
+
+ int nextGridPage =
+ taskGridNavHelper.getNextGridPage(currentPageTaskViewId, delta, direction, cycle);
+
+ assertEquals("Wrong next page returned.", CLEAR_ALL_PLACEHOLDER_ID, nextGridPage);
+ }
+
+ @Test
+ public void equalLengthRows_noFocused_onBottom_lastItem_pressLeft_toClearAll() {
+ IntArray topIds = IntArray.wrap(1, 3, 5);
+ IntArray bottomIds = IntArray.wrap(2, 4, 6);
+ int currentPageTaskViewId = 6;
+ int delta = 1;
+ @TaskGridNavHelper.TASK_NAV_DIRECTION int direction = TaskGridNavHelper.DIRECTION_LEFT;
+ boolean cycle = true;
+ TaskGridNavHelper taskGridNavHelper =
+ new TaskGridNavHelper(topIds, bottomIds, INVALID_FOCUSED_TASK_ID);
+
+ int nextGridPage =
+ taskGridNavHelper.getNextGridPage(currentPageTaskViewId, delta, direction, cycle);
+
+ assertEquals("Wrong next page returned.", CLEAR_ALL_PLACEHOLDER_ID, nextGridPage);
+ }
+
+ @Test
+ public void equalLengthRows_noFocused_onClearAll_pressLeft_cycleToFirst() {
+ IntArray topIds = IntArray.wrap(1, 3, 5);
+ IntArray bottomIds = IntArray.wrap(2, 4, 6);
+ int currentPageTaskViewId = CLEAR_ALL_PLACEHOLDER_ID;
+ int delta = 1;
+ @TaskGridNavHelper.TASK_NAV_DIRECTION int direction = TaskGridNavHelper.DIRECTION_LEFT;
+ boolean cycle = true;
+ TaskGridNavHelper taskGridNavHelper =
+ new TaskGridNavHelper(topIds, bottomIds, INVALID_FOCUSED_TASK_ID);
+
+ int nextGridPage =
+ taskGridNavHelper.getNextGridPage(currentPageTaskViewId, delta, direction, cycle);
+
+ assertEquals("Wrong next page returned.", 1, nextGridPage);
+ }
+
+ @Test
+ public void equalLengthRows_noFocused_onClearAll_pressRight_toLastInBottom() {
+ IntArray topIds = IntArray.wrap(1, 3, 5);
+ IntArray bottomIds = IntArray.wrap(2, 4, 6);
+ int currentPageTaskViewId = CLEAR_ALL_PLACEHOLDER_ID;
+ int delta = -1;
+ @TaskGridNavHelper.TASK_NAV_DIRECTION int direction = TaskGridNavHelper.DIRECTION_RIGHT;
+ boolean cycle = true;
+ TaskGridNavHelper taskGridNavHelper =
+ new TaskGridNavHelper(topIds, bottomIds, INVALID_FOCUSED_TASK_ID);
+
+ int nextGridPage =
+ taskGridNavHelper.getNextGridPage(currentPageTaskViewId, delta, direction, cycle);
+
+ assertEquals("Wrong next page returned.", 6, nextGridPage);
+ }
+
+ @Test
+ public void equalLengthRows_withFocused_onFocused_pressLeft_toTop() {
+ IntArray topIds = IntArray.wrap(1, 3, 5);
+ IntArray bottomIds = IntArray.wrap(2, 4, 6);
+ int focusedTaskId = 99;
+ int currentPageTaskViewId = focusedTaskId;
+ int delta = 1;
+ @TaskGridNavHelper.TASK_NAV_DIRECTION int direction = TaskGridNavHelper.DIRECTION_LEFT;
+ boolean cycle = true;
+ TaskGridNavHelper taskGridNavHelper =
+ new TaskGridNavHelper(topIds, bottomIds, focusedTaskId);
+
+ int nextGridPage =
+ taskGridNavHelper.getNextGridPage(currentPageTaskViewId, delta, direction, cycle);
+
+ assertEquals("Wrong next page returned.", 1, nextGridPage);
+ }
+
+ @Test
+ public void equalLengthRows_withFocused_onFocused_pressUp_stayOnFocused() {
+ IntArray topIds = IntArray.wrap(1, 3, 5);
+ IntArray bottomIds = IntArray.wrap(2, 4, 6);
+ int focusedTaskId = 99;
+ int currentPageTaskViewId = focusedTaskId;
+ int delta = 1;
+ @TaskGridNavHelper.TASK_NAV_DIRECTION int direction = TaskGridNavHelper.DIRECTION_UP;
+ boolean cycle = true;
+ TaskGridNavHelper taskGridNavHelper =
+ new TaskGridNavHelper(topIds, bottomIds, focusedTaskId);
+
+ int nextGridPage =
+ taskGridNavHelper.getNextGridPage(currentPageTaskViewId, delta, direction, cycle);
+
+ assertEquals("Wrong next page returned.", focusedTaskId, nextGridPage);
+ }
+
+ @Test
+ public void equalLengthRows_withFocused_onFocused_pressDown_stayOnFocused() {
+ IntArray topIds = IntArray.wrap(1, 3, 5);
+ IntArray bottomIds = IntArray.wrap(2, 4, 6);
+ int focusedTaskId = 99;
+ int currentPageTaskViewId = focusedTaskId;
+ int delta = 1;
+ @TaskGridNavHelper.TASK_NAV_DIRECTION int direction = TaskGridNavHelper.DIRECTION_DOWN;
+ boolean cycle = true;
+ TaskGridNavHelper taskGridNavHelper =
+ new TaskGridNavHelper(topIds, bottomIds, focusedTaskId);
+
+ int nextGridPage =
+ taskGridNavHelper.getNextGridPage(currentPageTaskViewId, delta, direction, cycle);
+
+ assertEquals("Wrong next page returned.", focusedTaskId, nextGridPage);
+ }
+
+ @Test
+ public void equalLengthRows_withFocused_onFocused_pressRight_cycleToClearAll() {
+ IntArray topIds = IntArray.wrap(1, 3, 5);
+ IntArray bottomIds = IntArray.wrap(2, 4, 6);
+ int focusedTaskId = 99;
+ int currentPageTaskViewId = focusedTaskId;
+ int delta = -1;
+ @TaskGridNavHelper.TASK_NAV_DIRECTION int direction = TaskGridNavHelper.DIRECTION_RIGHT;
+ boolean cycle = true;
+ TaskGridNavHelper taskGridNavHelper =
+ new TaskGridNavHelper(topIds, bottomIds, focusedTaskId);
+
+ int nextGridPage =
+ taskGridNavHelper.getNextGridPage(currentPageTaskViewId, delta, direction, cycle);
+
+ assertEquals("Wrong next page returned.", CLEAR_ALL_PLACEHOLDER_ID, nextGridPage);
+ }
+
+ @Test
+ public void equalLengthRows_withFocused_onClearAll_pressLeft_cycleToFocusedTask() {
+ IntArray topIds = IntArray.wrap(1, 3, 5);
+ IntArray bottomIds = IntArray.wrap(2, 4, 6);
+ int focusedTaskId = 99;
+ int currentPageTaskViewId = CLEAR_ALL_PLACEHOLDER_ID;
+ int delta = 1;
+ @TaskGridNavHelper.TASK_NAV_DIRECTION int direction = TaskGridNavHelper.DIRECTION_LEFT;
+ boolean cycle = true;
+ TaskGridNavHelper taskGridNavHelper =
+ new TaskGridNavHelper(topIds, bottomIds, focusedTaskId);
+
+ int nextGridPage =
+ taskGridNavHelper.getNextGridPage(currentPageTaskViewId, delta, direction, cycle);
+
+ assertEquals("Wrong next page returned.", focusedTaskId, nextGridPage);
+ }
+
+ @Test
+ public void longerTopRow_noFocused_atEndTopBeyondBottom_pressDown_stayTop() {
+ IntArray topIds = IntArray.wrap(1, 3, 5, 7);
+ IntArray bottomIds = IntArray.wrap(2, 4, 6);
+ int currentPageTaskViewId = 7;
+ int delta = 1;
+ @TaskGridNavHelper.TASK_NAV_DIRECTION int direction = TaskGridNavHelper.DIRECTION_DOWN;
+ boolean cycle = true;
+ TaskGridNavHelper taskGridNavHelper =
+ new TaskGridNavHelper(topIds, bottomIds, INVALID_FOCUSED_TASK_ID);
+
+ int nextGridPage =
+ taskGridNavHelper.getNextGridPage(currentPageTaskViewId, delta, direction, cycle);
+
+ assertEquals("Wrong next page returned.", 7, nextGridPage);
+ }
+
+ @Test
+ public void longerTopRow_noFocused_atEndTopBeyondBottom_pressUp_stayTop() {
+ IntArray topIds = IntArray.wrap(1, 3, 5, 7);
+ IntArray bottomIds = IntArray.wrap(2, 4, 6);
+ int currentPageTaskViewId = 7;
+ int delta = 1;
+ @TaskGridNavHelper.TASK_NAV_DIRECTION int direction = TaskGridNavHelper.DIRECTION_UP;
+ boolean cycle = true;
+ TaskGridNavHelper taskGridNavHelper =
+ new TaskGridNavHelper(topIds, bottomIds, INVALID_FOCUSED_TASK_ID);
+
+ int nextGridPage =
+ taskGridNavHelper.getNextGridPage(currentPageTaskViewId, delta, direction, cycle);
+
+ assertEquals("Wrong next page returned.", 7, nextGridPage);
+ }
+
+ @Test
+ public void longerTopRow_noFocused_atEndBottom_pressLeft_goToTop() {
+ IntArray topIds = IntArray.wrap(1, 3, 5, 7);
+ IntArray bottomIds = IntArray.wrap(2, 4, 6);
+ int currentPageTaskViewId = 6;
+ int delta = 1;
+ @TaskGridNavHelper.TASK_NAV_DIRECTION int direction = TaskGridNavHelper.DIRECTION_LEFT;
+ boolean cycle = true;
+ TaskGridNavHelper taskGridNavHelper =
+ new TaskGridNavHelper(topIds, bottomIds, INVALID_FOCUSED_TASK_ID);
+
+ int nextGridPage =
+ taskGridNavHelper.getNextGridPage(currentPageTaskViewId, delta, direction, cycle);
+
+ assertEquals("Wrong next page returned.", 7, nextGridPage);
+ }
+
+ @Test
+ public void longerTopRow_noFocused_atClearAll_pressRight_goToLonger() {
+ IntArray topIds = IntArray.wrap(1, 3, 5, 7);
+ IntArray bottomIds = IntArray.wrap(2, 4, 6);
+ int currentPageTaskViewId = CLEAR_ALL_PLACEHOLDER_ID;
+ int delta = -1;
+ @TaskGridNavHelper.TASK_NAV_DIRECTION int direction = TaskGridNavHelper.DIRECTION_RIGHT;
+ boolean cycle = true;
+ TaskGridNavHelper taskGridNavHelper =
+ new TaskGridNavHelper(topIds, bottomIds, INVALID_FOCUSED_TASK_ID);
+
+ int nextGridPage =
+ taskGridNavHelper.getNextGridPage(currentPageTaskViewId, delta, direction, cycle);
+
+ assertEquals("Wrong next page returned.", 7, nextGridPage);
+ }
+
+ @Test
+ public void longerBottomRow_noFocused_atClearAll_pressRight_goToLonger() {
+ IntArray topIds = IntArray.wrap(1, 3, 5);
+ IntArray bottomIds = IntArray.wrap(2, 4, 6, 7);
+ int currentPageTaskViewId = CLEAR_ALL_PLACEHOLDER_ID;
+ int delta = -1;
+ @TaskGridNavHelper.TASK_NAV_DIRECTION int direction = TaskGridNavHelper.DIRECTION_RIGHT;
+ boolean cycle = true;
+ TaskGridNavHelper taskGridNavHelper =
+ new TaskGridNavHelper(topIds, bottomIds, INVALID_FOCUSED_TASK_ID);
+
+ int nextGridPage =
+ taskGridNavHelper.getNextGridPage(currentPageTaskViewId, delta, direction, cycle);
+
+ assertEquals("Wrong next page returned.", 7, nextGridPage);
+ }
+
+ @Test
+ public void equalLengthRows_noFocused_onTop_pressTab_goesToBottom() {
+ IntArray topIds = IntArray.wrap(1, 3, 5);
+ IntArray bottomIds = IntArray.wrap(2, 4, 6);
+ int currentPageTaskViewId = 1;
+ int delta = 1;
+ @TaskGridNavHelper.TASK_NAV_DIRECTION int direction = TaskGridNavHelper.DIRECTION_TAB;
+ boolean cycle = true;
+ TaskGridNavHelper taskGridNavHelper =
+ new TaskGridNavHelper(topIds, bottomIds, INVALID_FOCUSED_TASK_ID);
+
+ int nextGridPage =
+ taskGridNavHelper.getNextGridPage(currentPageTaskViewId, delta, direction, cycle);
+
+ assertEquals("Wrong next page returned.", 2, nextGridPage);
+ }
+
+ @Test
+ public void equalLengthRows_noFocused_onBottom_pressTab_goesToNextTop() {
+ IntArray topIds = IntArray.wrap(1, 3, 5);
+ IntArray bottomIds = IntArray.wrap(2, 4, 6);
+ int currentPageTaskViewId = 2;
+ int delta = 1;
+ @TaskGridNavHelper.TASK_NAV_DIRECTION int direction = TaskGridNavHelper.DIRECTION_TAB;
+ boolean cycle = true;
+ TaskGridNavHelper taskGridNavHelper =
+ new TaskGridNavHelper(topIds, bottomIds, INVALID_FOCUSED_TASK_ID);
+
+ int nextGridPage =
+ taskGridNavHelper.getNextGridPage(currentPageTaskViewId, delta, direction, cycle);
+
+ assertEquals("Wrong next page returned.", 3, nextGridPage);
+ }
+
+ @Test
+ public void equalLengthRows_noFocused_onTop_pressTabWithShift_goesToPreviousBottom() {
+ IntArray topIds = IntArray.wrap(1, 3, 5);
+ IntArray bottomIds = IntArray.wrap(2, 4, 6);
+ int currentPageTaskViewId = 3;
+ int delta = -1;
+ @TaskGridNavHelper.TASK_NAV_DIRECTION int direction = TaskGridNavHelper.DIRECTION_TAB;
+ boolean cycle = true;
+ TaskGridNavHelper taskGridNavHelper =
+ new TaskGridNavHelper(topIds, bottomIds, INVALID_FOCUSED_TASK_ID);
+
+ int nextGridPage =
+ taskGridNavHelper.getNextGridPage(currentPageTaskViewId, delta, direction, cycle);
+
+ assertEquals("Wrong next page returned.", 2, nextGridPage);
+ }
+
+ @Test
+ public void equalLengthRows_noFocused_onBottom_pressTabWithShift_goesToTop() {
+ IntArray topIds = IntArray.wrap(1, 3, 5);
+ IntArray bottomIds = IntArray.wrap(2, 4, 6);
+ int currentPageTaskViewId = 2;
+ int delta = -1;
+ @TaskGridNavHelper.TASK_NAV_DIRECTION int direction = TaskGridNavHelper.DIRECTION_TAB;
+ boolean cycle = true;
+ TaskGridNavHelper taskGridNavHelper =
+ new TaskGridNavHelper(topIds, bottomIds, INVALID_FOCUSED_TASK_ID);
+
+ int nextGridPage =
+ taskGridNavHelper.getNextGridPage(currentPageTaskViewId, delta, direction, cycle);
+
+ assertEquals("Wrong next page returned.", 1, nextGridPage);
+ }
+}
diff --git a/quickstep/tests/src/com/android/quickstep/util/TaskKeyByLastActiveTimeCacheTest.java b/quickstep/tests/src/com/android/quickstep/util/TaskKeyByLastActiveTimeCacheTest.java
new file mode 100644
index 0000000000..ea2688a0fc
--- /dev/null
+++ b/quickstep/tests/src/com/android/quickstep/util/TaskKeyByLastActiveTimeCacheTest.java
@@ -0,0 +1,281 @@
+/*
+ * Copyright (C) 2023 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.quickstep.util;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertNotNull;
+import static junit.framework.Assert.assertNull;
+
+import android.content.ComponentName;
+import android.content.Intent;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.systemui.shared.recents.model.Task;
+import com.android.systemui.shared.recents.model.ThumbnailData;
+
+import org.junit.Test;
+
+@SmallTest
+public class TaskKeyByLastActiveTimeCacheTest {
+ @Test
+ public void add() {
+ TaskKeyByLastActiveTimeCache<ThumbnailData> cache = new TaskKeyByLastActiveTimeCache<>(3);
+ Task.TaskKey key1 = new Task.TaskKey(1, 0, new Intent(),
+ new ComponentName("", ""), 0, 1);
+ ThumbnailData data1 = new ThumbnailData();
+ cache.put(key1, data1);
+
+ Task.TaskKey key2 = new Task.TaskKey(2, 0, new Intent(),
+ new ComponentName("", ""), 0, 2);
+ ThumbnailData data2 = new ThumbnailData();
+ cache.put(key2, data2);
+
+ assertEquals(2, cache.getSize());
+ assertEquals(data1, cache.getAndInvalidateIfModified(key1));
+ assertEquals(data2, cache.getAndInvalidateIfModified(key2));
+
+ assertEquals(2, cache.getQueue().size());
+ assertEquals(key1, cache.getQueue().poll());
+ assertEquals(key2, cache.getQueue().poll());
+ }
+
+ @Test
+ public void addSameTasksWithSameLastActiveTimeTwice() {
+ // Add 2 tasks with same id and last active time, it should only have 1 entry in cache
+ TaskKeyByLastActiveTimeCache<ThumbnailData> cache = new TaskKeyByLastActiveTimeCache<>(3);
+ Task.TaskKey key1 = new Task.TaskKey(1, 0, new Intent(),
+ new ComponentName("", ""), 0, 1000);
+ ThumbnailData data1 = new ThumbnailData();
+ cache.put(key1, data1);
+
+ Task.TaskKey key2 = new Task.TaskKey(1, 0, new Intent(),
+ new ComponentName("", ""), 0, 1000);
+ ThumbnailData data2 = new ThumbnailData();
+ cache.put(key2, data2);
+
+ assertEquals(1, cache.getSize());
+ assertEquals(data2, cache.getAndInvalidateIfModified(key2));
+
+ assertEquals(1, cache.getQueue().size());
+ assertEquals(key2, cache.getQueue().poll());
+ }
+
+ @Test
+ public void addSameTasksWithDifferentLastActiveTime() {
+ // Add 2 tasks with same id and different last active time, it should only have the
+ // higher last active time entry
+ TaskKeyByLastActiveTimeCache<ThumbnailData> cache = new TaskKeyByLastActiveTimeCache<>(3);
+ Task.TaskKey key1 = new Task.TaskKey(1, 0, new Intent(),
+ new ComponentName("", ""), 0, 1000);
+ ThumbnailData data1 = new ThumbnailData();
+ cache.put(key1, data1);
+
+ Task.TaskKey key2 = new Task.TaskKey(1, 0, new Intent(),
+ new ComponentName("", ""), 0, 2000);
+ ThumbnailData data2 = new ThumbnailData();
+ cache.put(key2, data2);
+
+ assertEquals(1, cache.getSize());
+ assertEquals(data2, cache.getAndInvalidateIfModified(key2));
+
+ assertEquals(1, cache.getQueue().size());
+ Task.TaskKey queueKey = cache.getQueue().poll();
+ assertEquals(key2, queueKey);
+ // TaskKey's equal method does not check last active time, so we check here
+ assertEquals(2000, queueKey.lastActiveTime);
+ }
+
+ @Test
+ public void remove() {
+ TaskKeyByLastActiveTimeCache<ThumbnailData> cache = new TaskKeyByLastActiveTimeCache<>(3);
+ Task.TaskKey key1 = new Task.TaskKey(1, 0, new Intent(),
+ new ComponentName("", ""), 0, 0);
+ cache.put(key1, new ThumbnailData());
+
+ cache.remove(key1);
+
+ assertEquals(0, cache.getSize());
+ assertEquals(0, cache.getQueue().size());
+ }
+
+ @Test
+ public void removeByStubKey() {
+ TaskKeyByLastActiveTimeCache<ThumbnailData> cache = new TaskKeyByLastActiveTimeCache<>(3);
+ Task.TaskKey key1 = new Task.TaskKey(1, 1, new Intent(),
+ new ComponentName("", ""), 1, 100);
+ cache.put(key1, new ThumbnailData());
+
+ Task.TaskKey stubKey = new Task.TaskKey(1, 0, new Intent(),
+ new ComponentName("", ""), 0, 0);
+ cache.remove(stubKey);
+
+ assertEquals(0, cache.getSize());
+ assertEquals(0, cache.getQueue().size());
+ }
+
+ @Test
+ public void evictAll() {
+ TaskKeyByLastActiveTimeCache<ThumbnailData> cache = new TaskKeyByLastActiveTimeCache<>(3);
+ Task.TaskKey key1 = new Task.TaskKey(1, 0, new Intent(),
+ new ComponentName("", ""), 0, 0);
+ cache.put(key1, new ThumbnailData());
+ Task.TaskKey key2 = new Task.TaskKey(2, 0, new Intent(),
+ new ComponentName("", ""), 0, 0);
+ cache.put(key2, new ThumbnailData());
+
+ cache.evictAll();
+
+ assertEquals(0, cache.getSize());
+ assertEquals(0, cache.getQueue().size());
+ }
+
+ @Test
+ public void removeAllByPredicate() {
+ TaskKeyByLastActiveTimeCache<ThumbnailData> cache = new TaskKeyByLastActiveTimeCache<>(3);
+ // Add user 1's tasks
+ Task.TaskKey user1Key1 = new Task.TaskKey(1, 0, new Intent(),
+ new ComponentName("", ""), 1, 0);
+ cache.put(user1Key1, new ThumbnailData());
+ Task.TaskKey user1Key2 = new Task.TaskKey(2, 0, new Intent(),
+ new ComponentName("", ""), 1, 0);
+ cache.put(user1Key2, new ThumbnailData());
+ // Add user 2's task
+ Task.TaskKey user2Key = new Task.TaskKey(3, 0, new Intent(),
+ new ComponentName("", ""), 2, 0);
+ ThumbnailData user2Data = new ThumbnailData();
+ cache.put(user2Key, user2Data);
+
+ cache.removeAll(key -> key.userId == 1);
+
+ // Only user 2's task remains
+ assertEquals(1, cache.getSize());
+ assertEquals(user2Data, cache.getAndInvalidateIfModified(user2Key));
+
+ assertEquals(1, cache.getQueue().size());
+ assertEquals(user2Key, cache.getQueue().poll());
+ }
+
+ @Test
+ public void getAndInvalidateIfModified() {
+ TaskKeyByLastActiveTimeCache<ThumbnailData> cache = new TaskKeyByLastActiveTimeCache<>(3);
+ // Add user 1's tasks
+ Task.TaskKey key1 = new Task.TaskKey(1, 0, new Intent(),
+ new ComponentName("", ""), 1, 0);
+ ThumbnailData data1 = new ThumbnailData();
+ cache.put(key1, data1);
+
+ // Get result with task key of same last active time
+ Task.TaskKey keyWithSameActiveTime = new Task.TaskKey(1, 0, new Intent(),
+ new ComponentName("", ""), 1, 0);
+ ThumbnailData result1 = cache.getAndInvalidateIfModified(keyWithSameActiveTime);
+ assertEquals(data1, result1);
+ assertEquals(1, cache.getQueue().size());
+
+ // Invalidate result with task key of new last active time
+ Task.TaskKey keyWithNewActiveTime = new Task.TaskKey(1, 0, new Intent(),
+ new ComponentName("", ""), 1, 1);
+ ThumbnailData result2 = cache.getAndInvalidateIfModified(keyWithNewActiveTime);
+ // No entry is retrieved because the key has higher last active time
+ assertNull(result2);
+ assertEquals(0, cache.getSize());
+ assertEquals(0, cache.getQueue().size());
+ }
+
+ @Test
+ public void removeByLastActiveTimeWhenOverMaxSize() {
+ TaskKeyByLastActiveTimeCache<ThumbnailData> cache = new TaskKeyByLastActiveTimeCache<>(2);
+ Task.TaskKey key1 = new Task.TaskKey(1, 0, new Intent(),
+ new ComponentName("", ""), 0, 200);
+ ThumbnailData task1 = new ThumbnailData();
+ cache.put(key1, task1);
+ Task.TaskKey key2 = new Task.TaskKey(2, 0, new Intent(),
+ new ComponentName("", ""), 0, 100);
+ ThumbnailData task2 = new ThumbnailData();
+ cache.put(key2, task2);
+
+ // Add the 3rd entry which will exceed the max cache size
+ Task.TaskKey key3 = new Task.TaskKey(3, 0, new Intent(),
+ new ComponentName("", ""), 0, 300);
+ ThumbnailData task3 = new ThumbnailData();
+ cache.put(key3, task3);
+
+ // Assert map size and check the remaining entries have higher active time
+ assertEquals(2, cache.getSize());
+ assertEquals(task1, cache.getAndInvalidateIfModified(key1));
+ assertEquals(task3, cache.getAndInvalidateIfModified(key3));
+ assertNull(cache.getAndInvalidateIfModified(key2));
+
+ // Assert queue size and check the remaining entries have higher active time
+ assertEquals(2, cache.getQueue().size());
+ Task.TaskKey queueKey1 = cache.getQueue().poll();
+ assertEquals(key1, queueKey1);
+ assertEquals(200, queueKey1.lastActiveTime);
+ Task.TaskKey queueKey2 = cache.getQueue().poll();
+ assertEquals(key3, queueKey2);
+ assertEquals(300, queueKey2.lastActiveTime);
+ }
+
+ @Test
+ public void updateIfAlreadyInCache() {
+ TaskKeyByLastActiveTimeCache<ThumbnailData> cache = new TaskKeyByLastActiveTimeCache<>(2);
+ Task.TaskKey key1 = new Task.TaskKey(1, 0, new Intent(),
+ new ComponentName("", ""), 0, 200);
+ cache.put(key1, new ThumbnailData());
+
+ // Update original data to new data
+ ThumbnailData newData = new ThumbnailData();
+ cache.updateIfAlreadyInCache(key1.id, newData);
+
+ // Data is updated to newData successfully
+ ThumbnailData result = cache.getAndInvalidateIfModified(key1);
+ assertEquals(newData, result);
+ }
+
+ @Test
+ public void updateCacheSizeAndInvalidateExcess() {
+ // Last active time are not in-sync with insertion order to simulate the real async case
+ TaskKeyByLastActiveTimeCache<ThumbnailData> cache = new TaskKeyByLastActiveTimeCache<>(4);
+ Task.TaskKey key1 = new Task.TaskKey(1, 0, new Intent(),
+ new ComponentName("", ""), 0, 200);
+ cache.put(key1, new ThumbnailData());
+
+ Task.TaskKey key2 = new Task.TaskKey(2, 0, new Intent(),
+ new ComponentName("", ""), 0, 100);
+ cache.put(key2, new ThumbnailData());
+
+ Task.TaskKey key3 = new Task.TaskKey(3, 0, new Intent(),
+ new ComponentName("", ""), 0, 400);
+ cache.put(key3, new ThumbnailData());
+
+ Task.TaskKey key4 = new Task.TaskKey(4, 0, new Intent(),
+ new ComponentName("", ""), 0, 300);
+ cache.put(key4, new ThumbnailData());
+
+ // Check that it has 4 entries before cache size changes
+ assertEquals(4, cache.getSize());
+ assertEquals(4, cache.getQueue().size());
+
+ // Update size to 2
+ cache.updateCacheSizeAndRemoveExcess(2);
+
+ // Number of entries becomes 2, only key3 and key4 remain
+ assertEquals(2, cache.getSize());
+ assertEquals(2, cache.getQueue().size());
+ assertNotNull(cache.getAndInvalidateIfModified(key3));
+ assertNotNull(cache.getAndInvalidateIfModified(key4));
+ }
+}
diff --git a/quickstep/tests/src/com/android/quickstep/util/TaskViewSimulatorTest.java b/quickstep/tests/src/com/android/quickstep/util/TaskViewSimulatorTest.java
index a54dc2da18..b365173663 100644
--- a/quickstep/tests/src/com/android/quickstep/util/TaskViewSimulatorTest.java
+++ b/quickstep/tests/src/com/android/quickstep/util/TaskViewSimulatorTest.java
@@ -18,11 +18,15 @@ package com.android.quickstep.util;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+import android.content.Context;
+import android.content.res.Configuration;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.RectF;
import android.util.ArrayMap;
+import android.util.DisplayMetrics;
import android.view.RemoteAnimationTarget;
import android.view.Surface;
@@ -35,7 +39,6 @@ import com.android.launcher3.util.DisplayController;
import com.android.launcher3.util.DisplayController.Info;
import com.android.launcher3.util.LauncherModelHelper;
import com.android.launcher3.util.NavigationMode;
-import com.android.launcher3.util.ReflectionHelpers;
import com.android.launcher3.util.RotationUtils;
import com.android.launcher3.util.WindowBounds;
import com.android.launcher3.util.window.CachedDisplayInfo;
@@ -61,6 +64,7 @@ public class TaskViewSimulatorTest {
public void taskProperlyScaled_portrait_noRotation_sameInsets1() {
new TaskMatrixVerifier()
.withLauncherSize(1200, 2450)
+ .withDensityDpi(420)
.withInsets(new Rect(0, 80, 0, 120))
.verifyNoTransforms();
}
@@ -69,6 +73,7 @@ public class TaskViewSimulatorTest {
public void taskProperlyScaled_portrait_noRotation_sameInsets2() {
new TaskMatrixVerifier()
.withLauncherSize(1200, 2450)
+ .withDensityDpi(420)
.withInsets(new Rect(55, 80, 55, 120))
.verifyNoTransforms();
}
@@ -77,6 +82,7 @@ public class TaskViewSimulatorTest {
public void taskProperlyScaled_landscape_noRotation_sameInsets1() {
new TaskMatrixVerifier()
.withLauncherSize(2450, 1250)
+ .withDensityDpi(420)
.withInsets(new Rect(0, 80, 0, 40))
.verifyNoTransforms();
}
@@ -85,6 +91,7 @@ public class TaskViewSimulatorTest {
public void taskProperlyScaled_landscape_noRotation_sameInsets2() {
new TaskMatrixVerifier()
.withLauncherSize(2450, 1250)
+ .withDensityDpi(420)
.withInsets(new Rect(0, 80, 120, 0))
.verifyNoTransforms();
}
@@ -93,6 +100,7 @@ public class TaskViewSimulatorTest {
public void taskProperlyScaled_landscape_noRotation_sameInsets3() {
new TaskMatrixVerifier()
.withLauncherSize(2450, 1250)
+ .withDensityDpi(420)
.withInsets(new Rect(55, 80, 55, 120))
.verifyNoTransforms();
}
@@ -101,6 +109,7 @@ public class TaskViewSimulatorTest {
public void taskProperlyScaled_landscape_rotated() {
new TaskMatrixVerifier()
.withLauncherSize(1200, 2450)
+ .withDensityDpi(420)
.withInsets(new Rect(0, 80, 0, 120))
.withAppBounds(
new Rect(0, 0, 2450, 1200),
@@ -112,6 +121,7 @@ public class TaskViewSimulatorTest {
private static class TaskMatrixVerifier extends TransformParams {
private Point mDisplaySize = new Point();
+ private int mDensityDpi = DisplayMetrics.DENSITY_DEFAULT;
private Rect mDisplayInsets = new Rect();
private Rect mAppBounds = new Rect();
private Rect mLauncherInsets = new Rect();
@@ -129,6 +139,11 @@ public class TaskViewSimulatorTest {
return this;
}
+ TaskMatrixVerifier withDensityDpi(int densityDpi) {
+ mDensityDpi = densityDpi;
+ return this;
+ }
+
TaskMatrixVerifier withInsets(Rect insets) {
mDisplayInsets.set(insets);
mLauncherInsets.set(insets);
@@ -173,13 +188,17 @@ public class TaskViewSimulatorTest {
new ArrayMap<>();
perDisplayBoundsCache.put(cdi.normalize(), allBounds);
- DisplayController.Info mockInfo = new Info(
- helper.sandboxContext, wmProxy, perDisplayBoundsCache);
+ Configuration configuration = new Configuration();
+ configuration.densityDpi = mDensityDpi;
+ Context configurationContext = helper.sandboxContext.createConfigurationContext(
+ configuration);
+
+ DisplayController.Info info = new Info(
+ configurationContext, wmProxy, perDisplayBoundsCache);
- DisplayController controller =
- DisplayController.INSTANCE.get(helper.sandboxContext);
- controller.close();
- ReflectionHelpers.setField(controller, "mInfo", mockInfo);
+ DisplayController mockController = mock(DisplayController.class);
+ when(mockController.getInfo()).thenReturn(info);
+ helper.sandboxContext.putObject(DisplayController.INSTANCE, mockController);
mDeviceProfile = InvariantDeviceProfile.INSTANCE.get(helper.sandboxContext)
.getBestMatch(mAppBounds.width(), mAppBounds.height(), rotation);
@@ -189,7 +208,7 @@ public class TaskViewSimulatorTest {
FallbackActivityInterface.INSTANCE);
tvs.setDp(mDeviceProfile);
- int launcherRotation = mockInfo.rotation;
+ int launcherRotation = info.rotation;
if (mAppRotation < 0) {
mAppRotation = launcherRotation;
}
diff --git a/quickstep/tests/src/com/android/quickstep/util/unfold/PreemptiveUnfoldTransitionProgressProviderTest.kt b/quickstep/tests/src/com/android/quickstep/util/unfold/PreemptiveUnfoldTransitionProgressProviderTest.kt
index f73be7269d..6a418a4d8b 100644
--- a/quickstep/tests/src/com/android/quickstep/util/unfold/PreemptiveUnfoldTransitionProgressProviderTest.kt
+++ b/quickstep/tests/src/com/android/quickstep/util/unfold/PreemptiveUnfoldTransitionProgressProviderTest.kt
@@ -21,19 +21,17 @@ import android.testing.TestableLooper
import android.testing.TestableLooper.RunWithLooper
import android.util.Log
import androidx.test.filters.SmallTest
-import com.android.launcher3.util.any
-import com.android.launcher3.util.mock
import com.android.systemui.unfold.UnfoldTransitionProgressProvider
import com.android.systemui.unfold.UnfoldTransitionProgressProvider.TransitionProgressListener
import org.junit.After
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
-import org.mockito.Mockito.anyBoolean
-import org.mockito.Mockito.anyFloat
-import org.mockito.Mockito.inOrder
-import org.mockito.Mockito.never
-import org.mockito.Mockito.verify
+import org.mockito.kotlin.any
+import org.mockito.kotlin.inOrder
+import org.mockito.kotlin.mock
+import org.mockito.kotlin.never
+import org.mockito.kotlin.verify
@SmallTest
@RunWith(AndroidTestingRunner::class)
@@ -74,7 +72,7 @@ class PreemptiveUnfoldTransitionProgressProviderTest {
provider.preemptivelyStartTransition(initialProgress = null)
verify(listener).onTransitionStarted()
- verify(listener, never()).onTransitionProgress(anyFloat())
+ verify(listener, never()).onTransitionProgress(any())
}
@Test
@@ -90,7 +88,7 @@ class PreemptiveUnfoldTransitionProgressProviderTest {
provider.preemptivelyStartTransition()
provider.cancelPreemptiveStart()
- with(inOrder(listener)) {
+ inOrder(listener) {
verify(listener).onTransitionStarted()
verify(listener).onTransitionFinished()
}
@@ -111,7 +109,7 @@ class PreemptiveUnfoldTransitionProgressProviderTest {
source.onTransitionStarted()
source.onTransitionFinished()
- with(inOrder(listener)) {
+ inOrder(listener) {
verify(listener).onTransitionStarted()
verify(listener).onTransitionFinished()
}
@@ -152,7 +150,7 @@ class PreemptiveUnfoldTransitionProgressProviderTest {
provider.preemptivelyStartTransition()
source.onTransitionFinished()
- with(inOrder(listener)) {
+ inOrder(listener) {
verify(listener).onTransitionStarted()
verify(listener).onTransitionFinished()
}
@@ -165,7 +163,7 @@ class PreemptiveUnfoldTransitionProgressProviderTest {
testableLooper.moveTimeForward(PREEMPTIVE_UNFOLD_TIMEOUT_MS + 1)
testableLooper.processAllMessages()
- with(inOrder(listener)) {
+ inOrder(listener) {
verify(listener).onTransitionStarted()
verify(listener).onTransitionFinished()
}
@@ -178,7 +176,7 @@ class PreemptiveUnfoldTransitionProgressProviderTest {
testableLooper.moveTimeForward(PREEMPTIVE_UNFOLD_TIMEOUT_MS + 1)
testableLooper.processAllMessages()
- verify(testWtfHandler).onTerribleFailure(any(), any(), anyBoolean())
+ verify(testWtfHandler).onTerribleFailure(any(), any(), any())
}
@Test
@@ -225,7 +223,7 @@ class PreemptiveUnfoldTransitionProgressProviderTest {
source.onTransitionFinished()
- with(inOrder(listener)) {
+ inOrder(listener) {
verify(listener).onTransitionStarted()
verify(listener).onTransitionFinished()
}