1 /*
<lambda>null2  * Copyright (C) 2022 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.android.launcher3.model
17 
18 import android.content.ComponentName
19 import android.content.Context
20 import android.graphics.Rect
21 import com.android.launcher3.InvariantDeviceProfile
22 import com.android.launcher3.LauncherAppState
23 import com.android.launcher3.model.data.AppInfo
24 import com.android.launcher3.model.data.WorkspaceItemInfo
25 import com.android.launcher3.util.GridOccupancy
26 import com.android.launcher3.util.IntArray
27 import com.android.launcher3.util.IntSparseArrayMap
28 import com.android.launcher3.util.LauncherLayoutBuilder
29 import com.android.launcher3.util.LauncherModelHelper
30 import com.android.launcher3.util.LauncherModelHelper.TEST_ACTIVITY
31 import com.android.launcher3.util.LauncherModelHelper.TEST_PACKAGE
32 import java.util.UUID
33 
34 /** Base class for workspace related tests. */
35 abstract class AbstractWorkspaceModelTest {
36     companion object {
37         val emptyScreenSpaces = listOf(Rect(0, 0, 5, 5))
38         val fullScreenSpaces = emptyList<Rect>()
39         val nonEmptyScreenSpaces = listOf(Rect(1, 2, 3, 4))
40     }
41 
42     protected lateinit var mLayoutBuilder: LauncherLayoutBuilder
43     protected lateinit var mTargetContext: Context
44     protected lateinit var mIdp: InvariantDeviceProfile
45     protected lateinit var mAppState: LauncherAppState
46     protected lateinit var mModelHelper: LauncherModelHelper
47     protected lateinit var mExistingScreens: IntArray
48     protected lateinit var mNewScreens: IntArray
49     protected lateinit var mScreenOccupancy: IntSparseArrayMap<GridOccupancy>
50 
51     open fun setup() {
52         mLayoutBuilder = LauncherLayoutBuilder()
53         mModelHelper = LauncherModelHelper()
54         mTargetContext = mModelHelper.sandboxContext
55         mIdp = InvariantDeviceProfile.INSTANCE[mTargetContext]
56         mIdp.numRows = 5
57         mIdp.numColumns = mIdp.numRows
58         mAppState = LauncherAppState.getInstance(mTargetContext)
59         mExistingScreens = IntArray()
60         mScreenOccupancy = IntSparseArrayMap()
61         mNewScreens = IntArray()
62     }
63 
64     open fun tearDown() {
65         mModelHelper.destroy()
66     }
67 
68     /** Sets up workspaces with the given screen IDs with some items and a 2x2 space. */
69     fun setupWorkspaces(screenIdsWithItems: List<Int>) {
70         screenIdsWithItems.forEach { screenId -> setupWorkspace(screenId, nonEmptyScreenSpaces) }
71         mModelHelper.setupDefaultLayoutProvider(mLayoutBuilder)
72         mIdp.numRows = 5
73         mIdp.numColumns = mIdp.numRows
74         mModelHelper.loadModelSync()
75     }
76 
77     /**
78      * Sets up the given workspaces with the given spaces, and fills the remaining space with items.
79      */
80     fun setupWorkspacesWithSpaces(
81         screen0: List<Rect>? = null,
82         screen1: List<Rect>? = null,
83         screen2: List<Rect>? = null,
84         screen3: List<Rect>? = null,
85     ) {
86         listOf(screen0, screen1, screen2, screen3).let(this::setupWithSpaces)
87         mModelHelper.setupDefaultLayoutProvider(mLayoutBuilder)
88         mIdp.numRows = 5
89         mIdp.numColumns = mIdp.numRows
90         mModelHelper.loadModelSync()
91     }
92 
93     private fun setupWithSpaces(workspaceSpaces: List<List<Rect>?>) {
94         workspaceSpaces.forEachIndexed { screenId, spaces ->
95             if (spaces != null) {
96                 setupWorkspace(screenId, spaces)
97             }
98         }
99     }
100 
101     private fun setupWorkspace(screenId: Int, spaces: List<Rect>) {
102         val occupancy = GridOccupancy(mIdp.numColumns, mIdp.numRows)
103         occupancy.markCells(0, 0, mIdp.numColumns, mIdp.numRows, true)
104         spaces.forEach { spaceRect -> occupancy.markCells(spaceRect, false) }
105         mExistingScreens.add(screenId)
106         mScreenOccupancy.append(screenId, occupancy)
107         for (x in 0 until mIdp.numColumns) {
108             for (y in 0 until mIdp.numRows) {
109                 if (occupancy.cells[x][y]) {
110                     mLayoutBuilder.atWorkspace(x, y, screenId).putApp(TEST_PACKAGE, TEST_ACTIVITY)
111                 }
112             }
113         }
114     }
115 
116     fun getExistingItem() =
117         WorkspaceItemInfo().apply {
118             intent = AppInfo.makeLaunchIntent(ComponentName(TEST_PACKAGE, TEST_ACTIVITY))
119         }
120 
121     fun getNewItem(): WorkspaceItemInfo {
122         val itemPackage = UUID.randomUUID().toString()
123         return WorkspaceItemInfo().apply {
124             intent = AppInfo.makeLaunchIntent(ComponentName(itemPackage, itemPackage))
125         }
126     }
127 }
128 
129 data class NewItemSpace(val screenId: Int, val cellX: Int, val cellY: Int) {
toIntArraynull130     fun toIntArray() = intArrayOf(screenId, cellX, cellY)
131 
132     companion object {
133         fun fromIntArray(array: kotlin.IntArray) = NewItemSpace(array[0], array[1], array[2])
134     }
135 }
136