Merge "Let `getOffsetToDismissedTask` not rely on `taskCount`" into main
diff --git a/aconfig/launcher.aconfig b/aconfig/launcher.aconfig
index f0a9cba..c3fb150 100644
--- a/aconfig/launcher.aconfig
+++ b/aconfig/launcher.aconfig
@@ -554,3 +554,13 @@
     purpose: PURPOSE_BUGFIX
   }
 }
+
+flag {
+  name: "predictive_back_to_home_blur"
+  namespace: "launcher"
+  description: "Adds blur for predictive back-to-home"
+  bug: "342178850"
+  metadata {
+    purpose: PURPOSE_BUGFIX
+  }
+}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
index 107facf..7b326c1 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
@@ -1317,25 +1317,9 @@
         } else if (tag instanceof TaskItemInfo info) {
             RemoteTransition remoteTransition = canUnminimizeDesktopTask(info.getTaskId())
                     ? createUnminimizeRemoteTransition() : null;
-
-            if (areDesktopTasksVisible() && recents != null) {
-                TaskView taskView = recents.getTaskViewByTaskId(info.getTaskId());
-                if (taskView == null) return;
-                RunnableList runnableList = taskView.launchWithAnimation();
-                if (runnableList != null) {
-                    runnableList.add(() ->
-                            // wrapped it in runnable here since we need the post for DW to be
-                            // ready. if we don't other DW will be gone and only the launched task
-                            // will show.
-                            UI_HELPER_EXECUTOR.execute(() ->
-                                    SystemUiProxy.INSTANCE.get(this).showDesktopApp(
-                                            info.getTaskId(), remoteTransition)));
-                }
-            } else {
-                UI_HELPER_EXECUTOR.execute(() ->
-                        SystemUiProxy.INSTANCE.get(this).showDesktopApp(
-                                info.getTaskId(), remoteTransition));
-            }
+            UI_HELPER_EXECUTOR.execute(() ->
+                    SystemUiProxy.INSTANCE.get(this).showDesktopApp(
+                            info.getTaskId(), remoteTransition));
             mControllers.taskbarStashController.updateAndAnimateTransientTaskbar(
                     /* stash= */ true);
         } else if (tag instanceof WorkspaceItemInfo) {
@@ -1579,17 +1563,7 @@
                                                 .launchAppPair((AppPairIcon) launchingIconView,
                                                         -1 /*cuj*/)));
                     } else {
-                        if (areDesktopTasksVisible()) {
-                            RunnableList runnableList = recents.launchDesktopTaskView();
-                            // Wrapping it in runnable so we post after DW is ready for the app
-                            // launch.
-                            if (runnableList != null) {
-                                runnableList.add(() -> UI_HELPER_EXECUTOR.execute(
-                                        () -> startItemInfoActivity(itemInfos.get(0), foundTask)));
-                            }
-                        } else {
-                            startItemInfoActivity(itemInfos.get(0), foundTask);
-                        }
+                        startItemInfoActivity(itemInfos.get(0), foundTask);
                     }
                 }
         );
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarPopupController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarPopupController.java
index abf35a2..772d45d 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarPopupController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarPopupController.java
@@ -17,6 +17,7 @@
 
 import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_ALL_APPS;
 import static com.android.launcher3.model.data.AppInfo.COMPONENT_KEY_COMPARATOR;
+import static com.android.launcher3.popup.SystemShortcut.PIN_UNPIN_ITEM;
 import static com.android.launcher3.util.SplitConfigurationOptions.getLogEventForPosition;
 
 import android.content.Intent;
@@ -195,6 +196,9 @@
         // append split options to APP_INFO shortcut if not in Desktop Windowing mode, the order
         // here will reflect in the popup
         ArrayList<SystemShortcut.Factory> shortcuts = new ArrayList<>();
