1/* 2 * Copyright (C) 2008 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 17package com.android.launcher2; 18 19import android.app.ActivityManager; 20import android.content.ComponentName; 21import android.content.Context; 22import android.content.Intent; 23import android.content.pm.ActivityInfo; 24import android.content.pm.LauncherActivityInfo; 25import android.content.pm.LauncherApps; 26import android.content.pm.PackageManager; 27import android.content.pm.ResolveInfo; 28import android.content.res.Resources; 29import android.graphics.Bitmap; 30import android.graphics.Canvas; 31import android.graphics.drawable.Drawable; 32import android.os.UserHandle; 33 34import java.util.HashMap; 35 36/** 37 * Cache of application icons. Icons can be made from any thread. 38 */ 39public class IconCache { 40 @SuppressWarnings("unused") 41 private static final String TAG = "Launcher.IconCache"; 42 43 private static final int INITIAL_ICON_CACHE_CAPACITY = 50; 44 45 private static class CacheEntry { 46 public Bitmap icon; 47 public String title; 48 public CharSequence contentDescription; 49 } 50 51 private static class CacheKey { 52 public ComponentName componentName; 53 public UserHandle user; 54 55 CacheKey(ComponentName componentName, UserHandle user) { 56 this.componentName = componentName; 57 this.user = user; 58 } 59 60 @Override 61 public int hashCode() { 62 return componentName.hashCode() + user.hashCode(); 63 } 64 65 @Override 66 public boolean equals(Object o) { 67 CacheKey other = (CacheKey) o; 68 return other.componentName.equals(componentName) && other.user.equals(user); 69 } 70 } 71 72 private final Bitmap mDefaultIcon; 73 private final LauncherApplication mContext; 74 private final PackageManager mPackageManager; 75 private final HashMap<CacheKey, CacheEntry> mCache = 76 new HashMap<CacheKey, CacheEntry>(INITIAL_ICON_CACHE_CAPACITY); 77 private int mIconDpi; 78 79 public IconCache(LauncherApplication context) { 80 ActivityManager activityManager = 81 (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); 82 83 mContext = context; 84 mPackageManager = context.getPackageManager(); 85 mIconDpi = activityManager.getLauncherLargeIconDensity(); 86 // need to set mIconDpi before getting default icon 87 mDefaultIcon = makeDefaultIcon(); 88 } 89 90 public Drawable getFullResDefaultActivityIcon() { 91 return getFullResIcon(Resources.getSystem(), 92 android.R.mipmap.sym_def_app_icon, android.os.Process.myUserHandle()); 93 } 94 95 public Drawable getFullResIcon(Resources resources, int iconId, UserHandle user) { 96 Drawable d; 97 try { 98 d = resources.getDrawableForDensity(iconId, mIconDpi); 99 } catch (Resources.NotFoundException e) { 100 d = null; 101 } 102 103 if (d == null) { 104 d = getFullResDefaultActivityIcon(); 105 } 106 return mPackageManager.getUserBadgedIcon(d, user); 107 } 108 109 public Drawable getFullResIcon(String packageName, int iconId, UserHandle user) { 110 Resources resources; 111 try { 112 // TODO: Check if this needs to use the user param if we support 113 // shortcuts/widgets from other profiles. It won't work as is 114 // for packages that are only available in a different user profile. 115 resources = mPackageManager.getResourcesForApplication(packageName); 116 } catch (PackageManager.NameNotFoundException e) { 117 resources = null; 118 } 119 if (resources != null) { 120 if (iconId != 0) { 121 return getFullResIcon(resources, iconId, user); 122 } 123 } 124 return getFullResDefaultActivityIcon(); 125 } 126 127 public Drawable getFullResIcon(ResolveInfo info, UserHandle user) { 128 return getFullResIcon(info.activityInfo, user); 129 } 130 131 public Drawable getFullResIcon(ActivityInfo info, UserHandle user) { 132 Resources resources; 133 try { 134 resources = mPackageManager.getResourcesForApplication( 135 info.applicationInfo); 136 } catch (PackageManager.NameNotFoundException e) { 137 resources = null; 138 } 139 if (resources != null) { 140 int iconId = info.getIconResource(); 141 if (iconId != 0) { 142 return getFullResIcon(resources, iconId, user); 143 } 144 } 145 return getFullResDefaultActivityIcon(); 146 } 147 148 private Bitmap makeDefaultIcon() { 149 Drawable d = getFullResDefaultActivityIcon(); 150 Bitmap b = Bitmap.createBitmap(Math.max(d.getIntrinsicWidth(), 1), 151 Math.max(d.getIntrinsicHeight(), 1), 152 Bitmap.Config.ARGB_8888); 153 Canvas c = new Canvas(b); 154 d.setBounds(0, 0, b.getWidth(), b.getHeight()); 155 d.draw(c); 156 c.setBitmap(null); 157 return b; 158 } 159 160 /** 161 * Remove any records for the supplied ComponentName. 162 */ 163 public void remove(ComponentName componentName, UserHandle user) { 164 synchronized (mCache) { 165 mCache.remove(new CacheKey(componentName, user)); 166 } 167 } 168 169 /** 170 * Empty out the cache. 171 */ 172 public void flush() { 173 synchronized (mCache) { 174 mCache.clear(); 175 } 176 } 177 178 /** 179 * Fill in "application" with the icon and label for "info." 180 */ 181 public void getTitleAndIcon(ApplicationInfo application, LauncherActivityInfo info, 182 HashMap<Object, CharSequence> labelCache) { 183 synchronized (mCache) { 184 CacheEntry entry = cacheLocked(application.componentName, info, labelCache, 185 info.getUser()); 186 187 application.title = entry.title; 188 application.iconBitmap = entry.icon; 189 application.contentDescription = entry.contentDescription; 190 } 191 } 192 193 public Bitmap getIcon(Intent intent, UserHandle user) { 194 synchronized (mCache) { 195 LauncherApps launcherApps = (LauncherApps) 196 mContext.getSystemService(Context.LAUNCHER_APPS_SERVICE); 197 final LauncherActivityInfo launcherActInfo = 198 launcherApps.resolveActivity(intent, user); 199 ComponentName component = intent.getComponent(); 200 201 if (launcherActInfo == null || component == null) { 202 return mDefaultIcon; 203 } 204 205 CacheEntry entry = cacheLocked(component, launcherActInfo, null, user); 206 return entry.icon; 207 } 208 } 209 210 public Bitmap getIcon(ComponentName component, LauncherActivityInfo info, 211 HashMap<Object, CharSequence> labelCache) { 212 synchronized (mCache) { 213 if (info == null || component == null) { 214 return null; 215 } 216 217 CacheEntry entry = cacheLocked(component, info, labelCache, info.getUser()); 218 return entry.icon; 219 } 220 } 221 222 public boolean isDefaultIcon(Bitmap icon) { 223 return mDefaultIcon == icon; 224 } 225 226 private CacheEntry cacheLocked(ComponentName componentName, LauncherActivityInfo info, 227 HashMap<Object, CharSequence> labelCache, UserHandle user) { 228 CacheKey cacheKey = new CacheKey(componentName, user); 229 CacheEntry entry = mCache.get(cacheKey); 230 if (entry == null) { 231 entry = new CacheEntry(); 232 233 mCache.put(cacheKey, entry); 234 235 ComponentName key = info.getComponentName(); 236 if (labelCache != null && labelCache.containsKey(key)) { 237 entry.title = labelCache.get(key).toString(); 238 } else { 239 entry.title = info.getLabel().toString(); 240 if (labelCache != null) { 241 labelCache.put(key, entry.title); 242 } 243 } 244 if (entry.title == null) { 245 entry.title = info.getComponentName().getShortClassName(); 246 } 247 entry.contentDescription = mPackageManager.getUserBadgedLabel(entry.title, user); 248 entry.icon = Utilities.createIconBitmap(info.getBadgedIcon(mIconDpi), mContext); 249 } 250 return entry; 251 } 252} 253