diff --git a/tests/Android.bp b/tests/Android.bp
index c329ece..3670c37 100644
--- a/tests/Android.bp
+++ b/tests/Android.bp
@@ -23,7 +23,7 @@
 // Source code used for test
 filegroup {
     name: "launcher-tests-src",
-    srcs: ["src/**/*.java", "src/**/*.kt"],
+    srcs: ["src/**/*.java"],
 }
 
 // Source code used for oop test helpers
diff --git a/tests/src/com/android/launcher3/model/AddWorkspaceItemsTaskTest.java b/tests/src/com/android/launcher3/model/AddWorkspaceItemsTaskTest.java
new file mode 100644
index 0000000..8a4590a
--- /dev/null
+++ b/tests/src/com/android/launcher3/model/AddWorkspaceItemsTaskTest.java
@@ -0,0 +1,201 @@
+package com.android.launcher3.model;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.Rect;
+import android.util.Pair;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+
+import com.android.launcher3.InvariantDeviceProfile;
+import com.android.launcher3.LauncherAppState;
+import com.android.launcher3.LauncherSettings;
+import com.android.launcher3.LauncherSettings.Favorites;
+import com.android.launcher3.model.BgDataModel.Callbacks;
+import com.android.launcher3.model.data.ItemInfo;
+import com.android.launcher3.model.data.WorkspaceItemInfo;
+import com.android.launcher3.util.ContentWriter;
+import com.android.launcher3.util.Executors;
+import com.android.launcher3.util.GridOccupancy;
+import com.android.launcher3.util.IntArray;
+import com.android.launcher3.util.IntSparseArrayMap;
+import com.android.launcher3.util.LauncherModelHelper;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Tests for {@link AddWorkspaceItemsTask}
+ */
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class AddWorkspaceItemsTaskTest {
+
+    private final ComponentName mComponent1 = new ComponentName("a", "b");
+    private final ComponentName mComponent2 = new ComponentName("b", "b");
+
+    private Context mTargetContext;
+    private InvariantDeviceProfile mIdp;
+    private LauncherAppState mAppState;
+    private LauncherModelHelper mModelHelper;
+
+    private IntArray mExistingScreens;
+    private IntArray mNewScreens;
+    private IntSparseArrayMap<GridOccupancy> mScreenOccupancy;
+
+    @Before
+    public void setup() {
+        mModelHelper = new LauncherModelHelper();
+        mTargetContext = mModelHelper.sandboxContext;
+        mIdp = InvariantDeviceProfile.INSTANCE.get(mTargetContext);
+        mIdp.numColumns = mIdp.numRows = 5;
+        mAppState = LauncherAppState.getInstance(mTargetContext);
+
+        mExistingScreens = new IntArray();
+        mScreenOccupancy = new IntSparseArrayMap<>();
+        mNewScreens = new IntArray();
+    }
+
+    @After
+    public void tearDown() {
+        mModelHelper.destroy();
+    }
+
+    private AddWorkspaceItemsTask newTask(ItemInfo... items) {
+        List<Pair<ItemInfo, Object>> list = new ArrayList<>();
+        for (ItemInfo item : items) {
+            list.add(Pair.create(item, null));
+        }
+        return new AddWorkspaceItemsTask(list);
+    }
+
+    @Test
+    public void testFindSpaceForItem_prefers_second() throws Exception {
+        // First screen has only one hole of size 1
+        int nextId = setupWorkspaceWithHoles(1, 1, new Rect(2, 2, 3, 3));
+
+        // Second screen has 2 holes of sizes 3x2 and 2x3
+        setupWorkspaceWithHoles(nextId, 2, new Rect(2, 0, 5, 2), new Rect(0, 2, 2, 5));
+
+        int[] spaceFound = newTask().findSpaceForItem(
+                mAppState, mModelHelper.getBgDataModel(), mExistingScreens, mNewScreens, 1, 1);
+        assertEquals(1, spaceFound[0]);
+        assertTrue(mScreenOccupancy.get(spaceFound[0])
+                .isRegionVacant(spaceFound[1], spaceFound[2], 1, 1));
+
+        // Find a larger space
+        spaceFound = newTask().findSpaceForItem(
+                mAppState, mModelHelper.getBgDataModel(), mExistingScreens, mNewScreens, 2, 3);
+        assertEquals(2, spaceFound[0]);
+        assertTrue(mScreenOccupancy.get(spaceFound[0])
+                .isRegionVacant(spaceFound[1], spaceFound[2], 2, 3));
+    }
+
+    @Test
+    public void testFindSpaceForItem_adds_new_screen() throws Exception {
+        // First screen has 2 holes of sizes 3x2 and 2x3
+        setupWorkspaceWithHoles(1, 1, new Rect(2, 0, 5, 2), new Rect(0, 2, 2, 5));
+
+        IntArray oldScreens = mExistingScreens.clone();
+        int[] spaceFound = newTask().findSpaceForItem(
+                mAppState, mModelHelper.getBgDataModel(), mExistingScreens, mNewScreens, 3, 3);
+        assertFalse(oldScreens.contains(spaceFound[0]));
+        assertTrue(mNewScreens.contains(spaceFound[0]));
+    }
+
+    @Test
+    public void testAddItem_existing_item_ignored() throws Exception {
+        WorkspaceItemInfo info = new WorkspaceItemInfo();
+        info.intent = new Intent().setComponent(mComponent1);
+
+        // Setup a screen with a hole
+        setupWorkspaceWithHoles(1, 1, new Rect(2, 2, 3, 3));
+
+        // Nothing was added
+        assertTrue(mModelHelper.executeTaskForTest(newTask(info)).isEmpty());
+    }
+
+    @Test
+    public void testAddItem_some_items_added() throws Exception {
+        Callbacks callbacks = mock(Callbacks.class);
+        Executors.MAIN_EXECUTOR.submit(() -> mModelHelper.getModel().addCallbacks(callbacks)).get();
+
+        WorkspaceItemInfo info = new WorkspaceItemInfo();
+        info.intent = new Intent().setComponent(mComponent1);
+
+        WorkspaceItemInfo info2 = new WorkspaceItemInfo();
+        info2.intent = new Intent().setComponent(mComponent2);
+
+        // Setup a screen with a hole
+        setupWorkspaceWithHoles(1, 1, new Rect(2, 2, 3, 3));
+
+        mModelHelper.executeTaskForTest(newTask(info, info2)).get(0).run();
+        ArgumentCaptor<ArrayList> notAnimated = ArgumentCaptor.forClass(ArrayList.class);
+        ArgumentCaptor<ArrayList> animated = ArgumentCaptor.forClass(ArrayList.class);
+
+        // only info2 should be added because info was already added to the workspace
+        // in setupWorkspaceWithHoles()
+        verify(callbacks).bindAppsAdded(any(IntArray.class), notAnimated.capture(),
+                animated.capture());
+        assertTrue(notAnimated.getValue().isEmpty());
+
+        assertEquals(1, animated.getValue().size());
+        assertTrue(animated.getValue().contains(info2));
+    }
+
+    private int setupWorkspaceWithHoles(int startId, int screenId, Rect... holes) throws Exception {
+        return mModelHelper.executeSimpleTask(
+                model -> writeWorkspaceWithHoles(model, startId, screenId, holes));
+    }
+
+    private int writeWorkspaceWithHoles(
+            BgDataModel bgDataModel, int startId, int screenId, Rect... holes) {
+        GridOccupancy occupancy = new GridOccupancy(mIdp.numColumns, mIdp.numRows);
+        occupancy.markCells(0, 0, mIdp.numColumns, mIdp.numRows, true);
+        for (Rect r : holes) {
+            occupancy.markCells(r, false);
+        }
+
+        mExistingScreens.add(screenId);
+        mScreenOccupancy.append(screenId, occupancy);
+
+        for (int x = 0; x < mIdp.numColumns; x++) {
+            for (int y = 0; y < mIdp.numRows; y++) {
+                if (!occupancy.cells[x][y]) {
+                    continue;
+                }
+
+                WorkspaceItemInfo info = new WorkspaceItemInfo();
+                info.intent = new Intent().setComponent(mComponent1);
+                info.id = startId++;
+                info.screenId = screenId;
+                info.cellX = x;
+                info.cellY = y;
+                info.container = LauncherSettings.Favorites.CONTAINER_DESKTOP;
+                bgDataModel.addItem(mTargetContext, info, false);
+
+                ContentWriter writer = new ContentWriter(mTargetContext);
+                info.writeToValues(writer);
+                writer.put(Favorites._ID, info.id);
+                mTargetContext.getContentResolver().insert(Favorites.CONTENT_URI,
+                        writer.getValues(mTargetContext));
+            }
+        }
+        return startId;
+    }
+}
diff --git a/tests/src/com/android/launcher3/model/AddWorkspaceItemsTaskTest.kt b/tests/src/com/android/launcher3/model/AddWorkspaceItemsTaskTest.kt
deleted file mode 100644
index e315658..0000000
--- a/tests/src/com/android/launcher3/model/AddWorkspaceItemsTaskTest.kt
+++ /dev/null
@@ -1,325 +0,0 @@
-/*
- * Copyright (C) 2021 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.launcher3.model
-
-import android.content.ComponentName
-import android.content.Context
-import android.content.Intent
-import android.graphics.Rect
-import android.util.Pair
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import androidx.test.filters.SmallTest
-import com.android.launcher3.InvariantDeviceProfile
-import com.android.launcher3.LauncherAppState
-import com.android.launcher3.LauncherSettings
-import com.android.launcher3.model.data.ItemInfo
-import com.android.launcher3.model.data.WorkspaceItemInfo
-import com.android.launcher3.util.*
-import com.android.launcher3.util.IntArray
-import org.junit.After
-import org.junit.Assert.*
-import org.junit.Before
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.mockito.*
-import org.mockito.ArgumentMatchers.any
-import org.mockito.Mockito.verify
-import kotlin.collections.ArrayList
-
-/**
- * Tests for [AddWorkspaceItemsTask]
- */
-@SmallTest
-@RunWith(AndroidJUnit4::class)
-class AddWorkspaceItemsTaskTest {
-
-    @Captor
-    private lateinit var animatedItemArgumentCaptor: ArgumentCaptor<ArrayList<ItemInfo>>
-
-    @Captor
-    private lateinit var notAnimatedItemArgumentCaptor: ArgumentCaptor<ArrayList<ItemInfo>>
-
-    @Mock
-    private lateinit var dataModelCallbacks: BgDataModel.Callbacks
-
-    private lateinit var mTargetContext: Context
-    private lateinit var mIdp: InvariantDeviceProfile
-    private lateinit var mAppState: LauncherAppState
-    private lateinit var mModelHelper: LauncherModelHelper
-    private lateinit var mExistingScreens: IntArray
-    private lateinit var mNewScreens: IntArray
-    private lateinit var mScreenOccupancy: IntSparseArrayMap<GridOccupancy>
-
-    private val emptyScreenHoles = listOf(Rect(0, 0, 5, 5))
-    private val fullScreenHoles = emptyList<Rect>()
-
-
-    @Before
-    fun setup() {
-        MockitoAnnotations.initMocks(this)
-        mModelHelper = LauncherModelHelper()
-        mTargetContext = mModelHelper.sandboxContext
-        mIdp = InvariantDeviceProfile.INSTANCE[mTargetContext]
-        mIdp.numRows = 5
-        mIdp.numColumns = mIdp.numRows
-        mAppState = LauncherAppState.getInstance(mTargetContext)
-        mExistingScreens = IntArray()
-        mScreenOccupancy = IntSparseArrayMap()
-        mNewScreens = IntArray()
-        Executors.MAIN_EXECUTOR.submit { mModelHelper.model.addCallbacks(dataModelCallbacks) }.get()
-    }
-
-    @After
-    fun tearDown() {
-        mModelHelper.destroy()
-    }
-
-    @Test
-    fun justEnoughSpaceOnFirstScreen_whenFindSpaceForItem_thenReturnFirstScreenId() {
-        setupWorkspacesWithHoles(
-                screen1 = listOf(Rect(2, 2, 3, 3)), // 1x1 hole
-                //  2 holes of sizes 3x2 and 2x3
-                screen2 = listOf(Rect(2, 0, 5, 2), Rect(0, 2, 2, 5)),
-        )
-
-        val spaceFound = newTask().findSpaceForItem(
-                mAppState, mModelHelper.bgDataModel, mExistingScreens, mNewScreens, 1, 1)
-        assertEquals(1, spaceFound[0])
-        assertTrue(mScreenOccupancy[spaceFound[0]]
-                .isRegionVacant(spaceFound[1], spaceFound[2], 1, 1))
-    }
-
-    @Test
-    fun notEnoughSpaceOnFirstScreen_whenFindSpaceForItem_thenReturnSecondScreenId() {
-        setupWorkspacesWithHoles(
-                screen1 = listOf(Rect(2, 2, 3, 3)), // 1x1 hole
-                //  2 holes of sizes 3x2 and 2x3
-                screen2 = listOf(Rect(2, 0, 5, 2), Rect(0, 2, 2, 5)),
-        )
-
-        // Find a larger space
-        val spaceFound = newTask().findSpaceForItem(
-                mAppState, mModelHelper.bgDataModel, mExistingScreens, mNewScreens, 2, 3)
-        assertEquals(2, spaceFound[0])
-        assertTrue(mScreenOccupancy[spaceFound[0]]
-                .isRegionVacant(spaceFound[1], spaceFound[2], 2, 3))
-    }
-
-    @Test
-    fun notEnoughSpaceOnExistingScreens_whenFindSpaceForItem_thenReturnNewScreenId() {
-        setupWorkspacesWithHoles(
-                //  2 holes of sizes 3x2 and 2x3
-                screen1 = listOf(Rect(2, 0, 5, 2), Rect(0, 2, 2, 5)),
-                //  2 holes of sizes 1x2 and 2x2
-                screen2 = listOf(Rect(1, 0, 2, 2), Rect(3, 2, 5, 4)),
-        )
-
-        val oldScreens = mExistingScreens.clone()
-        val spaceFound = newTask().findSpaceForItem(
-                mAppState, mModelHelper.bgDataModel, mExistingScreens, mNewScreens, 3, 3)
-        assertFalse(oldScreens.contains(spaceFound[0]))
-        assertTrue(mNewScreens.contains(spaceFound[0]))
-    }
-
-    @Test
-    fun enoughSpaceOnFirstScreen_whenTaskRuns_thenAddItemToFirstScreen() {
-        val workspaceHoles = createWorkspaceHoles(
-                screen1 = listOf(Rect(2, 2, 3, 3)), // 1x1 space
-                screen2 = listOf(Rect(2, 0, 5, 2)), // 3x2 space
-        )
-        val addedItems = testAddItems(workspaceHoles, getNewItem())
-        assertEquals(1, addedItems.size)
-        assertEquals(1, addedItems.first().itemInfo.screenId)
-    }
-
-    @Test
-    fun firstPageIsFull_whenTaskRuns_thenAddItemToSecondScreen() {
-        val workspaceHoles = createWorkspaceHoles(
-                screen1 = fullScreenHoles,
-        )
-        val addedItems = testAddItems(workspaceHoles, getNewItem())
-        assertEquals(1, addedItems.size)
-        assertEquals(2, addedItems.first().itemInfo.screenId)
-    }
-
-    @Test
-    fun firstScreenIsEmptyButSecondIsNotEmpty_whenTaskRuns_thenAddItemToSecondScreen() {
-        val workspaceHoles = createWorkspaceHoles(
-                screen1 = emptyScreenHoles,
-                screen2 = listOf(Rect(2, 0, 5, 2)), // 3x2 space
-        )
-        val addedItems = testAddItems(workspaceHoles, getNewItem())
-        assertEquals(1, addedItems.size)
-        assertEquals(2, addedItems.first().itemInfo.screenId)
-    }
-
-    @Test
-    fun twoEmptyMiddleScreens_whenTaskRuns_thenAddItemToThirdScreen() {
-        val workspaceHoles = createWorkspaceHoles(
-                screen1 = emptyScreenHoles,
-                screen2 = emptyScreenHoles,
-                screen3 = listOf(Rect(1, 1, 4, 4)), // 3x3 space
-        )
-        val addedItems = testAddItems(workspaceHoles, getNewItem())
-        assertEquals(1, addedItems.size)
-        assertEquals(3, addedItems.first().itemInfo.screenId)
-    }
-
-    @Test
-    fun allPagesAreFull_whenTaskRuns_thenAddItemToNewScreen() {
-        val workspaceHoles = createWorkspaceHoles(
-                screen1 = fullScreenHoles,
-                screen2 = fullScreenHoles,
-        )
-        val addedItems = testAddItems(workspaceHoles, getNewItem())
-        assertEquals(1, addedItems.size)
-        assertEquals(3, addedItems.first().itemInfo.screenId)
-    }
-
-    @Test
-    fun firstTwoPagesAreFull_and_ThirdPageIsEmpty_whenTaskRuns_thenAddItemToThirdPage() {
-        val workspaceHoles = createWorkspaceHoles(
-                screen1 = fullScreenHoles,
-                screen2 = fullScreenHoles,
-                screen3 = emptyScreenHoles
-        )
-        val addedItems = testAddItems(workspaceHoles, getNewItem())
-        assertEquals(1, addedItems.size)
-        assertEquals(3, addedItems.first().itemInfo.screenId)
-    }
-
-    @Test
-    fun itemIsAlreadyAdded_whenTaskRun_thenIgnoreItem() {
-        val task = newTask(getExistingItem())
-        setupWorkspacesWithHoles(
-                screen1 = listOf(Rect(2, 2, 3, 3)), // 1x1 hole
-        )
-
-        // Nothing was added
-        assertTrue(mModelHelper.executeTaskForTest(task).isEmpty())
-    }
-
-    @Test
-    fun newAndExistingItems_whenTaskRun_thenAddOnlyTheNewOne() {
-        val newItem = getNewItem()
-        val workspaceHoles = createWorkspaceHoles(
-                screen1 = listOf(Rect(2, 2, 3, 3)), // 1x1 hole
-        )
-        val addedItems = testAddItems(workspaceHoles, getExistingItem(), newItem)
-        assertEquals(1, addedItems.size)
-        val addedItem = addedItems.first()
-        assert(addedItem.isAnimated)
-        val addedItemInfo = addedItem.itemInfo
-        assertEquals(1, addedItemInfo.screenId)
-        assertEquals(newItem, addedItemInfo)
-    }
-
-    private fun testAddItems(
-            workspaceHoles: List<List<Rect>>,
-            vararg itemsToAdd: WorkspaceItemInfo
-    ): List<AddedItem> {
-        setupWorkspaces(workspaceHoles)
-        mModelHelper.executeTaskForTest(newTask(*itemsToAdd))[0].run()
-
-        verify(dataModelCallbacks).bindAppsAdded(any(),
-                notAnimatedItemArgumentCaptor.capture(), animatedItemArgumentCaptor.capture())
-
-        val addedItems = mutableListOf<AddedItem>()
-        addedItems.addAll(animatedItemArgumentCaptor.value.map { AddedItem(it, true) })
-        addedItems.addAll(notAnimatedItemArgumentCaptor.value.map { AddedItem(it, false) })
-        return addedItems
-    }
-
-    private fun setupWorkspaces(workspaceHoles: List<List<Rect>>) {
-        var nextItemId = 1
-        var screenId = 1
-        workspaceHoles.forEach { holes ->
-            nextItemId = setupWorkspace(nextItemId, screenId++, *holes.toTypedArray())
-        }
-    }
-
-    private fun setupWorkspace(startId: Int, screenId: Int, vararg holes: Rect): Int {
-        return mModelHelper.executeSimpleTask { dataModel ->
-            writeWorkspaceWithHoles(dataModel, startId, screenId, *holes)
-        }
-    }
-
-    private fun writeWorkspaceWithHoles(
-            bgDataModel: BgDataModel,
-            itemStartId: Int,
-            screenId: Int,
-            vararg holes: Rect,
-    ): Int {
-        var itemId = itemStartId
-        val occupancy = GridOccupancy(mIdp.numColumns, mIdp.numRows)
-        occupancy.markCells(0, 0, mIdp.numColumns, mIdp.numRows, true)
-        holes.forEach { holeRect ->
-            occupancy.markCells(holeRect, false)
-        }
-        mExistingScreens.add(screenId)
-        mScreenOccupancy.append(screenId, occupancy)
-        for (x in 0 until mIdp.numColumns) {
-            for (y in 0 until mIdp.numRows) {
-                if (!occupancy.cells[x][y]) {
-                    continue
-                }
-                val info = getExistingItem()
-                info.id = itemId++
-                info.screenId = screenId
-                info.cellX = x
-                info.cellY = y
-                info.container = LauncherSettings.Favorites.CONTAINER_DESKTOP
-                bgDataModel.addItem(mTargetContext, info, false)
-                val writer = ContentWriter(mTargetContext)
-                info.writeToValues(writer)
-                writer.put(LauncherSettings.Favorites._ID, info.id)
-                mTargetContext.contentResolver.insert(LauncherSettings.Favorites.CONTENT_URI,
-                        writer.getValues(mTargetContext))
-            }
-        }
-        return itemId
-    }
-
-    private fun setupWorkspacesWithHoles(
-            screen1: List<Rect>? = null,
-            screen2: List<Rect>? = null,
-            screen3: List<Rect>? = null,
-    ) = createWorkspaceHoles(screen1, screen2, screen3)
-            .let(this::setupWorkspaces)
-
-    private fun createWorkspaceHoles(
-            screen1: List<Rect>? = null,
-            screen2: List<Rect>? = null,
-            screen3: List<Rect>? = null,
-    ): List<List<Rect>> = listOfNotNull(screen1, screen2, screen3)
-
-    private fun newTask(vararg items: ItemInfo): AddWorkspaceItemsTask =
-            items.map { Pair.create(it, Any()) }
-                    .toMutableList()
-                    .let(::AddWorkspaceItemsTask)
-
-    private fun getExistingItem() = WorkspaceItemInfo()
-            .apply { intent = Intent().setComponent(ComponentName("a", "b")) }
-
-    private fun getNewItem() = WorkspaceItemInfo()
-            .apply { intent = Intent().setComponent(ComponentName("b", "b")) }
-}
-
-private data class AddedItem(
-        val itemInfo: ItemInfo,
-        val isAnimated: Boolean
-)
\ No newline at end of file
