2021-11-22 16:54:54 +00:00
|
|
|
/*
|
|
|
|
|
* Copyright (C) 2022 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.graphics.Rect
|
|
|
|
|
import com.android.launcher3.InvariantDeviceProfile
|
|
|
|
|
import com.android.launcher3.LauncherAppState
|
2025-03-25 23:58:18 -07:00
|
|
|
import com.android.launcher3.LauncherModel
|
2023-05-01 16:55:59 -07:00
|
|
|
import com.android.launcher3.model.data.AppInfo
|
2025-07-22 20:32:17 +00:00
|
|
|
import com.android.launcher3.model.data.ItemInfo
|
2021-11-22 16:54:54 +00:00
|
|
|
import com.android.launcher3.model.data.WorkspaceItemInfo
|
|
|
|
|
import com.android.launcher3.util.GridOccupancy
|
|
|
|
|
import com.android.launcher3.util.IntArray
|
|
|
|
|
import com.android.launcher3.util.IntSparseArrayMap
|
2023-05-01 16:55:59 -07:00
|
|
|
import com.android.launcher3.util.LauncherLayoutBuilder
|
|
|
|
|
import com.android.launcher3.util.LauncherModelHelper.TEST_ACTIVITY
|
|
|
|
|
import com.android.launcher3.util.LauncherModelHelper.TEST_PACKAGE
|
2025-03-25 23:58:18 -07:00
|
|
|
import com.android.launcher3.util.ModelTestExtensions.loadModelSync
|
|
|
|
|
import com.android.launcher3.util.SandboxApplication
|
|
|
|
|
import com.android.launcher3.util.rule.LayoutProviderRule
|
2021-11-22 16:54:54 +00:00
|
|
|
import java.util.UUID
|
2025-03-25 23:58:18 -07:00
|
|
|
import org.junit.Rule
|
2021-11-22 16:54:54 +00:00
|
|
|
|
2023-01-06 15:16:41 +00:00
|
|
|
/** Base class for workspace related tests. */
|
2021-11-22 16:54:54 +00:00
|
|
|
abstract class AbstractWorkspaceModelTest {
|
|
|
|
|
companion object {
|
|
|
|
|
val emptyScreenSpaces = listOf(Rect(0, 0, 5, 5))
|
|
|
|
|
val fullScreenSpaces = emptyList<Rect>()
|
|
|
|
|
val nonEmptyScreenSpaces = listOf(Rect(1, 2, 3, 4))
|
|
|
|
|
}
|
|
|
|
|
|
2025-03-25 23:58:18 -07:00
|
|
|
@get:Rule val mTargetContext: SandboxApplication = SandboxApplication().withModelDependency()
|
|
|
|
|
@get:Rule var mLayoutProvider: LayoutProviderRule = LayoutProviderRule(mTargetContext)
|
|
|
|
|
|
2023-05-01 16:55:59 -07:00
|
|
|
protected lateinit var mLayoutBuilder: LauncherLayoutBuilder
|
2021-11-22 16:54:54 +00:00
|
|
|
protected lateinit var mIdp: InvariantDeviceProfile
|
|
|
|
|
protected lateinit var mAppState: LauncherAppState
|
|
|
|
|
protected lateinit var mExistingScreens: IntArray
|
|
|
|
|
protected lateinit var mNewScreens: IntArray
|
2025-07-22 20:32:17 +00:00
|
|
|
protected lateinit var mAddedWorkspaceItems: ArrayList<ItemInfo>
|
2021-11-22 16:54:54 +00:00
|
|
|
protected lateinit var mScreenOccupancy: IntSparseArrayMap<GridOccupancy>
|
|
|
|
|
|
2025-03-25 23:58:18 -07:00
|
|
|
val model: LauncherModel
|
|
|
|
|
get() = LauncherAppState.getInstance(mTargetContext).model
|
|
|
|
|
|
2021-11-22 16:54:54 +00:00
|
|
|
open fun setup() {
|
2023-05-01 16:55:59 -07:00
|
|
|
mLayoutBuilder = LauncherLayoutBuilder()
|
2021-11-22 16:54:54 +00:00
|
|
|
mIdp = InvariantDeviceProfile.INSTANCE[mTargetContext]
|
|
|
|
|
mIdp.numRows = 5
|
|
|
|
|
mIdp.numColumns = mIdp.numRows
|
|
|
|
|
mAppState = LauncherAppState.getInstance(mTargetContext)
|
|
|
|
|
mExistingScreens = IntArray()
|
|
|
|
|
mScreenOccupancy = IntSparseArrayMap()
|
|
|
|
|
mNewScreens = IntArray()
|
2025-07-22 20:32:17 +00:00
|
|
|
mAddedWorkspaceItems = ArrayList()
|
2021-11-22 16:54:54 +00:00
|
|
|
}
|
|
|
|
|
|
2023-01-06 15:16:41 +00:00
|
|
|
/** Sets up workspaces with the given screen IDs with some items and a 2x2 space. */
|
2021-11-22 16:54:54 +00:00
|
|
|
fun setupWorkspaces(screenIdsWithItems: List<Int>) {
|
2023-05-01 16:55:59 -07:00
|
|
|
screenIdsWithItems.forEach { screenId -> setupWorkspace(screenId, nonEmptyScreenSpaces) }
|
2025-03-25 23:58:18 -07:00
|
|
|
mLayoutProvider.setupDefaultLayoutProvider(mLayoutBuilder)
|
2023-05-01 16:55:59 -07:00
|
|
|
mIdp.numRows = 5
|
|
|
|
|
mIdp.numColumns = mIdp.numRows
|
2025-03-25 23:58:18 -07:00
|
|
|
model.loadModelSync()
|
2021-11-22 16:54:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Sets up the given workspaces with the given spaces, and fills the remaining space with items.
|
|
|
|
|
*/
|
|
|
|
|
fun setupWorkspacesWithSpaces(
|
|
|
|
|
screen0: List<Rect>? = null,
|
|
|
|
|
screen1: List<Rect>? = null,
|
|
|
|
|
screen2: List<Rect>? = null,
|
|
|
|
|
screen3: List<Rect>? = null,
|
2023-05-01 16:55:59 -07:00
|
|
|
) {
|
|
|
|
|
listOf(screen0, screen1, screen2, screen3).let(this::setupWithSpaces)
|
2025-03-25 23:58:18 -07:00
|
|
|
mLayoutProvider.setupDefaultLayoutProvider(mLayoutBuilder)
|
2023-05-01 16:55:59 -07:00
|
|
|
mIdp.numRows = 5
|
|
|
|
|
mIdp.numColumns = mIdp.numRows
|
2025-03-25 23:58:18 -07:00
|
|
|
model.loadModelSync()
|
2023-05-01 16:55:59 -07:00
|
|
|
}
|
2021-11-22 16:54:54 +00:00
|
|
|
|
|
|
|
|
private fun setupWithSpaces(workspaceSpaces: List<List<Rect>?>) {
|
|
|
|
|
workspaceSpaces.forEachIndexed { screenId, spaces ->
|
|
|
|
|
if (spaces != null) {
|
2023-05-01 16:55:59 -07:00
|
|
|
setupWorkspace(screenId, spaces)
|
2021-11-22 16:54:54 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-05-01 16:55:59 -07:00
|
|
|
private fun setupWorkspace(screenId: Int, spaces: List<Rect>) {
|
2021-11-22 16:54:54 +00:00
|
|
|
val occupancy = GridOccupancy(mIdp.numColumns, mIdp.numRows)
|
|
|
|
|
occupancy.markCells(0, 0, mIdp.numColumns, mIdp.numRows, true)
|
2023-01-06 15:16:41 +00:00
|
|
|
spaces.forEach { spaceRect -> occupancy.markCells(spaceRect, false) }
|
2021-11-22 16:54:54 +00:00
|
|
|
mExistingScreens.add(screenId)
|
|
|
|
|
mScreenOccupancy.append(screenId, occupancy)
|
|
|
|
|
for (x in 0 until mIdp.numColumns) {
|
|
|
|
|
for (y in 0 until mIdp.numRows) {
|
2023-05-01 16:55:59 -07:00
|
|
|
if (occupancy.cells[x][y]) {
|
|
|
|
|
mLayoutBuilder.atWorkspace(x, y, screenId).putApp(TEST_PACKAGE, TEST_ACTIVITY)
|
2021-11-22 16:54:54 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-06 15:16:41 +00:00
|
|
|
fun getExistingItem() =
|
2023-05-01 16:55:59 -07:00
|
|
|
WorkspaceItemInfo().apply {
|
|
|
|
|
intent = AppInfo.makeLaunchIntent(ComponentName(TEST_PACKAGE, TEST_ACTIVITY))
|
|
|
|
|
}
|
2021-11-22 16:54:54 +00:00
|
|
|
|
|
|
|
|
fun getNewItem(): WorkspaceItemInfo {
|
|
|
|
|
val itemPackage = UUID.randomUUID().toString()
|
2023-01-06 15:16:41 +00:00
|
|
|
return WorkspaceItemInfo().apply {
|
2023-05-01 16:55:59 -07:00
|
|
|
intent = AppInfo.makeLaunchIntent(ComponentName(itemPackage, itemPackage))
|
2023-01-06 15:16:41 +00:00
|
|
|
}
|
2021-11-22 16:54:54 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-06 15:16:41 +00:00
|
|
|
data class NewItemSpace(val screenId: Int, val cellX: Int, val cellY: Int) {
|
2021-11-22 16:54:54 +00:00
|
|
|
fun toIntArray() = intArrayOf(screenId, cellX, cellY)
|
|
|
|
|
|
|
|
|
|
companion object {
|
|
|
|
|
fun fromIntArray(array: kotlin.IntArray) = NewItemSpace(array[0], array[1], array[2])
|
|
|
|
|
}
|
2023-01-06 15:16:41 +00:00
|
|
|
}
|