1 /* <lambda>null2 * Copyright (C) 2024 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.icons 18 19 import android.content.ComponentName 20 import android.content.Context 21 import android.content.pm.LauncherActivityInfo 22 import android.content.pm.LauncherApps 23 import android.content.pm.ShortcutInfo 24 import android.graphics.drawable.Drawable 25 import android.os.UserHandle 26 import android.util.Log 27 import com.android.launcher3.BuildConfig 28 import com.android.launcher3.LauncherAppState 29 import com.android.launcher3.icons.BaseIconFactory.IconOptions 30 import com.android.launcher3.icons.cache.BaseIconCache 31 import com.android.launcher3.icons.cache.CachingLogic 32 import com.android.launcher3.shortcuts.ShortcutKey 33 import com.android.launcher3.util.ApiWrapper 34 import com.android.launcher3.util.ApplicationInfoWrapper 35 import com.android.launcher3.util.PackageUserKey 36 import com.android.launcher3.util.Themes 37 38 /** Wrapper over ShortcutInfo to provide extra information related to ShortcutInfo */ 39 class CacheableShortcutInfo(val shortcutInfo: ShortcutInfo, val appInfo: ApplicationInfoWrapper) { 40 41 constructor( 42 info: ShortcutInfo, 43 ctx: Context, 44 ) : this(info, ApplicationInfoWrapper(ctx, info.getPackage(), info.userHandle)) 45 46 companion object { 47 private const val TAG = "CacheableShortcutInfo" 48 49 /** 50 * Similar to [LauncherApps.getShortcutIconDrawable] with additional Launcher specific 51 * checks 52 */ 53 @JvmStatic 54 fun getIcon(context: Context, shortcutInfo: ShortcutInfo, density: Int): Drawable? { 55 if (!BuildConfig.WIDGETS_ENABLED) { 56 return null 57 } 58 try { 59 return context 60 .getSystemService(LauncherApps::class.java) 61 .getShortcutIconDrawable(shortcutInfo, density) 62 } catch (e: Exception) { 63 Log.e(TAG, "Failed to get shortcut icon", e) 64 return null 65 } 66 } 67 68 /** 69 * Converts the provided list of Shortcuts to CacheableShortcuts by using the application 70 * info from the provided list of apps 71 */ 72 @JvmStatic 73 fun convertShortcutsToCacheableShortcuts( 74 shortcuts: List<ShortcutInfo>, 75 activities: List<LauncherActivityInfo>, 76 ): List<CacheableShortcutInfo> { 77 // Create a map of package to applicationInfo 78 val appMap = 79 activities.associateBy( 80 { PackageUserKey(it.componentName.packageName, it.user) }, 81 { it.applicationInfo }, 82 ) 83 84 return shortcuts.map { 85 CacheableShortcutInfo( 86 it, 87 ApplicationInfoWrapper(appMap[PackageUserKey(it.getPackage(), it.userHandle)]), 88 ) 89 } 90 } 91 } 92 } 93 94 /** Caching logic for CacheableShortcutInfo. */ 95 object CacheableShortcutCachingLogic : CachingLogic<CacheableShortcutInfo> { 96 getComponentnull97 override fun getComponent(info: CacheableShortcutInfo): ComponentName = 98 ShortcutKey.fromInfo(info.shortcutInfo).componentName 99 100 override fun getUser(info: CacheableShortcutInfo): UserHandle = info.shortcutInfo.userHandle 101 102 override fun getLabel(info: CacheableShortcutInfo): CharSequence? = info.shortcutInfo.shortLabel 103 104 override fun getApplicationInfo(info: CacheableShortcutInfo) = info.appInfo.getInfo() 105 106 override fun loadIcon(context: Context, cache: BaseIconCache, info: CacheableShortcutInfo) = 107 LauncherIcons.obtain(context).use { li -> 108 CacheableShortcutInfo.getIcon( 109 context, 110 info.shortcutInfo, 111 LauncherAppState.getIDP(context).fillResIconDpi, 112 ) 113 ?.let { d -> 114 li.createBadgedIconBitmap( 115 d, 116 IconOptions() 117 .setExtractedColor(Themes.getColorAccent(context)) 118 .setSourceHint( 119 getSourceHint(info, cache) 120 .copy( 121 isFileDrawable = 122 ApiWrapper.INSTANCE[context].isFileDrawable( 123 info.shortcutInfo 124 ) 125 ) 126 ), 127 ) 128 } ?: BitmapInfo.LOW_RES_INFO 129 } 130 getFreshnessIdentifiernull131 override fun getFreshnessIdentifier( 132 item: CacheableShortcutInfo, 133 provider: IconProvider, 134 ): String? = 135 // Manifest shortcuts get updated on every reboot. Don't include their change timestamp as 136 // it gets covered by the app's version 137 (if (item.shortcutInfo.isDeclaredInManifest) "" 138 else item.shortcutInfo.lastChangedTimestamp.toString()) + 139 "-" + 140 provider.getStateForApp(getApplicationInfo(item)) 141 } 142