<lambda>null1 package com.android.launcher3.model
2
3 import android.appwidget.AppWidgetManager
4 import android.content.ComponentName
5 import android.content.Intent
6 import android.content.pm.ApplicationInfo
7 import android.content.pm.LauncherActivityInfo
8 import android.database.sqlite.SQLiteDatabase
9 import android.os.Process
10 import android.os.UserHandle
11 import android.platform.test.annotations.DisableFlags
12 import android.platform.test.annotations.EnableFlags
13 import android.platform.test.flag.junit.SetFlagsRule
14 import android.provider.Settings
15 import androidx.test.ext.junit.runners.AndroidJUnit4
16 import androidx.test.filters.SmallTest
17 import com.android.dx.mockito.inline.extended.ExtendedMockito
18 import com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn
19 import com.android.launcher3.Flags
20 import com.android.launcher3.LauncherModel
21 import com.android.launcher3.LauncherModel.LoaderTransaction
22 import com.android.launcher3.LauncherPrefs
23 import com.android.launcher3.LauncherPrefs.Companion.IS_FIRST_LOAD_AFTER_RESTORE
24 import com.android.launcher3.LauncherPrefs.Companion.RESTORE_DEVICE
25 import com.android.launcher3.LauncherSettings.Favorites.CONTAINER_DESKTOP
26 import com.android.launcher3.LauncherSettings.Favorites.CONTAINER_HOTSEAT
27 import com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_APP_PAIR
28 import com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_FOLDER
29 import com.android.launcher3.LauncherSettings.Favorites.TABLE_NAME
30 import com.android.launcher3.dagger.LauncherAppComponent
31 import com.android.launcher3.dagger.LauncherAppSingleton
32 import com.android.launcher3.icons.IconCache
33 import com.android.launcher3.icons.cache.CachingLogic
34 import com.android.launcher3.icons.cache.IconCacheUpdateHandler
35 import com.android.launcher3.model.LoaderTask.LoaderTaskFactory
36 import com.android.launcher3.model.data.AppInfo
37 import com.android.launcher3.model.data.IconRequestInfo
38 import com.android.launcher3.model.data.WorkspaceItemInfo
39 import com.android.launcher3.pm.UserCache
40 import com.android.launcher3.provider.RestoreDbTask
41 import com.android.launcher3.ui.TestViewHelpers
42 import com.android.launcher3.util.AllModulesForTest
43 import com.android.launcher3.util.Executors.MODEL_EXECUTOR
44 import com.android.launcher3.util.LauncherModelHelper.SandboxModelContext
45 import com.android.launcher3.util.LooperIdleLock
46 import com.android.launcher3.util.ModelTestExtensions
47 import com.android.launcher3.util.TestUtil
48 import com.android.launcher3.util.UserIconInfo
49 import com.google.common.truth.Truth.assertThat
50 import dagger.BindsInstance
51 import dagger.Component
52 import java.util.concurrent.CountDownLatch
53 import junit.framework.Assert.assertEquals
54 import org.junit.After
55 import org.junit.Before
56 import org.junit.Rule
57 import org.junit.Test
58 import org.junit.runner.RunWith
59 import org.mockito.ArgumentCaptor
60 import org.mockito.Mock
61 import org.mockito.Mockito
62 import org.mockito.Mockito.times
63 import org.mockito.Mockito.`when`
64 import org.mockito.MockitoAnnotations
65 import org.mockito.MockitoSession
66 import org.mockito.Spy
67 import org.mockito.kotlin.any
68 import org.mockito.kotlin.anyOrNull
69 import org.mockito.kotlin.doAnswer
70 import org.mockito.kotlin.doReturn
71 import org.mockito.kotlin.mock
72 import org.mockito.kotlin.verify
73 import org.mockito.kotlin.whenever
74 import org.mockito.quality.Strictness
75
76 private const val INSERTION_STATEMENT_FILE = "databases/workspace_items.sql"
77
78 @SmallTest
79 @RunWith(AndroidJUnit4::class)
80 class LoaderTaskTest {
81 private var context = SandboxModelContext()
82 private val expectedBroadcastModel =
83 FirstScreenBroadcastModel(
84 installerPackage = "installerPackage",
85 pendingCollectionItems = mutableSetOf("pendingCollectionItem"),
86 pendingWidgetItems = mutableSetOf("pendingWidgetItem"),
87 pendingHotseatItems = mutableSetOf("pendingHotseatItem"),
88 pendingWorkspaceItems = mutableSetOf("pendingWorkspaceItem"),
89 installedHotseatItems = mutableSetOf("installedHotseatItem"),
90 installedWorkspaceItems = mutableSetOf("installedWorkspaceItem"),
91 firstScreenInstalledWidgets = mutableSetOf("installedFirstScreenWidget"),
92 secondaryScreenInstalledWidgets = mutableSetOf("installedSecondaryScreenWidget"),
93 )
94 private lateinit var mockitoSession: MockitoSession
95
96 @Mock private lateinit var bgAllAppsList: AllAppsList
97 @Mock private lateinit var modelDelegate: ModelDelegate
98 @Mock private lateinit var launcherModel: LauncherModel
99 @Mock private lateinit var iconCache: IconCache
100 @Mock private lateinit var userCache: UserCache
101 @Mock private lateinit var modelDbController: ModelDbController
102
103 @Mock private lateinit var launcherBinder: BaseLauncherBinder
104 @Mock private lateinit var transaction: LoaderTransaction
105 @Mock private lateinit var idleLock: LooperIdleLock
106 @Mock private lateinit var iconCacheUpdateHandler: IconCacheUpdateHandler
107
108 @Spy private var userManagerState: UserManagerState = UserManagerState()
109
110 @get:Rule val setFlagsRule = SetFlagsRule()
111
112 private val testComponent: TestComponent
113 get() = context.appComponent as TestComponent
114
115 private val bgDataModel: BgDataModel
116 get() = testComponent.getDataModel()
117
118 private val inMemoryDb: SQLiteDatabase by lazy {
119 ModelTestExtensions.createInMemoryDb(INSERTION_STATEMENT_FILE)
120 }
121
122 @Before
123 fun setup() {
124 MockitoAnnotations.initMocks(this)
125 mockitoSession =
126 ExtendedMockito.mockitoSession()
127 .strictness(Strictness.LENIENT)
128 .mockStatic(FirstScreenBroadcastHelper::class.java)
129 .startMocking()
130 doReturn(TestViewHelpers.findWidgetProvider(false))
131 .`when`(context.spyService(AppWidgetManager::class.java))
132 .getAppWidgetInfo(any())
133
134 `when`(launcherModel.beginLoader(any())).thenReturn(transaction)
135
136 `when`(launcherModel.modelDbController).thenReturn(modelDbController)
137 doAnswer {}.whenever(modelDbController).loadDefaultFavoritesIfNecessary()
138 doAnswer { i ->
139 inMemoryDb.query(
140 TABLE_NAME,
141 i.getArgument(0),
142 i.getArgument(1),
143 i.getArgument(2),
144 null,
145 null,
146 i.getArgument(3),
147 )
148 }
149 .whenever(modelDbController)
150 .query(anyOrNull(), anyOrNull(), anyOrNull(), anyOrNull())
151
152 `when`(launcherModel.modelDelegate).thenReturn(modelDelegate)
153 `when`(launcherBinder.newIdleLock(any())).thenReturn(idleLock)
154 `when`(idleLock.awaitLocked(1000)).thenReturn(false)
155 `when`(iconCache.getUpdateHandler()).thenReturn(iconCacheUpdateHandler)
156
157 context.initDaggerComponent(
158 DaggerLoaderTaskTest_TestComponent.builder()
159 .bindUserCache(userCache)
160 .bindIconCache(iconCache)
161 .bindLauncherModel(launcherModel)
162 .bindAllAppsList(bgAllAppsList)
163 )
164 context.appComponent.idp.apply {
165 numRows = 5
166 numColumns = 6
167 numDatabaseHotseatIcons = 5
168 }
169 TestUtil.grantWriteSecurePermission()
170 }
171
172 @After
173 fun tearDown() {
174 LauncherPrefs.get(context).removeSync(RESTORE_DEVICE)
175 LauncherPrefs.get(context).putSync(IS_FIRST_LOAD_AFTER_RESTORE.to(false))
176 inMemoryDb.close()
177 context.onDestroy()
178 mockitoSession.finishMocking()
179 }
180
181 @Test
182 fun loadsDataProperly() =
183 with(bgDataModel) {
184 val MAIN_HANDLE = Process.myUserHandle()
185 val mockUserHandles = arrayListOf<UserHandle>(MAIN_HANDLE)
186 `when`(userCache.userProfiles).thenReturn(mockUserHandles)
187 `when`(userCache.getUserInfo(MAIN_HANDLE)).thenReturn(UserIconInfo(MAIN_HANDLE, 1))
188 testComponent
189 .getLoaderTaskFactory()
190 .newLoaderTask(launcherBinder, userManagerState)
191 .runSyncOnBackgroundThread()
192 assertThat(
193 itemsIdMap
194 .filter {
195 it.container == CONTAINER_DESKTOP || it.container == CONTAINER_HOTSEAT
196 }
197 .size
198 )
199 .isAtLeast(32)
200 assertThat(itemsIdMap.filter { ModelUtils.WIDGET_FILTER.test(it) }.size).isAtLeast(7)
201 assertThat(
202 itemsIdMap
203 .filter {
204 it.itemType == ITEM_TYPE_FOLDER || it.itemType == ITEM_TYPE_APP_PAIR
205 }
206 .size
207 )
208 .isAtLeast(8)
209 assertThat(itemsIdMap.size()).isAtLeast(40)
210 }
211
212 @Test
213 fun bindsLoadedDataCorrectly() {
214 testComponent
215 .getLoaderTaskFactory()
216 .newLoaderTask(launcherBinder, userManagerState)
217 .runSyncOnBackgroundThread()
218
219 verify(launcherBinder).bindWorkspace(true, false)
220 verify(modelDelegate).workspaceLoadComplete()
221 verify(modelDelegate).loadAndBindAllAppsItems(any(), anyOrNull(), any())
222 verify(launcherBinder).bindAllApps()
223 verify(iconCacheUpdateHandler, times(4)).updateIcons(any(), any<CachingLogic<Any>>(), any())
224 verify(launcherBinder).bindDeepShortcuts()
225 verify(launcherBinder).bindWidgets()
226 verify(modelDelegate).loadAndBindOtherItems(anyOrNull())
227 verify(iconCacheUpdateHandler).finish()
228 verify(modelDelegate).modelLoadComplete()
229 verify(transaction).commit()
230 }
231
232 @Test
233 fun setsQuietModeFlagCorrectlyForWorkProfile() =
234 with(bgDataModel) {
235 setFlagsRule.enableFlags(Flags.FLAG_ENABLE_PRIVATE_SPACE)
236 val MAIN_HANDLE = Process.myUserHandle()
237 val mockUserHandles = arrayListOf<UserHandle>(MAIN_HANDLE)
238 `when`(userCache.userProfiles).thenReturn(mockUserHandles)
239 `when`(userManagerState?.isUserQuiet(MAIN_HANDLE)).thenReturn(true)
240 `when`(userCache.getUserInfo(MAIN_HANDLE)).thenReturn(UserIconInfo(MAIN_HANDLE, 1))
241
242 testComponent
243 .getLoaderTaskFactory()
244 .newLoaderTask(launcherBinder, userManagerState)
245 .runSyncOnBackgroundThread()
246
247 verify(bgAllAppsList)
248 .setFlags(BgDataModel.Callbacks.FLAG_WORK_PROFILE_QUIET_MODE_ENABLED, true)
249 verify(bgAllAppsList)
250 .setFlags(BgDataModel.Callbacks.FLAG_PRIVATE_PROFILE_QUIET_MODE_ENABLED, false)
251 verify(bgAllAppsList, Mockito.never())
252 .setFlags(BgDataModel.Callbacks.FLAG_QUIET_MODE_ENABLED, true)
253 }
254
255 @Test
256 fun setsQuietModeFlagCorrectlyForPrivateProfile() =
257 with(bgDataModel) {
258 setFlagsRule.enableFlags(Flags.FLAG_ENABLE_PRIVATE_SPACE)
259 val MAIN_HANDLE = Process.myUserHandle()
260 val mockUserHandles = arrayListOf<UserHandle>(MAIN_HANDLE)
261 `when`(userCache.userProfiles).thenReturn(mockUserHandles)
262 `when`(userManagerState?.isUserQuiet(MAIN_HANDLE)).thenReturn(true)
263 `when`(userCache.getUserInfo(MAIN_HANDLE)).thenReturn(UserIconInfo(MAIN_HANDLE, 3))
264
265 testComponent
266 .getLoaderTaskFactory()
267 .newLoaderTask(launcherBinder, userManagerState)
268 .runSyncOnBackgroundThread()
269
270 verify(bgAllAppsList)
271 .setFlags(BgDataModel.Callbacks.FLAG_WORK_PROFILE_QUIET_MODE_ENABLED, false)
272 verify(bgAllAppsList)
273 .setFlags(BgDataModel.Callbacks.FLAG_PRIVATE_PROFILE_QUIET_MODE_ENABLED, true)
274 verify(bgAllAppsList, Mockito.never())
275 .setFlags(BgDataModel.Callbacks.FLAG_QUIET_MODE_ENABLED, true)
276 }
277
278 @Test
279 @EnableFlags(Flags.FLAG_ENABLE_FIRST_SCREEN_BROADCAST_ARCHIVING_EXTRAS)
280 fun `When broadcast flag on and is restore and secure setting off then send new broadcast`() {
281 // Given
282 spyOn(context)
283 val spyContext = context
284 whenever(
285 FirstScreenBroadcastHelper.createModelsForFirstScreenBroadcast(
286 any(),
287 any(),
288 any(),
289 any(),
290 )
291 )
292 .thenReturn(listOf(expectedBroadcastModel))
293
294 whenever(
295 FirstScreenBroadcastHelper.sendBroadcastsForModels(
296 spyContext,
297 listOf(expectedBroadcastModel),
298 )
299 )
300 .thenCallRealMethod()
301
302 Settings.Secure.putInt(spyContext.contentResolver, "launcher_broadcast_installed_apps", 0)
303 RestoreDbTask.setPending(spyContext)
304
305 // When
306 testComponent
307 .getLoaderTaskFactory()
308 .newLoaderTask(launcherBinder, userManagerState)
309 .runSyncOnBackgroundThread()
310
311 // Then
312 val argumentCaptor = ArgumentCaptor.forClass(Intent::class.java)
313 verify(spyContext).sendBroadcast(argumentCaptor.capture())
314 val actualBroadcastIntent = argumentCaptor.value
315 assertEquals(expectedBroadcastModel.installerPackage, actualBroadcastIntent.`package`)
316 assertEquals(
317 ArrayList(expectedBroadcastModel.installedWorkspaceItems),
318 actualBroadcastIntent.getStringArrayListExtra("workspaceInstalledItems"),
319 )
320 assertEquals(
321 ArrayList(expectedBroadcastModel.installedHotseatItems),
322 actualBroadcastIntent.getStringArrayListExtra("hotseatInstalledItems"),
323 )
324 assertEquals(
325 ArrayList(
326 expectedBroadcastModel.firstScreenInstalledWidgets +
327 expectedBroadcastModel.secondaryScreenInstalledWidgets
328 ),
329 actualBroadcastIntent.getStringArrayListExtra("widgetInstalledItems"),
330 )
331 assertEquals(
332 ArrayList(expectedBroadcastModel.pendingCollectionItems),
333 actualBroadcastIntent.getStringArrayListExtra("folderItem"),
334 )
335 assertEquals(
336 ArrayList(expectedBroadcastModel.pendingWorkspaceItems),
337 actualBroadcastIntent.getStringArrayListExtra("workspaceItem"),
338 )
339 assertEquals(
340 ArrayList(expectedBroadcastModel.pendingHotseatItems),
341 actualBroadcastIntent.getStringArrayListExtra("hotseatItem"),
342 )
343 assertEquals(
344 ArrayList(expectedBroadcastModel.pendingWidgetItems),
345 actualBroadcastIntent.getStringArrayListExtra("widgetItem"),
346 )
347 }
348
349 @Test
350 @EnableFlags(Flags.FLAG_ENABLE_FIRST_SCREEN_BROADCAST_ARCHIVING_EXTRAS)
351 fun `When not a restore then installed item broadcast not sent`() {
352 // Given
353 spyOn(context)
354 val spyContext = context
355 whenever(
356 FirstScreenBroadcastHelper.createModelsForFirstScreenBroadcast(
357 any(),
358 any(),
359 any(),
360 any(),
361 )
362 )
363 .thenReturn(listOf(expectedBroadcastModel))
364
365 whenever(
366 FirstScreenBroadcastHelper.sendBroadcastsForModels(
367 spyContext,
368 listOf(expectedBroadcastModel),
369 )
370 )
371 .thenCallRealMethod()
372
373 Settings.Secure.putInt(spyContext.contentResolver, "launcher_broadcast_installed_apps", 0)
374
375 // When
376 testComponent
377 .getLoaderTaskFactory()
378 .newLoaderTask(launcherBinder, userManagerState)
379 .runSyncOnBackgroundThread()
380
381 // Then
382 verify(spyContext, times(0)).sendBroadcast(any())
383 }
384
385 @Test
386 @DisableFlags(Flags.FLAG_ENABLE_FIRST_SCREEN_BROADCAST_ARCHIVING_EXTRAS)
387 fun `When broadcast flag off then installed item broadcast not sent`() {
388 // Given
389 spyOn(context)
390 val spyContext = context
391 whenever(
392 FirstScreenBroadcastHelper.createModelsForFirstScreenBroadcast(
393 any(),
394 any(),
395 any(),
396 any(),
397 )
398 )
399 .thenReturn(listOf(expectedBroadcastModel))
400
401 whenever(
402 FirstScreenBroadcastHelper.sendBroadcastsForModels(
403 spyContext,
404 listOf(expectedBroadcastModel),
405 )
406 )
407 .thenCallRealMethod()
408
409 Settings.Secure.putInt(
410 spyContext.contentResolver,
411 "disable_launcher_broadcast_installed_apps",
412 0,
413 )
414 RestoreDbTask.setPending(spyContext)
415
416 // When
417 testComponent
418 .getLoaderTaskFactory()
419 .newLoaderTask(launcherBinder, userManagerState)
420 .runSyncOnBackgroundThread()
421
422 // Then
423 verify(spyContext, times(0)).sendBroadcast(any())
424 }
425
426 @Test
427 @EnableFlags(Flags.FLAG_ENABLE_FIRST_SCREEN_BROADCAST_ARCHIVING_EXTRAS)
428 fun `When failsafe secure setting on then installed item broadcast not sent`() {
429 // Given
430 spyOn(context)
431 val spyContext = context
432 whenever(
433 FirstScreenBroadcastHelper.createModelsForFirstScreenBroadcast(
434 any(),
435 any(),
436 any(),
437 any(),
438 )
439 )
440 .thenReturn(listOf(expectedBroadcastModel))
441
442 whenever(
443 FirstScreenBroadcastHelper.sendBroadcastsForModels(
444 spyContext,
445 listOf(expectedBroadcastModel),
446 )
447 )
448 .thenCallRealMethod()
449
450 Settings.Secure.putInt(
451 spyContext.contentResolver,
452 "disable_launcher_broadcast_installed_apps",
453 1,
454 )
455 RestoreDbTask.setPending(spyContext)
456
457 // When
458 testComponent
459 .getLoaderTaskFactory()
460 .newLoaderTask(launcherBinder, userManagerState)
461 .runSyncOnBackgroundThread()
462
463 // Then
464 verify(spyContext, times(0)).sendBroadcast(any())
465 }
466
467 @Test
468 @EnableFlags(Flags.FLAG_RESTORE_ARCHIVED_APP_ICONS_FROM_DB)
469 fun `When flag on and restore then archived AllApps icons on Workspace load from db`() {
470 // Given
471 val activityInfo: LauncherActivityInfo = mock()
472 val applicationInfo: ApplicationInfo = mock<ApplicationInfo>().apply { isArchived = true }
473 whenever(activityInfo.applicationInfo).thenReturn(applicationInfo)
474 val expectedIconBlob = byteArrayOf(0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08)
475 val expectedComponent = ComponentName("package", "class")
476 val workspaceIconRequests =
477 listOf(
478 IconRequestInfo<WorkspaceItemInfo>(
479 WorkspaceItemInfo().apply {
480 intent = Intent().apply { component = expectedComponent }
481 },
482 activityInfo,
483 expectedIconBlob,
484 false, /* useLowResIcon */
485 )
486 )
487 val expectedAppInfo = AppInfo().apply { componentName = expectedComponent }
488 // When
489 val loader =
490 testComponent.getLoaderTaskFactory().newLoaderTask(launcherBinder, userManagerState)
491 val actualIconRequest =
492 loader.getAppInfoIconRequestInfo(
493 expectedAppInfo,
494 activityInfo,
495 workspaceIconRequests,
496 /* isRestoreFromBackup */ true,
497 )
498 // Then
499 assertThat(actualIconRequest.iconBlob).isEqualTo(expectedIconBlob)
500 assertThat(actualIconRequest.itemInfo).isEqualTo(expectedAppInfo)
501 }
502
503 @Test
504 @EnableFlags(Flags.FLAG_RESTORE_ARCHIVED_APP_ICONS_FROM_DB)
505 fun `When flag on and not restore then archived AllApps icons do not load from db`() {
506 // Given
507 val activityInfo: LauncherActivityInfo = mock()
508 val applicationInfo: ApplicationInfo = mock<ApplicationInfo>().apply { isArchived = true }
509 whenever(activityInfo.applicationInfo).thenReturn(applicationInfo)
510 val expectedIconBlob = byteArrayOf(0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08)
511 val expectedComponent = ComponentName("package", "class")
512 val workspaceIconRequests =
513 listOf(
514 IconRequestInfo<WorkspaceItemInfo>(
515 WorkspaceItemInfo().apply {
516 intent = Intent().apply { component = expectedComponent }
517 },
518 activityInfo,
519 expectedIconBlob,
520 false, /* useLowResIcon */
521 )
522 )
523 val expectedAppInfo = AppInfo().apply { componentName = expectedComponent }
524 // When
525 val loader =
526 testComponent.getLoaderTaskFactory().newLoaderTask(launcherBinder, userManagerState)
527 val actualIconRequest =
528 loader.getAppInfoIconRequestInfo(
529 expectedAppInfo,
530 activityInfo,
531 workspaceIconRequests,
532 /* isRestoreFromBackup */ false,
533 )
534 // Then
535 assertThat(actualIconRequest.iconBlob).isNull()
536 assertThat(actualIconRequest.itemInfo).isEqualTo(expectedAppInfo)
537 }
538
539 @Test
540 @EnableFlags(Flags.FLAG_RESTORE_ARCHIVED_APP_ICONS_FROM_DB)
541 fun `When flag on and restore then unarchived AllApps icons not loaded from db`() {
542 // Given
543 val activityInfo: LauncherActivityInfo = mock()
544 val applicationInfo: ApplicationInfo = mock<ApplicationInfo>().apply { isArchived = false }
545 whenever(activityInfo.applicationInfo).thenReturn(applicationInfo)
546 val expectedIconBlob = byteArrayOf(0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08)
547 val expectedComponent = ComponentName("package", "class")
548 val workspaceIconRequests =
549 listOf(
550 IconRequestInfo<WorkspaceItemInfo>(
551 WorkspaceItemInfo().apply {
552 intent = Intent().apply { component = expectedComponent }
553 },
554 activityInfo,
555 expectedIconBlob,
556 false, /* useLowResIcon */
557 )
558 )
559 val expectedAppInfo = AppInfo().apply { componentName = expectedComponent }
560 // When
561 val loader =
562 testComponent.getLoaderTaskFactory().newLoaderTask(launcherBinder, userManagerState)
563 val actualIconRequest =
564 loader.getAppInfoIconRequestInfo(
565 expectedAppInfo,
566 activityInfo,
567 workspaceIconRequests,
568 /* isRestoreFromBackup */ true,
569 )
570 // Then
571 assertThat(actualIconRequest.iconBlob).isNull()
572 assertThat(actualIconRequest.itemInfo).isEqualTo(expectedAppInfo)
573 }
574
575 @Test
576 @EnableFlags(Flags.FLAG_RESTORE_ARCHIVED_APP_ICONS_FROM_DB)
577 fun `When flag on and restore then all apps icon not on workspace is not loaded from db`() {
578 // Given
579 val activityInfo: LauncherActivityInfo = mock()
580 val applicationInfo: ApplicationInfo = mock<ApplicationInfo>().apply { isArchived = true }
581 whenever(activityInfo.applicationInfo).thenReturn(applicationInfo)
582 val expectedIconBlob = byteArrayOf(0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08)
583 val expectedComponent = ComponentName("package", "class")
584 val workspaceIconRequests =
585 listOf(
586 IconRequestInfo<WorkspaceItemInfo>(
587 WorkspaceItemInfo().apply {
588 intent = Intent().apply { component = expectedComponent }
589 },
590 activityInfo,
591 expectedIconBlob,
592 false, /* useLowResIcon */
593 )
594 )
595 val expectedAppInfo =
596 AppInfo().apply { componentName = ComponentName("differentPkg", "differentClass") }
597 // When
598 val loader =
599 testComponent.getLoaderTaskFactory().newLoaderTask(launcherBinder, userManagerState)
600 val actualIconRequest =
601 loader.getAppInfoIconRequestInfo(
602 expectedAppInfo,
603 activityInfo,
604 workspaceIconRequests,
605 /* isRestoreFromBackup */ true,
606 )
607 // Then
608 assertThat(actualIconRequest.iconBlob).isNull()
609 assertThat(actualIconRequest.itemInfo).isEqualTo(expectedAppInfo)
610 }
611
612 @Test
613 @DisableFlags(Flags.FLAG_RESTORE_ARCHIVED_APP_ICONS_FROM_DB)
614 fun `When flag off and restore then archived AllApps icons not loaded from db`() {
615 // Given
616 val activityInfo: LauncherActivityInfo = mock()
617 val applicationInfo: ApplicationInfo = mock<ApplicationInfo>().apply { isArchived = true }
618 whenever(activityInfo.applicationInfo).thenReturn(applicationInfo)
619 val expectedIconBlob = byteArrayOf(0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08)
620 val workspaceIconRequests =
621 listOf(
622 IconRequestInfo<WorkspaceItemInfo>(
623 WorkspaceItemInfo(),
624 activityInfo,
625 expectedIconBlob,
626 false, /* useLowResIcon */
627 )
628 )
629 val expectedAppInfo = AppInfo()
630 // When
631 val loader =
632 testComponent.getLoaderTaskFactory().newLoaderTask(launcherBinder, userManagerState)
633 val actualIconRequest =
634 loader.getAppInfoIconRequestInfo(
635 expectedAppInfo,
636 activityInfo,
637 workspaceIconRequests,
638 /* isRestoreFromBackup */ true,
639 )
640 // Then
641 assertThat(actualIconRequest.iconBlob).isNull()
642 assertThat(actualIconRequest.itemInfo).isEqualTo(expectedAppInfo)
643 }
644
645 @LauncherAppSingleton
646 @Component(modules = [AllModulesForTest::class])
647 interface TestComponent : LauncherAppComponent {
648
649 fun getLoaderTaskFactory(): LoaderTaskFactory
650
651 fun getDataModel(): BgDataModel
652
653 @Component.Builder
654 interface Builder : LauncherAppComponent.Builder {
655 @BindsInstance fun bindUserCache(userCache: UserCache): Builder
656
657 @BindsInstance fun bindLauncherModel(model: LauncherModel): Builder
658
659 @BindsInstance fun bindIconCache(iconCache: IconCache): Builder
660
661 @BindsInstance fun bindAllAppsList(list: AllAppsList): Builder
662
663 override fun build(): TestComponent
664 }
665 }
666 }
667
runSyncOnBackgroundThreadnull668 private fun LoaderTask.runSyncOnBackgroundThread() {
669 val latch = CountDownLatch(1)
670 MODEL_EXECUTOR.execute {
671 run()
672 latch.countDown()
673 }
674 latch.await()
675 }
676