+        if (Flags.enablePinningAppWithContextMenu()) {
+            shortcuts.add(PIN_UNPIN_ITEM);
+        }
         shortcuts.add(APP_INFO);
         if (!mControllers.taskbarDesktopModeController.getAreDesktopTasksVisible()) {
             shortcuts.addAll(mControllers.uiController.getSplitMenuOptions().toList());
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarViewController.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarViewController.java
index dd1b0ca..d00959e 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarViewController.java
@@ -183,6 +183,11 @@
         if (!Flags.enableOptionalBubbleOverflow()) {
             showOverflow(true);
         }
+        if (!mBubbleStashController.isTransientTaskBar()) {
+            // TODO(b/380274085) for transient taskbar mode, the click is also handled by the input
+            //  consumer. This check can be removed once b/380274085 is fixed.
+            mBarView.setOnClickListener(v -> setExpanded(!mBarView.isExpanded()));
+        }
         mBarView.addOnLayoutChangeListener(
                 (v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> {
                     mTaskbarInsetsController.onTaskbarOrBubblebarWindowHeightOrInsetsChanged();
@@ -650,10 +655,12 @@
     }
 
     private void updateVisibilityForStateChange() {
-        if (!mHiddenForSysui && !mHiddenForNoBubbles && !mHiddenForStashed) {
-            mBarView.setVisibility(VISIBLE);
-        } else {
+        boolean hiddenForStashedAndNotAnimating =
+                mHiddenForStashed && !mBubbleBarViewAnimator.isAnimating();
+        if (mHiddenForSysui || mHiddenForNoBubbles || hiddenForStashedAndNotAnimating) {
             mBarView.setVisibility(INVISIBLE);
+        } else {
+            mBarView.setVisibility(VISIBLE);
         }
     }
 
@@ -1215,6 +1222,7 @@
         pw.println("Bubble bar view controller state:");
         pw.println("  mHiddenForSysui: " + mHiddenForSysui);
         pw.println("  mHiddenForNoBubbles: " + mHiddenForNoBubbles);
+        pw.println("  mHiddenForStashed: " + mHiddenForStashed);
         pw.println("  mShouldShowEducation: " + mShouldShowEducation);
         pw.println("  mBubbleBarTranslationY.value: " + mBubbleBarTranslationY.value);
         pw.println("  mBubbleBarSwipeUpTranslationY: " + mBubbleBarSwipeUpTranslationY);
diff --git a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
index 3fd9970..e17771c 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
@@ -48,6 +48,7 @@
 import static com.android.launcher3.popup.SystemShortcut.BUBBLE_SHORTCUT;
 import static com.android.launcher3.popup.SystemShortcut.DONT_SUGGEST_APP;
 import static com.android.launcher3.popup.SystemShortcut.INSTALL;
+import static com.android.launcher3.popup.SystemShortcut.PIN_UNPIN_ITEM;
 import static com.android.launcher3.popup.SystemShortcut.PRIVATE_PROFILE_INSTALL;
 import static com.android.launcher3.popup.SystemShortcut.UNINSTALL_APP;
 import static com.android.launcher3.popup.SystemShortcut.WIDGETS;
@@ -457,6 +458,10 @@
         // Order matters as it affects order of appearance in popup container
         List<SystemShortcut.Factory> shortcuts = new ArrayList(Arrays.asList(
                 APP_INFO, WellbeingModel.SHORTCUT_FACTORY, mHotseatPredictionController));
+
+        if (Flags.enablePinningAppWithContextMenu()) {
+            shortcuts.add(0, PIN_UNPIN_ITEM);
+        }
         shortcuts.addAll(getSplitShortcuts());
         shortcuts.add(WIDGETS);
         shortcuts.add(INSTALL);
diff --git a/quickstep/src/com/android/quickstep/LauncherBackAnimationController.java b/quickstep/src/com/android/quickstep/LauncherBackAnimationController.java
index 69f28fa..c1e018d 100644
--- a/quickstep/src/com/android/quickstep/LauncherBackAnimationController.java
+++ b/quickstep/src/com/android/quickstep/LauncherBackAnimationController.java
@@ -16,6 +16,7 @@
 
 package com.android.quickstep;
 
+import static android.util.MathUtils.lerp;
 import static android.view.RemoteAnimationTarget.MODE_CLOSING;
 import static android.view.RemoteAnimationTarget.MODE_OPENING;
 import static android.view.WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS;
@@ -96,6 +97,8 @@
             Flags.predictiveBackToHomePolish() ? 0.75f : 0.85f;
     private static final float MAX_SCRIM_ALPHA_DARK = 0.8f;
     private static final float MAX_SCRIM_ALPHA_LIGHT = 0.2f;
+    private static final int MAX_BLUR_RADIUS = 20;
+    private static final int MIN_BLUR_RADIUS_PRE_COMMIT = 10;
 
     private final QuickstepTransitionManager mQuickstepTransitionManager;
     private final Matrix mTransformMatrix = new Matrix();
@@ -125,6 +128,7 @@
     private ValueAnimator mScrimAlphaAnimator;
     private float mScrimAlpha;
     private boolean mOverridingStatusBarFlags;
+    private int mLastBlurRadius = 0;
 
     private final ComponentCallbacks mComponentCallbacks = new ComponentCallbacks() {
         @Override
@@ -324,6 +328,9 @@
                 && !mLauncher.isInState(LauncherState.ALL_APPS)) {
             Animations.cancelOngoingAnimation(mLauncher.getWorkspace());
             Animations.cancelOngoingAnimation(mLauncher.getHotseat());
+            if (Flags.predictiveBackToHomeBlur()) {
+                mLauncher.getDepthController().pauseBlursOnWindows(true);
+            }
             mLauncher.getDepthController().stateDepth.setValue(
                     LauncherState.BACKGROUND_APP.getDepth(mLauncher));
             setLauncherScale(ScalingWorkspaceRevealAnim.MIN_SIZE);
@@ -367,6 +374,7 @@
         final float[] colorComponents = new float[] { 0f, 0f, 0f };
         mScrimAlpha = (isDarkTheme)
                 ? MAX_SCRIM_ALPHA_DARK : MAX_SCRIM_ALPHA_LIGHT;
+        setBlur(MAX_BLUR_RADIUS);
         mTransaction
                 .setColor(mScrimLayer, colorComponents)
                 .setAlpha(mScrimLayer, mScrimAlpha)
@@ -393,6 +401,9 @@
         if (mScrimLayer == null) {
             // Scrim hasn't been attached yet. Let's attach it.
             addScrimLayer();
+        } else {
+            mLastBlurRadius = (int) lerp(MAX_BLUR_RADIUS, MIN_BLUR_RADIUS_PRE_COMMIT, progress);
+            setBlur(mLastBlurRadius);
         }
         float screenWidth = mStartRect.width();
         float screenHeight = mStartRect.height();
@@ -424,6 +435,12 @@
         customizeStatusBarAppearance(top > mStatusBarHeight / 2);
     }
 
+    private void setBlur(int blurRadius) {
+        if (Flags.predictiveBackToHomeBlur()) {
+            mTransaction.setBackgroundBlurRadius(mScrimLayer, blurRadius);
+        }
+    }
+
     /** Transform the target window to match the target rect. */
     private void applyTransform(RectF targetRect, float cornerRadius) {
         final float scale = targetRect.width() / mStartRect.width();
@@ -524,7 +541,11 @@
         if (Flags.predictiveBackToHomePolish() && !mLauncher.getWorkspace().isOverlayShown()
                 && !mLauncher.isInState(LauncherState.ALL_APPS)) {
             setLauncherScale(ScalingWorkspaceRevealAnim.MAX_SIZE);
+            if (Flags.predictiveBackToHomeBlur()) {
+                mLauncher.getDepthController().pauseBlursOnWindows(false);
+            }
         }
+        mLastBlurRadius = 0;
     }
 
     private void startTransitionAnimations(BackAnimState backAnim) {
@@ -538,6 +559,7 @@
             float value = (Float) animation.getAnimatedValue();
             if (mScrimLayer != null && mScrimLayer.isValid()) {
                 mTransaction.setAlpha(mScrimLayer, value * mScrimAlpha);
+                setBlur((int) lerp(mLastBlurRadius, 0, 1f - value));
                 applyTransaction();
             }
         });
diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java
index a413128..499f50e 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsView.java
@@ -1572,19 +1572,6 @@
     }
 
     /**
-     * Launch DesktopTaskView if found.
-     * @return provides runnable list to attach runnable at end of Desktop Mode launch
-     */
-    public RunnableList launchDesktopTaskView() {
-        for (TaskView taskView : getTaskViews()) {
-            if (taskView instanceof DesktopTaskView) {
-                return taskView.launchWithAnimation();
-            }
-        }
-        return null;
-    }
-
-    /**
      * Returns a {@link TaskView} that has taskId matching {@code taskId} or null if no match.
      */
     @Nullable
diff --git a/res/values/strings.xml b/res/values/strings.xml
index cdfbefe..2fc039e 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -212,6 +212,7 @@
     <string name="all_apps_button_personal_label">Personal apps list</string>
     <string name="all_apps_button_work_label">Work apps list</string>
 
+    <!-- System shortcuts -->
     <!-- Label for remove drop target (from the homescreen only).
          May appear next to uninstall_drop_target_label [CHAR_LIMIT=20] -->
     <string name="remove_drop_target_label">Remove</string>
@@ -232,6 +233,8 @@
     <string name="pin_prediction">Pin Prediction</string>
     <!-- Label for bubbling a launcher item. [CHAR_LIMIT=20] -->
     <string name="bubble">Bubble</string>
+    <!-- Label for pinning an item to the taskbar. [CHAR_LIMIT=20] -->
+    <string name="pin_to_taskbar">Pin to taskbar</string>
 
     <!-- Permissions: -->
     <skip />
diff --git a/src/com/android/launcher3/InvariantDeviceProfile.java b/src/com/android/launcher3/InvariantDeviceProfile.java
index 0104b6c..28293d1 100644
--- a/src/com/android/launcher3/InvariantDeviceProfile.java
+++ b/src/com/android/launcher3/InvariantDeviceProfile.java
@@ -246,10 +246,6 @@
     @TargetApi(23)
     private InvariantDeviceProfile(Context context) {
         String gridName = getCurrentGridName(context);
-        FileLog.d(TAG, "New InvariantDeviceProfile, before initGrid(): "
-                + "gridName:" + gridName
-                + ", LauncherPrefs GRID_NAME:" + LauncherPrefs.get(context).get(GRID_NAME)
-                + ", LauncherPrefs DB_FILE:" + LauncherPrefs.get(context).get(DB_FILE));
         initGrid(context, gridName);
         DisplayController.INSTANCE.get(context).setPriorityListener(
                 (displayContext, info, flags) -> {
@@ -358,6 +354,11 @@
     }
 
     private String initGrid(Context context, String gridName) {
+        FileLog.d(TAG, "Before initGrid:"
+                + "gridName:" + gridName
+                + ", dbFile:" + dbFile
+                + ", LauncherPrefs GRID_NAME:" + LauncherPrefs.get(context).get(GRID_NAME)
+                + ", LauncherPrefs DB_FILE:" + LauncherPrefs.get(context).get(DB_FILE));
         Info displayInfo = DisplayController.INSTANCE.get(context).getInfo();
         List<DisplayOption> allOptions = getPredefinedDeviceProfiles(
                 context,
@@ -383,8 +384,9 @@
         }
 
         initGrid(context, displayInfo, displayOption);
-        FileLog.d(TAG, "initGrid: "
+        FileLog.d(TAG, "After initGrid:"
                 + "gridName:" + gridName
+                + ", dbFile:" + dbFile
                 + ", LauncherPrefs GRID_NAME:" + LauncherPrefs.get(context).get(GRID_NAME)
                 + ", LauncherPrefs DB_FILE:" + LauncherPrefs.get(context).get(DB_FILE));
         return displayOption.grid.name;
@@ -402,7 +404,7 @@
      */
     @Deprecated
     public void reset(Context context) {
-        initGrid(context, getDefaultGridName(context));
+        initGrid(context, getCurrentGridName(context));
     }
 
     @VisibleForTesting
diff --git a/src/com/android/launcher3/allapps/AllAppsTransitionController.java b/src/com/android/launcher3/allapps/AllAppsTransitionController.java
index 8554de5..4cc31d2 100644
--- a/src/com/android/launcher3/allapps/AllAppsTransitionController.java
+++ b/src/com/android/launcher3/allapps/AllAppsTransitionController.java
@@ -34,6 +34,7 @@
 import static com.android.launcher3.util.SystemUiController.UI_STATE_ALL_APPS;
 
 import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
 import android.animation.ObjectAnimator;
 import android.util.FloatProperty;
 import android.view.HapticFeedbackConstants;
@@ -365,6 +366,12 @@
         Interpolator verticalProgressInterpolator = config.getInterpolator(ANIM_VERTICAL_PROGRESS,
                 config.isUserControlled() ? LINEAR : DECELERATE_1_7);
         Animator anim = createSpringAnimation(mProgress, targetProgress);
+        anim.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationCancel(Animator animation) {
+                setProgress(targetProgress);
+            }
+        });
         anim.setInterpolator(verticalProgressInterpolator);
         builder.add(anim);
 
diff --git a/src/com/android/launcher3/allapps/WorkUtilityView.java b/src/com/android/launcher3/allapps/WorkUtilityView.java
index b263639..bccc279 100644
--- a/src/com/android/launcher3/allapps/WorkUtilityView.java
+++ b/src/com/android/launcher3/allapps/WorkUtilityView.java
@@ -134,7 +134,8 @@
         if (shouldUseScheduler()) {
             mSchedulerButton.setVisibility(VISIBLE);
             mSchedulerButton.setOnClickListener(view ->
-                    mContext.startActivity(new Intent(mWorkSchedulerIntentAction)));
+                    mActivityContext.startActivitySafely(view,
+                            new Intent(mWorkSchedulerIntentAction), null /* itemInfo */));
         }
     }
 
diff --git a/src/com/android/launcher3/dragndrop/DragLayer.java b/src/com/android/launcher3/dragndrop/DragLayer.java
index a826b9e..41b42b6 100644
--- a/src/com/android/launcher3/dragndrop/DragLayer.java
+++ b/src/com/android/launcher3/dragndrop/DragLayer.java
@@ -50,6 +50,7 @@
 import com.android.launcher3.Launcher;
 import com.android.launcher3.R;
 import com.android.launcher3.ShortcutAndWidgetContainer;
+import com.android.launcher3.ShortcutAndWidgetContainer.TranslationProvider;
 import com.android.launcher3.Utilities;
 import com.android.launcher3.Workspace;
 import com.android.launcher3.anim.PendingAnimation;
@@ -248,23 +249,27 @@
     public void animateViewIntoPosition(DragView dragView, final View child, int duration,
             View anchorView) {
 
-        ShortcutAndWidgetContainer parentChildren = (ShortcutAndWidgetContainer) child.getParent();
+        ShortcutAndWidgetContainer childParent = (ShortcutAndWidgetContainer) child.getParent();
         CellLayoutLayoutParams lp =  (CellLayoutLayoutParams) child.getLayoutParams();
-        parentChildren.measureChild(child);
-        parentChildren.layoutChild(child);
+        childParent.measureChild(child);
+        childParent.layoutChild(child);
 
         float coord[] = new float[2];
         float childScale = child.getScaleX();
 
         coord[0] = lp.x + (child.getMeasuredWidth() * (1 - childScale) / 2);
         coord[1] = lp.y + (child.getMeasuredHeight() * (1 - childScale) / 2);
+        TranslationProvider translationProvider = childParent.getTranslationProvider();
+        if (translationProvider != null) {
+            coord[0] = coord[0] + translationProvider.getTranslationX(lp.getCellX());
+        }
 
         // Since the child hasn't necessarily been laid out, we force the lp to be updated with
         // the correct coordinates (above) and use these to determine the final location
         float scale = getDescendantCoordRelativeToSelf((View) child.getParent(), coord);
 
         // We need to account for the scale of the child itself, as the above only accounts for
-        // for the scale in parents.
+        // the scale in parents.
         scale *= childScale;
         int toX = Math.round(coord[0]);
         int toY = Math.round(coord[1]);
diff --git a/src/com/android/launcher3/dragndrop/SpringLoadedDragController.kt b/src/com/android/launcher3/dragndrop/SpringLoadedDragController.kt
index 2aeab9d..4cbe7bb 100644
--- a/src/com/android/launcher3/dragndrop/SpringLoadedDragController.kt
+++ b/src/com/android/launcher3/dragndrop/SpringLoadedDragController.kt
@@ -47,7 +47,11 @@
     override fun onAlarm(alarm: Alarm) {
         if (screen != null) {
             // Snap to the screen that we are hovering over now
-            with(launcher.workspace) { if (!isVisible(screen)) snapToPage(indexOfChild(screen)) }
+            with(launcher.workspace) {
+                if (!isVisible(screen) && launcher.dragController.mDistanceSinceScroll != 0) {
+                    snapToPage(indexOfChild(screen))
+                }
+            }
         } else {
             launcher.dragController.cancelDrag()
         }
diff --git a/src/com/android/launcher3/popup/SystemShortcut.java b/src/com/android/launcher3/popup/SystemShortcut.java
index 63c9d94..329d9df 100644
--- a/src/com/android/launcher3/popup/SystemShortcut.java
+++ b/src/com/android/launcher3/popup/SystemShortcut.java
@@ -210,6 +210,30 @@
         }
     }
 
+    public static final Factory<ActivityContext> PIN_UNPIN_ITEM =
+            (context, itemInfo, originalView) -> {
+                // Predicted items use {@code HotseatPredictionController.PinPrediction} shortcut
+                // to pin.
+                if (itemInfo.isPredictedItem()) {
+                    return null;
+                }
+                return new PinUnpinItem<>(context, itemInfo, originalView);
+            };
+
+    private static class PinUnpinItem<T extends ActivityContext> extends SystemShortcut<T> {
+        PinUnpinItem(T target, ItemInfo itemInfo, @NonNull View originalView) {
+            // TODO(b/375648361): Check the pin state of the item to determine if the pin or the
+            //  unpin option should be used.
+            super(R.drawable.ic_pin, R.string.pin_to_taskbar, target,
+                    itemInfo, originalView);
+        }
+
+        @Override
+        public void onClick(View view) {
+            // TODO(b/375648361): Pin/Unpin the item here.
+        }
+    }
+
     public static final Factory<ActivityContext> PRIVATE_PROFILE_INSTALL =
             (context, itemInfo, originalView) -> {
                 if (originalView == null) {
diff --git a/tests/multivalentTests/src/com/android/launcher3/folder/FolderTest.kt b/tests/multivalentTests/src/com/android/launcher3/folder/FolderTest.kt
index 4eb335e..bcf5f0d 100644
--- a/tests/multivalentTests/src/com/android/launcher3/folder/FolderTest.kt
+++ b/tests/multivalentTests/src/com/android/launcher3/folder/FolderTest.kt
@@ -58,6 +58,7 @@
 import junit.framework.TestCase.assertNull
 import junit.framework.TestCase.assertTrue
 import org.junit.After
+import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.mockito.Mockito
@@ -74,10 +75,16 @@
 @RunWith(AndroidJUnit4::class)
 class FolderTest {
 
-    private val context: Context =
-        ActivityContextWrapper(ApplicationProvider.getApplicationContext())
-    private val workspaceBuilder = TestWorkspaceBuilder(context)
-    private val folder: Folder = spy(Folder(context, null))
+    private lateinit var context: Context
+    private lateinit var workspaceBuilder: TestWorkspaceBuilder
+    private lateinit var folder: Folder
+
+    @Before
+    fun setUp() {
+        context = ActivityContextWrapper(ApplicationProvider.getApplicationContext())
+        workspaceBuilder = TestWorkspaceBuilder(context)
+        folder = spy(Folder(context, null))
+    }
 
     @After
     fun tearDown() {
@@ -412,7 +419,7 @@
             folder.onEditorAction(
                 Mockito.mock(TextView::class.java),
                 EditorInfo.IME_ACTION_DONE,
-                Mockito.mock(KeyEvent::class.java)
+                Mockito.mock(KeyEvent::class.java),
             )
 
         assertTrue(result)
@@ -427,7 +434,7 @@
             folder.onEditorAction(
                 Mockito.mock(TextView::class.java),
                 EditorInfo.IME_ACTION_NONE,
-                Mockito.mock(KeyEvent::class.java)
+                Mockito.mock(KeyEvent::class.java),
             )
 
         assertFalse(result)
@@ -824,7 +831,7 @@
         val items =
             arrayListOf<ItemInfo>(
                 Mockito.mock(ItemInfo::class.java),
-                Mockito.mock(ItemInfo::class.java)
+                Mockito.mock(ItemInfo::class.java),
             )
         val view1 = Mockito.mock(View::class.java)
         val view2 = Mockito.mock(View::class.java)
@@ -845,7 +852,7 @@
         val items =
             arrayListOf<ItemInfo>(
                 Mockito.mock(ItemInfo::class.java),
-                Mockito.mock(ItemInfo::class.java)
+                Mockito.mock(ItemInfo::class.java),
             )
         val view1 = Mockito.mock(View::class.java)
         val view2 = Mockito.mock(View::class.java)
@@ -867,7 +874,7 @@
         val items =
             arrayListOf<ItemInfo>(
                 Mockito.mock(ItemInfo::class.java),
-                Mockito.mock(ItemInfo::class.java)
+                Mockito.mock(ItemInfo::class.java),
             )
         val view1 = Mockito.mock(View::class.java)
         val view2 = Mockito.mock(View::class.java)
@@ -887,7 +894,7 @@
         val items =
             arrayListOf<ItemInfo>(
                 Mockito.mock(ItemInfo::class.java),
-                Mockito.mock(ItemInfo::class.java)
+                Mockito.mock(ItemInfo::class.java),
             )
         val view1 = Mockito.mock(View::class.java)
         val view2 = Mockito.mock(View::class.java)
@@ -908,7 +915,7 @@
         val items =
             arrayListOf<ItemInfo>(
                 Mockito.mock(ItemInfo::class.java),
-                Mockito.mock(ItemInfo::class.java)
+                Mockito.mock(ItemInfo::class.java),
             )
         val view1 = Mockito.mock(View::class.java)
         val view2 = Mockito.mock(View::class.java)