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