Add logs and prevent collissions when adding items

-AddWorkspaceItemsTask can add multiple items to the same position, we
avoid that here by adding each item to the database before processing
the next item.
-We add more logs to InstallSessionHelper to be able to check who the
installer is

Bug: 432237485, 425754534
Test: AddWorkspaceItemsTaskTest
Flag: EXEMPT bugfix
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:4b439e999734852a017ce662543b4789b36e0e3b)
Merged-In: I2d238f3eb27734ab9cb723e2fe9d6752c5921dd1
Change-Id: I2d238f3eb27734ab9cb723e2fe9d6752c5921dd1
This commit is contained in:
Federico Baron
2025-07-22 20:32:17 +00:00
committed by Android Build Coastguard Worker
parent 02aa11510d
commit df328e5dfa
6 changed files with 71 additions and 15 deletions
@@ -21,6 +21,7 @@ import com.android.launcher3.InvariantDeviceProfile
import com.android.launcher3.LauncherAppState
import com.android.launcher3.LauncherModel
import com.android.launcher3.model.data.AppInfo
import com.android.launcher3.model.data.ItemInfo
import com.android.launcher3.model.data.WorkspaceItemInfo
import com.android.launcher3.util.GridOccupancy
import com.android.launcher3.util.IntArray
@@ -50,6 +51,7 @@ abstract class AbstractWorkspaceModelTest {
protected lateinit var mAppState: LauncherAppState
protected lateinit var mExistingScreens: IntArray
protected lateinit var mNewScreens: IntArray
protected lateinit var mAddedWorkspaceItems: ArrayList<ItemInfo>
protected lateinit var mScreenOccupancy: IntSparseArrayMap<GridOccupancy>
val model: LauncherModel
@@ -64,6 +66,7 @@ abstract class AbstractWorkspaceModelTest {
mExistingScreens = IntArray()
mScreenOccupancy = IntSparseArrayMap()
mNewScreens = IntArray()
mAddedWorkspaceItems = ArrayList()
}
/** Sets up workspaces with the given screen IDs with some items and a 2x2 space. */
@@ -25,6 +25,7 @@ import com.android.launcher3.util.Executors
import com.android.launcher3.util.IntArray
import com.android.launcher3.util.TestUtil.runOnExecutorSync
import com.google.common.truth.Truth.assertThat
import java.util.ArrayList
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@@ -62,7 +63,7 @@ class AddWorkspaceItemsTaskTest : AbstractWorkspaceModelTest() {
assertThat(addedItems.size).isEqualTo(1)
assertThat(addedItems.first().screenId).isEqualTo(1)
verifyItemSpaceFinderCall(nonEmptyScreenIds, numberOfExpectedCall = 1)
verifyItemSpaceFinderCall(nonEmptyScreenIds, numberOfExpectedCall = 1, addedItems)
}
@Test
@@ -75,7 +76,7 @@ class AddWorkspaceItemsTaskTest : AbstractWorkspaceModelTest() {
assertThat(addedItems.size).isEqualTo(1)
assertThat(addedItems.first().screenId).isEqualTo(1)
verifyItemSpaceFinderCall(nonEmptyScreenIds, numberOfExpectedCall = 1)
verifyItemSpaceFinderCall(nonEmptyScreenIds, numberOfExpectedCall = 1, addedItems)
}
@Test
@@ -101,7 +102,7 @@ class AddWorkspaceItemsTaskTest : AbstractWorkspaceModelTest() {
assertThat(addedItems.size).isEqualTo(1)
assertThat(addedItems.first().screenId).isEqualTo(2)
verifyItemSpaceFinderCall(nonEmptyScreenIds, numberOfExpectedCall = 1)
verifyItemSpaceFinderCall(nonEmptyScreenIds, numberOfExpectedCall = 1, addedItems)
}
@Test
@@ -123,26 +124,30 @@ class AddWorkspaceItemsTaskTest : AbstractWorkspaceModelTest() {
// Items that are added to the second screen should be animated
val itemsAddedToSecondScreen = addedItems.filter { it.screenId == 2 }
assertThat(itemsAddedToSecondScreen.size).isEqualTo(2)
verifyItemSpaceFinderCall(nonEmptyScreenIds, numberOfExpectedCall = 3)
verifyItemSpaceFinderCall(nonEmptyScreenIds, numberOfExpectedCall = 3, addedItems)
}
/** Sets up the item space data that will be returned from WorkspaceItemSpaceFinder. */
private fun givenNewItemSpaces(vararg newItemSpaces: NewItemSpace) {
val spaceStack = newItemSpaces.toMutableList()
whenever(mWorkspaceItemSpaceFinder.findSpaceForItem(any(), any(), any(), any())).then {
spaceStack.removeFirst().toIntArray()
}
whenever(mWorkspaceItemSpaceFinder.findSpaceForItem(any(), any(), any(), any(), any()))
.then { spaceStack.removeFirst().toIntArray() }
}
/**
* Verifies if WorkspaceItemSpaceFinder was called with proper arguments and how many times was
* it called.
*/
private fun verifyItemSpaceFinderCall(nonEmptyScreenIds: List<Int>, numberOfExpectedCall: Int) {
private fun verifyItemSpaceFinderCall(
nonEmptyScreenIds: List<Int>,
numberOfExpectedCall: Int,
items: List<ItemInfo>,
) {
verify(mWorkspaceItemSpaceFinder, times(numberOfExpectedCall))
.findSpaceForItem(
eq(IntArray.wrap(*nonEmptyScreenIds.toIntArray())),
eq(IntArray()),
eq(ArrayList(items)),
eq(1),
eq(1),
)
@@ -18,6 +18,8 @@ package com.android.launcher3.model
import android.graphics.Rect
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.launcher3.LauncherSettings.Favorites.CONTAINER_DESKTOP
import com.android.launcher3.model.data.ItemInfo
import com.android.launcher3.util.ModelTestExtensions.bgDataModel
import com.google.common.truth.Truth.assertThat
import org.junit.Before
@@ -36,7 +38,7 @@ class WorkspaceItemSpaceFinderTest : AbstractWorkspaceModelTest() {
private fun findSpace(spanX: Int, spanY: Int): NewItemSpace =
WorkspaceItemSpaceFinder(model.bgDataModel, mAppState.invariantDeviceProfile, model)
.findSpaceForItem(mExistingScreens, mNewScreens, spanX, spanY)
.findSpaceForItem(mExistingScreens, mNewScreens, mAddedWorkspaceItems, spanX, spanY)
.let { NewItemSpace.fromIntArray(it) }
private fun assertRegionVacant(newItemSpace: NewItemSpace, spanX: Int, spanY: Int) {
@@ -67,6 +69,37 @@ class WorkspaceItemSpaceFinderTest : AbstractWorkspaceModelTest() {
assertRegionVacant(spaceFound, 1, 1)
}
@Test
fun workspaceItemsAddedButNotYetCommittedToDbShouldBeTakenIntoAccountInFindSpaceForItem() {
setupWorkspacesWithSpaces(
// 3x2 space on screen 0, but it should be skipped
screen0 = listOf(Rect(2, 0, 5, 2)),
screen1 = listOf(Rect(2, 2, 4, 4)), // 2x2 space
)
val itemInfo = ItemInfo()
itemInfo.cellX = 2
itemInfo.cellY = 2
itemInfo.screenId = 1
itemInfo.container = CONTAINER_DESKTOP
mAddedWorkspaceItems.add(itemInfo)
val itemInfo2 = ItemInfo()
itemInfo2.cellX = 3
itemInfo2.cellY = 2
itemInfo2.screenId = 1
itemInfo2.container = CONTAINER_DESKTOP
mAddedWorkspaceItems.add(itemInfo2)
val spaceFound = findSpace(1, 1)
assertThat(spaceFound.screenId).isEqualTo(1)
assertThat(spaceFound.cellX).isEqualTo(2)
assertThat(spaceFound.cellY).isEqualTo(3)
assertRegionVacant(spaceFound, 1, 1)
mAddedWorkspaceItems.clear()
}
@Test
fun notEnoughSpaceOnFirstScreen_whenFindSpaceForItem_thenReturnSecondScreenId() {
setupWorkspacesWithSpaces(