diff --git a/tests/Android.bp b/tests/Android.bp
index 3670c37..c329ece 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"],
+    srcs: ["src/**/*.java", "src/**/*.kt"],
 }
 
 // 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
deleted file mode 100644
index 8a4590a..0000000
--- a/tests/src/com/android/launcher3/model/AddWorkspaceItemsTaskTest.java
+++ /dev/null
@@ -1,201 +0,0 @@
-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
new file mode 100644
index 0000000..e315658
--- /dev/null
+++ b/tests/src/com/android/launcher3/model/AddWorkspaceItemsTaskTest.kt
@@ -0,0 +1,325 @@
+/*
+ * 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
