• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2023 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 androidx.test.ext.junit.runners.AndroidJUnit4
19 import androidx.test.filters.SmallTest
20 import com.android.launcher3.LauncherAppState
21 import com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_FOLDER
22 import com.android.launcher3.icons.BitmapInfo
23 import com.android.launcher3.icons.waitForUpdateHandlerToFinish
24 import com.android.launcher3.model.data.FolderInfo
25 import com.android.launcher3.model.data.WorkspaceItemInfo
26 import com.android.launcher3.util.Executors
27 import com.android.launcher3.util.LauncherLayoutBuilder
28 import com.android.launcher3.util.LauncherModelHelper
29 import com.android.launcher3.util.LauncherModelHelper.*
30 import com.android.launcher3.util.TestUtil
31 import com.google.common.truth.Truth.assertThat
32 import com.google.common.truth.Truth.assertWithMessage
33 import org.junit.After
34 import org.junit.Before
35 import org.junit.Test
36 import org.junit.runner.RunWith
37 
38 /** Tests to verify that folder icons are loaded with appropriate resolution */
39 @SmallTest
40 @RunWith(AndroidJUnit4::class)
41 class FolderIconLoadTest {
42 
43     private lateinit var modelHelper: LauncherModelHelper
44 
45     private val uniqueActivities =
46         listOf(
47             TEST_ACTIVITY,
48             TEST_ACTIVITY2,
49             TEST_ACTIVITY3,
50             TEST_ACTIVITY4,
51             TEST_ACTIVITY5,
52             TEST_ACTIVITY6,
53             TEST_ACTIVITY7,
54             TEST_ACTIVITY8,
55             TEST_ACTIVITY9,
56             TEST_ACTIVITY10,
57             TEST_ACTIVITY11,
58             TEST_ACTIVITY12,
59             TEST_ACTIVITY13,
60             TEST_ACTIVITY14,
61         )
62 
63     @Before
setUpnull64     fun setUp() {
65         modelHelper = LauncherModelHelper()
66     }
67 
68     @After
69     @Throws(Exception::class)
tearDownnull70     fun tearDown() {
71         modelHelper.destroy()
72         TestUtil.uninstallDummyApp()
73     }
74 
75     @Test
76     @Throws(Exception::class)
folderLoadedWithHighRes_2x2null77     fun folderLoadedWithHighRes_2x2() {
78         val items = setupAndLoadFolder(4)
79         assertThat(items.size).isEqualTo(4)
80         verifyHighRes(items, 0, 1, 2, 3)
81     }
82 
83     @Test
84     @Throws(Exception::class)
folderLoadedWithHighRes_3x2null85     fun folderLoadedWithHighRes_3x2() {
86         val items = setupAndLoadFolder(6)
87         assertThat(items.size).isEqualTo(6)
88         verifyHighRes(items, 0, 1, 3, 4)
89         verifyLowRes(items, 2, 5)
90     }
91 
92     @Test
93     @Throws(Exception::class)
folderLoadedWithHighRes_max_3x3null94     fun folderLoadedWithHighRes_max_3x3() {
95         val idp = LauncherAppState.getIDP(modelHelper.sandboxContext)
96         idp.numFolderColumns = intArrayOf(3, 3, 3, 3)
97         idp.numFolderRows = intArrayOf(3, 3, 3, 3)
98         recreateSupportedDeviceProfiles()
99 
100         val items = setupAndLoadFolder(14)
101         verifyHighRes(items, 0, 1, 3, 4)
102         verifyLowRes(items, 2, 5, 6, 7, 8, 9, 10, 11, 12, 13)
103     }
104 
105     @Test
106     @Throws(Exception::class)
folderLoadedWithHighRes_max_4x4null107     fun folderLoadedWithHighRes_max_4x4() {
108         val idp = LauncherAppState.getIDP(modelHelper.sandboxContext)
109         idp.numFolderColumns = intArrayOf(4, 4, 4, 4)
110         idp.numFolderRows = intArrayOf(4, 4, 4, 4)
111         recreateSupportedDeviceProfiles()
112 
113         val items = setupAndLoadFolder(14)
114         verifyHighRes(items, 0, 1, 4, 5)
115         verifyLowRes(items, 2, 3, 6, 7, 8, 9, 10, 11, 12, 13)
116     }
117 
118     @Test
119     @Throws(Exception::class)
folderLoadedWithHighRes_differentFolderConfigurationsnull120     fun folderLoadedWithHighRes_differentFolderConfigurations() {
121         val idp = LauncherAppState.getIDP(modelHelper.sandboxContext)
122         idp.numFolderColumns = intArrayOf(4, 3, 4, 4)
123         idp.numFolderRows = intArrayOf(4, 3, 4, 4)
124         recreateSupportedDeviceProfiles()
125 
126         val items = setupAndLoadFolder(14)
127         verifyHighRes(items, 0, 1, 3, 4, 5)
128         verifyLowRes(items, 2, 6, 7, 8, 9, 10, 11, 12, 13)
129     }
130 
131     @Throws(Exception::class)
setupAndLoadFoldernull132     private fun setupAndLoadFolder(itemCount: Int): ArrayList<WorkspaceItemInfo> {
133         val builder =
134             LauncherLayoutBuilder()
135                 .atWorkspace(0, 0, 1)
136                 .putFolder("Sample")
137                 .apply {
138                     for (i in 0..itemCount - 1) this.addApp(TEST_PACKAGE, uniqueActivities[i])
139                 }
140                 .build()
141 
142         modelHelper.setupDefaultLayoutProvider(builder)
143         modelHelper.loadModelSync()
144 
145         // The first load initializes the DB, load again so that icons are now used from the DB
146         // Wait for the icon cache to be updated and then reload
147         val app = LauncherAppState.getInstance(modelHelper.sandboxContext)
148         app.iconCache.waitForUpdateHandlerToFinish()
149 
150         TestUtil.runOnExecutorSync(Executors.MODEL_EXECUTOR) { app.iconCache.clearMemoryCache() }
151         // Reload again with correct icon state
152         app.model.forceReload()
153         modelHelper.loadModelSync()
154         val collections =
155             modelHelper.bgDataModel.itemsIdMap
156                 .filter { it.itemType == ITEM_TYPE_FOLDER }
157                 .map { it as FolderInfo }
158         assertThat(collections.size).isEqualTo(1)
159         assertThat(collections[0].getAppContents().size).isEqualTo(itemCount)
160         return collections[0].getAppContents()
161     }
162 
verifyHighResnull163     private fun verifyHighRes(items: ArrayList<WorkspaceItemInfo>, vararg indices: Int) {
164         for (index in indices) {
165             assertWithMessage("Index $index was not highRes")
166                 .that(items[index].bitmap.isNullOrLowRes)
167                 .isFalse()
168             assertWithMessage("Index $index was the default icon")
169                 .that(isDefaultIcon(items[index].bitmap))
170                 .isFalse()
171         }
172     }
173 
verifyLowResnull174     private fun verifyLowRes(items: ArrayList<WorkspaceItemInfo>, vararg indices: Int) {
175         for (index in indices) {
176             assertWithMessage("Index $index was not lowRes")
177                 .that(items[index].bitmap.isNullOrLowRes)
178                 .isTrue()
179             assertWithMessage("Index $index was the default icon")
180                 .that(isDefaultIcon(items[index].bitmap))
181                 .isFalse()
182         }
183     }
184 
isDefaultIconnull185     private fun isDefaultIcon(bitmap: BitmapInfo) =
186         LauncherAppState.getInstance(modelHelper.sandboxContext)
187             .iconCache
188             .isDefaultIcon(bitmap, modelHelper.sandboxContext.user)
189 
190     /** Recreate DeviceProfiles after changing InvariantDeviceProfile */
191     private fun recreateSupportedDeviceProfiles() {
192         LauncherAppState.getIDP(modelHelper.sandboxContext).supportedProfiles =
193             LauncherAppState.getIDP(modelHelper.sandboxContext).supportedProfiles.map {
194                 it.copy(modelHelper.sandboxContext)
195             }
196     }
197 }
198