Add a test base for AbsSwipeUpHandler and its subclasses
- Added a few basic tests for scenarios that should be contant across subclasses. These tests will not run on their own, they will only run when a subclass' test suite is run.
- Added test suites for LauncherSwipeHandlerV2 and FallbackSwipeHandler
Flag: EXEMPT adding tests
Bug: 353763639
Test: LauncherSwipeHandlerV2Test, FallbackSwipeHandlerTest
Change-Id: Ib44199f5d5281a544b433649d6ed49ae2a65ed70
diff --git a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
index 3d94442..bbf58a2 100644
--- a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
+++ b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
@@ -97,6 +97,7 @@
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.UiThread;
+import androidx.annotation.VisibleForTesting;
import com.android.internal.jank.Cuj;
import com.android.internal.util.LatencyTracker;
@@ -170,10 +171,12 @@
/**
* Handles the navigation gestures when Launcher is the default home activity.
*/
-public abstract class AbsSwipeUpHandler<T extends RecentsViewContainer,
- Q extends RecentsView, S extends BaseState<S>>
- extends SwipeUpAnimationLogic implements OnApplyWindowInsetsListener,
- RecentsAnimationCallbacks.RecentsAnimationListener {
+public abstract class AbsSwipeUpHandler<
+ RECENTS_CONTAINER extends Context & RecentsViewContainer,
+ RECENTS_VIEW extends RecentsView<RECENTS_CONTAINER, STATE>,
+ STATE extends BaseState<STATE>>
+ extends SwipeUpAnimationLogic
+ implements OnApplyWindowInsetsListener, RecentsAnimationCallbacks.RecentsAnimationListener {
private static final String TAG = "AbsSwipeUpHandler";
private static final ArrayList<String> STATE_NAMES = new ArrayList<>();
@@ -181,7 +184,7 @@
// Fraction of the scroll and transform animation in which the current task fades out
private static final float KQS_TASK_FADE_ANIMATION_FRACTION = 0.4f;
- protected final BaseContainerInterface<S, T> mContainerInterface;
+ protected final BaseContainerInterface<STATE, RECENTS_CONTAINER> mContainerInterface;
protected final InputConsumerProxy mInputConsumerProxy;
protected final ActivityInitListener mActivityInitListener;
// Callbacks to be made once the recents animation starts
@@ -192,8 +195,8 @@
protected @Nullable RecentsAnimationController mRecentsAnimationController;
protected @Nullable RecentsAnimationController mDeferredCleanupRecentsAnimationController;
protected RecentsAnimationTargets mRecentsAnimationTargets;
- protected @Nullable T mContainer;
- protected @Nullable Q mRecentsView;
+ protected @Nullable RECENTS_CONTAINER mContainer;
+ protected @Nullable RECENTS_VIEW mRecentsView;
protected Runnable mGestureEndCallback;
protected MultiStateCallback mStateCallback;
protected boolean mCanceled;
@@ -486,11 +489,11 @@
return false;
}
- T createdContainer = (T) mContainerInterface.getCreatedContainer();
+ RECENTS_CONTAINER createdContainer = mContainerInterface.getCreatedContainer();
if (createdContainer != null) {
initTransitionEndpoints(createdContainer.getDeviceProfile());
}
- final T container = (T) mContainerInterface.getCreatedContainer();
+ final RECENTS_CONTAINER container = mContainerInterface.getCreatedContainer();
if (mContainer == container) {
return true;
}
@@ -564,7 +567,7 @@
}
private void onLauncherStart() {
- final T container = (T) mContainerInterface.getCreatedContainer();
+ final RECENTS_CONTAINER container = mContainerInterface.getCreatedContainer();
if (container == null || mContainer != container) {
return;
}
@@ -1097,7 +1100,7 @@
*/
@UiThread
private void notifyGestureStarted() {
- final T curActivity = mContainer;
+ final RECENTS_CONTAINER curActivity = mContainer;
if (curActivity != null) {
// Once the gesture starts, we can no longer transition home through the button, so
// reset the force override of the activity visibility
@@ -1168,7 +1171,8 @@
/**
* Called if the end target has been set and the recents animation is started.
*/
- private void onCalculateEndTarget() {
+ @VisibleForTesting
+ protected void onCalculateEndTarget() {
final GestureEndTarget endTarget = mGestureState.getEndTarget();
switch (endTarget) {
@@ -1181,7 +1185,8 @@
}
}
- private void onSettledOnEndTarget() {
+ @VisibleForTesting
+ protected void onSettledOnEndTarget() {
// Fast-finish the attaching animation if it's still running.
maybeUpdateRecentsAttachedState(false);
final GestureEndTarget endTarget = mGestureState.getEndTarget();
@@ -1417,7 +1422,7 @@
}
}
Interpolator interpolator;
- S state = mContainerInterface.stateFromGestureEndTarget(endTarget);
+ STATE state = mContainerInterface.stateFromGestureEndTarget(endTarget);
if (isKeyboardTaskFocusPending()) {
interpolator = EMPHASIZED;
} else if (state.displayOverviewTasksAsGrid(mDp)) {
@@ -2499,7 +2504,7 @@
}
private void animateSplashScreenExit(
- @NonNull T activity,
+ @NonNull RECENTS_CONTAINER activity,
@NonNull RemoteAnimationTarget[] appearedTaskTargets,
@NonNull RemoteAnimationTarget[] animatingTargets) {
ViewGroup splashView = activity.getDragLayer();
diff --git a/quickstep/src/com/android/quickstep/LauncherSwipeHandlerV2.java b/quickstep/src/com/android/quickstep/LauncherSwipeHandlerV2.java
index e17cdcd..d4b37f1 100644
--- a/quickstep/src/com/android/quickstep/LauncherSwipeHandlerV2.java
+++ b/quickstep/src/com/android/quickstep/LauncherSwipeHandlerV2.java
@@ -62,8 +62,8 @@
/**
* Temporary class to allow easier refactoring
*/
-public class LauncherSwipeHandlerV2 extends
- AbsSwipeUpHandler<QuickstepLauncher, RecentsView, LauncherState> {
+public class LauncherSwipeHandlerV2 extends AbsSwipeUpHandler<
+ QuickstepLauncher, RecentsView<QuickstepLauncher, LauncherState>, LauncherState> {
public LauncherSwipeHandlerV2(Context context, RecentsAnimationDeviceState deviceState,
TaskAnimationManager taskAnimationManager, GestureState gestureState, long touchTimeMs,
diff --git a/quickstep/src/com/android/quickstep/OverviewCommandHelper.kt b/quickstep/src/com/android/quickstep/OverviewCommandHelper.kt
index f6b9e4e..d70f0d7 100644
--- a/quickstep/src/com/android/quickstep/OverviewCommandHelper.kt
+++ b/quickstep/src/com/android/quickstep/OverviewCommandHelper.kt
@@ -347,7 +347,7 @@
taskAnimationManager.notifyRecentsAnimationState(recentAnimListener)
} else {
val intent =
- Intent(interactionHandler.launchIntent)
+ Intent(interactionHandler.getLaunchIntent())
.putExtra(ActiveGestureLog.INTENT_EXTRA_LOG_TRACE_ID, gestureState.gestureId)
command.setAnimationCallbacks(
taskAnimationManager.startRecentsAnimation(gestureState, intent, interactionHandler)
diff --git a/quickstep/tests/multivalentTests/src/com/android/quickstep/AbsSwipeUpHandlerTestCase.java b/quickstep/tests/multivalentTests/src/com/android/quickstep/AbsSwipeUpHandlerTestCase.java
new file mode 100644
index 0000000..2a0aa4c
--- /dev/null
+++ b/quickstep/tests/multivalentTests/src/com/android/quickstep/AbsSwipeUpHandlerTestCase.java
@@ -0,0 +1,276 @@
+/*
+ * Copyright (C) 2024 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.anyBoolean;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.ActivityManager;
+import android.content.Context;
+import android.content.Intent;
+import android.content.res.Configuration;
+import android.graphics.PointF;
+import android.graphics.Rect;
+import android.os.Bundle;
+import android.os.SystemClock;
+import android.view.RemoteAnimationTarget;
+import android.view.SurfaceControl;
+import android.view.ViewTreeObserver;
+
+import androidx.annotation.NonNull;
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import com.android.launcher3.DeviceProfile;
+import com.android.launcher3.LauncherRootView;
+import com.android.launcher3.dragndrop.DragLayer;
+import com.android.launcher3.statemanager.BaseState;
+import com.android.launcher3.statemanager.StatefulActivity;
+import com.android.launcher3.util.SystemUiController;
+import com.android.quickstep.util.ActivityInitListener;
+import com.android.quickstep.views.RecentsView;
+import com.android.quickstep.views.RecentsViewContainer;
+import com.android.systemui.shared.system.InputConsumerController;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+
+import java.util.Collections;
+import java.util.HashMap;
+
+public abstract class AbsSwipeUpHandlerTestCase<
+ RECENTS_CONTAINER extends Context & RecentsViewContainer,
+ STATE extends BaseState<STATE>,
+ RECENTS_VIEW extends RecentsView<RECENTS_CONTAINER, STATE>,
+ ACTIVITY_TYPE extends StatefulActivity<STATE> & RecentsViewContainer,
+ ACTIVITY_INTERFACE extends BaseActivityInterface<STATE, ACTIVITY_TYPE>,
+ SWIPE_HANDLER extends AbsSwipeUpHandler<RECENTS_CONTAINER, RECENTS_VIEW, STATE>> {
+
+ protected final Context mContext =
+ InstrumentationRegistry.getInstrumentation().getTargetContext();
+ protected final TaskAnimationManager mTaskAnimationManager = new TaskAnimationManager(mContext);
+ protected final RecentsAnimationDeviceState mRecentsAnimationDeviceState =
+ new RecentsAnimationDeviceState(mContext, true);
+ protected final InputConsumerController mInputConsumerController =
+ InputConsumerController.getRecentsAnimationInputConsumer();
+ protected final ActivityManager.RunningTaskInfo mRunningTaskInfo =
+ new ActivityManager.RunningTaskInfo();
+ protected final TopTaskTracker.CachedTaskInfo mCachedTaskInfo =
+ new TopTaskTracker.CachedTaskInfo(Collections.singletonList(mRunningTaskInfo));
+ protected final RemoteAnimationTarget mRemoteAnimationTarget = new RemoteAnimationTarget(
+ /* taskId= */ 0,
+ /* mode= */ RemoteAnimationTarget.MODE_CLOSING,
+ /* leash= */ new SurfaceControl(),
+ /* isTranslucent= */ false,
+ /* clipRect= */ null,
+ /* contentInsets= */ null,
+ /* prefixOrderIndex= */ 0,
+ /* position= */ null,
+ /* localBounds= */ null,
+ /* screenSpaceBounds= */ null,
+ new Configuration().windowConfiguration,
+ /* isNotInRecents= */ false,
+ /* startLeash= */ null,
+ /* startBounds= */ null,
+ /* taskInfo= */ mRunningTaskInfo,
+ /* allowEnterPip= */ false);
+ protected final RecentsAnimationTargets mRecentsAnimationTargets = new RecentsAnimationTargets(
+ new RemoteAnimationTarget[] {mRemoteAnimationTarget},
+ new RemoteAnimationTarget[] {mRemoteAnimationTarget},
+ new RemoteAnimationTarget[] {mRemoteAnimationTarget},
+ /* homeContentInsets= */ new Rect(),
+ /* minimizedHomeBounds= */ null,
+ new Bundle());
+
+ @Mock protected ACTIVITY_INTERFACE mActivityInterface;
+ @Mock protected ActivityInitListener<?> mActivityInitListener;
+ @Mock protected RecentsAnimationController mRecentsAnimationController;
+ @Mock protected STATE mState;
+ @Mock protected ViewTreeObserver mViewTreeObserver;
+ @Mock protected DragLayer mDragLayer;
+ @Mock protected LauncherRootView mRootView;
+ @Mock protected SystemUiController mSystemUiController;
+ @Mock protected GestureState mGestureState;
+
+ @Rule
+ public final MockitoRule mMockitoRule = MockitoJUnit.rule();
+
+ @Before
+ public void setUpRunningTaskInfo() {
+ mRunningTaskInfo.baseIntent = new Intent(Intent.ACTION_MAIN)
+ .addCategory(Intent.CATEGORY_HOME)
+ .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ }
+
+ @Before
+ public void setUpGestureState() {
+ when(mGestureState.getRunningTask()).thenReturn(mCachedTaskInfo);
+ when(mGestureState.getLastAppearedTaskIds()).thenReturn(new int[0]);
+ when(mGestureState.getLastStartedTaskIds()).thenReturn(new int[1]);
+ when(mGestureState.getHomeIntent()).thenReturn(new Intent(Intent.ACTION_MAIN)
+ .addCategory(Intent.CATEGORY_HOME)
+ .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
+ doReturn(mActivityInterface).when(mGestureState).getContainerInterface();
+ }
+
+ @Before
+ public void setUpRecentsView() {
+ RECENTS_VIEW recentsView = getRecentsView();
+ when(recentsView.getViewTreeObserver()).thenReturn(mViewTreeObserver);
+ doAnswer(answer -> {
+ runOnMainSync(() -> answer.<Runnable>getArgument(0).run());
+ return this;
+ }).when(recentsView).runOnPageScrollsInitialized(any());
+ }
+
+ @Before
+ public void setUpRecentsContainer() {
+ RecentsViewContainer recentsContainer = getRecentsContainer();
+ RECENTS_VIEW recentsView = getRecentsView();
+
+ when(recentsContainer.getDeviceProfile()).thenReturn(new DeviceProfile());
+ when(recentsContainer.getOverviewPanel()).thenReturn(recentsView);
+ when(recentsContainer.getDragLayer()).thenReturn(mDragLayer);
+ when(recentsContainer.getRootView()).thenReturn(mRootView);
+ when(recentsContainer.getSystemUiController()).thenReturn(mSystemUiController);
+ when(mActivityInterface.createActivityInitListener(any()))
+ .thenReturn(mActivityInitListener);
+ doReturn(recentsContainer).when(mActivityInterface).getCreatedContainer();
+ doAnswer(answer -> {
+ answer.<Runnable>getArgument(0).run();
+ return this;
+ }).when(recentsContainer).runOnBindToTouchInteractionService(any());
+ }
+
+ @Test
+ public void testInitWhenReady_registersActivityInitListener() {
+ String reasonString = "because i said so";
+
+ createSwipeHandler().initWhenReady(reasonString);
+ verify(mActivityInitListener).register(eq(reasonString));
+ }
+
+ @Test
+ public void testOnRecentsAnimationCanceled_unregistersActivityInitListener() {
+ createSwipeHandler()
+ .onRecentsAnimationCanceled(new HashMap<>());
+
+ runOnMainSync(() -> verify(mActivityInitListener)
+ .unregister(eq("AbsSwipeUpHandler.onRecentsAnimationCanceled")));
+ }
+
+ @Test
+ public void testOnConsumerAboutToBeSwitched_unregistersActivityInitListener() {
+ createSwipeHandler().onConsumerAboutToBeSwitched();
+
+ runOnMainSync(() -> verify(mActivityInitListener)
+ .unregister("AbsSwipeUpHandler.invalidateHandler"));
+ }
+
+ @Test
+ public void testOnConsumerAboutToBeSwitched_midQuickSwitch_unregistersActivityInitListener() {
+ createSwipeUpHandlerForGesture(GestureState.GestureEndTarget.NEW_TASK)
+ .onConsumerAboutToBeSwitched();
+
+ runOnMainSync(() -> verify(mActivityInitListener)
+ .unregister(eq("AbsSwipeUpHandler.cancelCurrentAnimation")));
+ }
+
+ @Test
+ public void testStartNewTask_finishesRecentsAnimationController() {
+ SWIPE_HANDLER absSwipeUpHandler = createSwipeHandler();
+
+ onRecentsAnimationStart(absSwipeUpHandler);
+
+ runOnMainSync(() -> {
+ absSwipeUpHandler.startNewTask(unused -> {});
+ verify(mRecentsAnimationController).finish(anyBoolean(), any());
+ });
+ }
+
+ @Test
+ public void testHomeGesture_finishesRecentsAnimationController() {
+ createSwipeUpHandlerForGesture(GestureState.GestureEndTarget.HOME);
+
+ runOnMainSync(() -> {
+ verify(mRecentsAnimationController).detachNavigationBarFromApp(true);
+ verify(mRecentsAnimationController).finish(anyBoolean(), any(), anyBoolean());
+ });
+ }
+
+ private SWIPE_HANDLER createSwipeUpHandlerForGesture(GestureState.GestureEndTarget endTarget) {
+ boolean isQuickSwitch = endTarget == GestureState.GestureEndTarget.NEW_TASK;
+
+ doReturn(mState).when(mActivityInterface).stateFromGestureEndTarget(any());
+
+ SWIPE_HANDLER swipeHandler = createSwipeHandler(SystemClock.uptimeMillis(), isQuickSwitch);
+
+ swipeHandler.onActivityInit(/* alreadyOnHome= */ false);
+ swipeHandler.onGestureStarted(isQuickSwitch);
+ onRecentsAnimationStart(swipeHandler);
+
+ when(mGestureState.getRunningTaskIds(anyBoolean())).thenReturn(new int[0]);
+ runOnMainSync(swipeHandler::switchToScreenshot);
+
+ when(mGestureState.getEndTarget()).thenReturn(endTarget);
+ when(mGestureState.isRecentsAnimationRunning()).thenReturn(isQuickSwitch);
+ float xVelocityPxPerMs = isQuickSwitch ? 100 : 0;
+ float yVelocityPxPerMs = isQuickSwitch ? 0 : -100;
+ swipeHandler.onGestureEnded(
+ yVelocityPxPerMs, new PointF(xVelocityPxPerMs, yVelocityPxPerMs));
+ swipeHandler.onCalculateEndTarget();
+ runOnMainSync(swipeHandler::onSettledOnEndTarget);
+
+ return swipeHandler;
+ }
+
+ private void onRecentsAnimationStart(SWIPE_HANDLER absSwipeUpHandler) {
+ when(mActivityInterface.getOverviewWindowBounds(any(), any())).thenReturn(new Rect());
+ doNothing().when(mActivityInterface).setOnDeferredActivityLaunchCallback(any());
+
+ runOnMainSync(() -> absSwipeUpHandler.onRecentsAnimationStart(
+ mRecentsAnimationController, mRecentsAnimationTargets));
+ }
+
+ private static void runOnMainSync(Runnable runnable) {
+ InstrumentationRegistry.getInstrumentation().runOnMainSync(runnable);
+ }
+
+ @NonNull
+ private SWIPE_HANDLER createSwipeHandler() {
+ return createSwipeHandler(SystemClock.uptimeMillis(), false);
+ }
+
+ @NonNull
+ protected abstract SWIPE_HANDLER createSwipeHandler(
+ long touchTimeMs, boolean continuingLastGesture);
+
+ @NonNull
+ protected abstract RecentsViewContainer getRecentsContainer();
+
+ @NonNull
+ protected abstract RECENTS_VIEW getRecentsView();
+}
diff --git a/quickstep/tests/multivalentTests/src/com/android/quickstep/FallbackSwipeHandlerTestCase.java b/quickstep/tests/multivalentTests/src/com/android/quickstep/FallbackSwipeHandlerTestCase.java
new file mode 100644
index 0000000..dd0b4b3
--- /dev/null
+++ b/quickstep/tests/multivalentTests/src/com/android/quickstep/FallbackSwipeHandlerTestCase.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2024 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 androidx.test.filters.SmallTest;
+
+import com.android.launcher3.util.LauncherMultivalentJUnit;
+import com.android.quickstep.fallback.FallbackRecentsView;
+import com.android.quickstep.fallback.RecentsState;
+
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+
+@SmallTest
+@RunWith(LauncherMultivalentJUnit.class)
+public class FallbackSwipeHandlerTestCase extends AbsSwipeUpHandlerTestCase<
+ RecentsActivity,
+ RecentsState,
+ FallbackRecentsView,
+ RecentsActivity,
+ FallbackActivityInterface,
+ FallbackSwipeHandler> {
+
+ @Mock private RecentsActivity mRecentsActivity;
+ @Mock private FallbackRecentsView mRecentsView;
+
+
+ @Override
+ protected FallbackSwipeHandler createSwipeHandler(
+ long touchTimeMs, boolean continuingLastGesture) {
+ return new FallbackSwipeHandler(
+ mContext,
+ mRecentsAnimationDeviceState,
+ mTaskAnimationManager,
+ mGestureState,
+ touchTimeMs,
+ continuingLastGesture,
+ mInputConsumerController);
+ }
+
+ @Override
+ protected RecentsActivity getRecentsContainer() {
+ return mRecentsActivity;
+ }
+
+ @Override
+ protected FallbackRecentsView getRecentsView() {
+ return mRecentsView;
+ }
+}
diff --git a/quickstep/tests/multivalentTests/src/com/android/quickstep/LauncherSwipeHandlerV2TestCase.java b/quickstep/tests/multivalentTests/src/com/android/quickstep/LauncherSwipeHandlerV2TestCase.java
new file mode 100644
index 0000000..653dc01
--- /dev/null
+++ b/quickstep/tests/multivalentTests/src/com/android/quickstep/LauncherSwipeHandlerV2TestCase.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2024 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.Mockito.doReturn;
+import static org.mockito.Mockito.when;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.launcher3.Hotseat;
+import com.android.launcher3.LauncherState;
+import com.android.launcher3.Workspace;
+import com.android.launcher3.WorkspaceStateTransitionAnimation;
+import com.android.launcher3.statemanager.StateManager;
+import com.android.launcher3.statemanager.StateManager.AtomicAnimationFactory;
+import com.android.launcher3.uioverrides.QuickstepLauncher;
+import com.android.launcher3.util.LauncherMultivalentJUnit;
+import com.android.quickstep.views.RecentsView;
+
+import org.junit.Before;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+
+@SmallTest
+@RunWith(LauncherMultivalentJUnit.class)
+public class LauncherSwipeHandlerV2TestCase extends AbsSwipeUpHandlerTestCase<
+ QuickstepLauncher,
+ LauncherState,
+ RecentsView<QuickstepLauncher, LauncherState>,
+ QuickstepLauncher,
+ LauncherActivityInterface,
+ LauncherSwipeHandlerV2> {
+
+ @Mock private QuickstepLauncher mQuickstepLauncher;
+ @Mock private RecentsView<QuickstepLauncher, LauncherState> mRecentsView;
+ @Mock private Workspace<?> mWorkspace;
+ @Mock private Hotseat mHotseat;
+ @Mock private WorkspaceStateTransitionAnimation mTransitionAnimation;
+
+ @Before
+ public void setUpQuickStepLauncher() {
+ when(mQuickstepLauncher.createAtomicAnimationFactory())
+ .thenReturn(new AtomicAnimationFactory<>(0));
+ when(mQuickstepLauncher.getHotseat()).thenReturn(mHotseat);
+ doReturn(mWorkspace).when(mQuickstepLauncher).getWorkspace();
+ doReturn(new StateManager(mQuickstepLauncher, LauncherState.NORMAL))
+ .when(mQuickstepLauncher).getStateManager();
+
+ }
+
+ @Before
+ public void setUpWorkspace() {
+ when(mWorkspace.getStateTransitionAnimation()).thenReturn(mTransitionAnimation);
+ }
+
+ @Override
+ protected LauncherSwipeHandlerV2 createSwipeHandler(
+ long touchTimeMs, boolean continuingLastGesture) {
+ return new LauncherSwipeHandlerV2(
+ mContext,
+ mRecentsAnimationDeviceState,
+ mTaskAnimationManager,
+ mGestureState,
+ touchTimeMs,
+ continuingLastGesture,
+ mInputConsumerController);
+ }
+
+ @Override
+ protected QuickstepLauncher getRecentsContainer() {
+ return mQuickstepLauncher;
+ }
+
+ @Override
+ protected RecentsView<QuickstepLauncher, LauncherState> getRecentsView() {
+ return mRecentsView;
+ }
+}
diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java
index 5cbf6fb..8ae6d73 100644
--- a/src/com/android/launcher3/DeviceProfile.java
+++ b/src/com/android/launcher3/DeviceProfile.java
@@ -316,6 +316,74 @@
// DragController
public int flingToDeleteThresholdVelocity;
+ /** Used only as an alternative to mocking when null values cannot be used. */
+ @VisibleForTesting
+ public DeviceProfile() {
+ inv = null;
+ mInfo = null;
+ mMetrics = null;
+ mIconSizeSteps = null;
+ isTablet = false;
+ isPhone = false;
+ transposeLayoutWithOrientation = false;
+ isMultiDisplay = false;
+ isTwoPanels = false;
+ isPredictiveBackSwipe = false;
+ isQsbInline = false;
+ isLandscape = false;
+ isMultiWindowMode = false;
+ isGestureMode = false;
+ isLeftRightSplit = false;
+ windowX = 0;
+ windowY = 0;
+ widthPx = 0;
+ heightPx = 0;
+ availableWidthPx = 0;
+ availableHeightPx = 0;
+ rotationHint = 0;
+ aspectRatio = 1;
+ mIsScalableGrid = false;
+ mTypeIndex = 0;
+ mIsResponsiveGrid = false;
+ desiredWorkspaceHorizontalMarginOriginalPx = 0;
+ edgeMarginPx = 0;
+ workspaceContentScale = 0;
+ workspaceSpringLoadedMinNextPageVisiblePx = 0;
+ extraSpace = 0;
+ workspacePageIndicatorHeight = 0;
+ mWorkspacePageIndicatorOverlapWorkspace = 0;
+ numFolderRows = 0;
+ numFolderColumns = 0;
+ folderLabelTextScale = 0;
+ areNavButtonsInline = false;
+ mHotseatBarEdgePaddingPx = 0;
+ mHotseatBarWorkspaceSpacePx = 0;
+ hotseatQsbWidth = 0;
+ hotseatQsbHeight = 0;
+ hotseatQsbVisualHeight = 0;
+ hotseatQsbShadowHeight = 0;
+ hotseatBorderSpace = 0;
+ mMinHotseatIconSpacePx = 0;
+ mMinHotseatQsbWidthPx = 0;
+ mMaxHotseatIconSpacePx = 0;
+ inlineNavButtonsEndSpacingPx = 0;
+ mBubbleBarSpaceThresholdPx = 0;
+ numShownAllAppsColumns = 0;
+ overviewActionsHeight = 0;
+ overviewActionsTopMarginPx = 0;
+ overviewActionsButtonSpacing = 0;
+ mViewScaleProvider = null;
+ mDotRendererWorkSpace = null;
+ mDotRendererAllApps = null;
+ taskbarHeight = 0;
+ stashedTaskbarHeight = 0;
+ taskbarBottomMargin = 0;
+ taskbarIconSize = 0;
+ mTransientTaskbarClaimedSpace = 0;
+ startAlignTaskbar = false;
+ isTransientTaskbar = false;
+ }
+
/** TODO: Once we fully migrate to staged split, remove "isMultiWindowMode" */
DeviceProfile(Context context, InvariantDeviceProfile inv, Info info, WindowBounds windowBounds,
SparseArray<DotRenderer> dotRendererCache, boolean isMultiWindowMode,