• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
<lambda>null2  * Copyright (C) 2025 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 
17 package com.android.launcher3.util
18 
19 import android.content.ComponentName
20 import android.content.pm.LauncherApps
21 import android.graphics.Bitmap
22 import android.graphics.Bitmap.Config.ARGB_8888
23 import android.os.Process.myUserHandle
24 import android.platform.uiautomatorhelpers.DeviceHelpers.context
25 import android.view.View
26 import androidx.test.ext.junit.runners.AndroidJUnit4
27 import androidx.test.filters.SmallTest
28 import com.android.launcher3.BubbleTextView
29 import com.android.launcher3.graphics.PreloadIconDrawable
30 import com.android.launcher3.icons.BitmapInfo
31 import com.android.launcher3.icons.FastBitmapDrawable
32 import com.android.launcher3.icons.PlaceHolderIconDrawable
33 import com.android.launcher3.model.data.AppInfo
34 import com.android.launcher3.model.data.AppInfo.makeLaunchIntent
35 import com.android.launcher3.model.data.ItemInfo
36 import com.android.launcher3.model.data.WorkspaceItemInfo
37 import com.android.launcher3.pm.PackageInstallInfo
38 import com.android.launcher3.util.Executors.MAIN_EXECUTOR
39 import com.android.launcher3.util.LauncherBindableItemsContainer.ItemOperator
40 import com.android.launcher3.util.LauncherModelHelper.TEST_ACTIVITY
41 import com.android.launcher3.util.LauncherModelHelper.TEST_ACTIVITY2
42 import com.android.launcher3.util.LauncherModelHelper.TEST_ACTIVITY3
43 import com.android.launcher3.util.LauncherModelHelper.TEST_PACKAGE
44 import com.google.common.truth.Truth.assertThat
45 import org.junit.Test
46 import org.junit.runner.RunWith
47 
48 @SmallTest
49 @RunWith(AndroidJUnit4::class)
50 class LauncherBindableItemsContainerTest {
51 
52     private val icon1 by lazy { getLAI(TEST_ACTIVITY) }
53     private val icon2 by lazy { getLAI(TEST_ACTIVITY2) }
54     private val icon3 by lazy { getLAI(TEST_ACTIVITY3) }
55 
56     private val container = TestContainer()
57 
58     @Test
59     fun `icon bitmap is updated`() {
60         container.addIcon(icon1)
61         container.addIcon(icon2)
62         container.addIcon(icon3)
63 
64         assertThat(container.getAppIcon(icon1).icon)
65             .isInstanceOf(PlaceHolderIconDrawable::class.java)
66         assertThat(container.getAppIcon(icon2).icon)
67             .isInstanceOf(PlaceHolderIconDrawable::class.java)
68         assertThat(container.getAppIcon(icon3).icon)
69             .isInstanceOf(PlaceHolderIconDrawable::class.java)
70 
71         icon2.bitmap = BitmapInfo.fromBitmap(Bitmap.createBitmap(200, 200, ARGB_8888))
72         TestUtil.runOnExecutorSync(MAIN_EXECUTOR) {
73             container.updateContainerItems(setOf(icon2), container)
74         }
75 
76         assertThat(container.getAppIcon(icon1).icon)
77             .isInstanceOf(PlaceHolderIconDrawable::class.java)
78         assertThat(container.getAppIcon(icon3).icon)
79             .isInstanceOf(PlaceHolderIconDrawable::class.java)
80         assertThat(container.getAppIcon(icon2).icon)
81             .isNotInstanceOf(PlaceHolderIconDrawable::class.java)
82         assertThat(container.getAppIcon(icon2).icon).isInstanceOf(FastBitmapDrawable::class.java)
83     }
84 
85     @Test
86     fun `icon download progress updated`() {
87         container.addIcon(icon1)
88         container.addIcon(icon2)
89         assertThat(container.getAppIcon(icon1).icon)
90             .isInstanceOf(PlaceHolderIconDrawable::class.java)
91         assertThat(container.getAppIcon(icon2).icon)
92             .isInstanceOf(PlaceHolderIconDrawable::class.java)
93 
94         icon1.status = WorkspaceItemInfo.FLAG_RESTORED_ICON
95         icon1.bitmap = BitmapInfo.fromBitmap(Bitmap.createBitmap(200, 200, ARGB_8888))
96         icon1.setProgressLevel(30, PackageInstallInfo.STATUS_INSTALLING)
97         TestUtil.runOnExecutorSync(MAIN_EXECUTOR) {
98             container.updateContainerItems(setOf(icon1), container)
99         }
100 
101         assertThat(container.getAppIcon(icon2).icon)
102             .isInstanceOf(PlaceHolderIconDrawable::class.java)
103         assertThat(container.getAppIcon(icon1).icon).isInstanceOf(PreloadIconDrawable::class.java)
104         val oldIcon = container.getAppIcon(icon1).icon as PreloadIconDrawable
105         assertThat(oldIcon.level).isEqualTo(30)
106     }
107 
108     private fun getLAI(className: String): WorkspaceItemInfo =
109         AppInfo(
110                 context,
111                 context
112                     .getSystemService(LauncherApps::class.java)!!
113                     .resolveActivity(
114                         makeLaunchIntent(ComponentName(TEST_PACKAGE, className)),
115                         myUserHandle(),
116                     )!!,
117                 myUserHandle(),
118             )
119             .makeWorkspaceItem(context)
120 
121     class TestContainer : ActivityContextWrapper(context), LauncherBindableItemsContainer {
122 
123         val items = mutableMapOf<ItemInfo, View>()
124 
125         override fun mapOverItems(op: ItemOperator): View? =
126             items.firstNotNullOfOrNull { (item, view) ->
127                 if (op.evaluate(item, view)) view else null
128             }
129 
130         fun addIcon(info: WorkspaceItemInfo) {
131             val btv = BubbleTextView(this)
132             btv.applyFromWorkspaceItem(info)
133             items[info] = btv
134         }
135 
136         fun getAppIcon(info: WorkspaceItemInfo) = items[info] as BubbleTextView
137     }
138 }
139