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 17 package com.android.launcher2; 18 19 import android.content.ComponentName; 20 import android.content.Intent; 21 import android.content.pm.PackageManager; 22 import android.content.pm.ResolveInfo; 23 import android.content.res.Resources; 24 import android.graphics.Bitmap; 25 import android.graphics.Canvas; 26 import android.graphics.drawable.Drawable; 27 import android.util.DisplayMetrics; 28 29 import java.util.HashMap; 30 31 /** 32 * Cache of application icons. Icons can be made from any thread. 33 */ 34 public class IconCache { 35 private static final String TAG = "Launcher.IconCache"; 36 37 private static final int INITIAL_ICON_CACHE_CAPACITY = 50; 38 39 private static class CacheEntry { 40 public Bitmap icon; 41 public String title; 42 } 43 44 private final Bitmap mDefaultIcon; 45 private final LauncherApplication mContext; 46 private final PackageManager mPackageManager; 47 private final HashMap<ComponentName, CacheEntry> mCache = 48 new HashMap<ComponentName, CacheEntry>(INITIAL_ICON_CACHE_CAPACITY); 49 private int mIconDpi; 50 51 public IconCache(LauncherApplication context) { 52 mContext = context; 53 mPackageManager = context.getPackageManager(); 54 int density = context.getResources().getDisplayMetrics().densityDpi; 55 if (LauncherApplication.isScreenLarge()) { 56 if (density == DisplayMetrics.DENSITY_LOW) { 57 mIconDpi = DisplayMetrics.DENSITY_MEDIUM; 58 } else if (density == DisplayMetrics.DENSITY_MEDIUM) { 59 mIconDpi = DisplayMetrics.DENSITY_HIGH; 60 } else if (density == DisplayMetrics.DENSITY_HIGH) { 61 mIconDpi = DisplayMetrics.DENSITY_XHIGH; 62 } else if (density == DisplayMetrics.DENSITY_XHIGH) { 63 // We'll need to use a denser icon, or some sort of a mipmap 64 mIconDpi = DisplayMetrics.DENSITY_XHIGH; 65 } 66 } else { 67 mIconDpi = context.getResources().getDisplayMetrics().densityDpi; 68 } 69 // need to set mIconDpi before getting default icon 70 mDefaultIcon = makeDefaultIcon(); 71 } 72 73 public Drawable getFullResDefaultActivityIcon() { 74 return getFullResIcon(Resources.getSystem(), 75 com.android.internal.R.mipmap.sym_def_app_icon); 76 } 77 78 public Drawable getFullResIcon(Resources resources, int iconId) { 79 Drawable d; 80 try { 81 d = resources.getDrawableForDensity(iconId, mIconDpi); 82 } catch (Resources.NotFoundException e) { 83 d = null; 84 } 85 86 return (d != null) ? d : getFullResDefaultActivityIcon(); 87 } 88 89 public Drawable getFullResIcon(String packageName, int iconId) { 90 Resources resources; 91 try { 92 resources = mPackageManager.getResourcesForApplication(packageName); 93 } catch (PackageManager.NameNotFoundException e) { 94 resources = null; 95 } 96 if (resources != null) { 97 if (iconId != 0) { 98 return getFullResIcon(resources, iconId); 99 } 100 } 101 return getFullResDefaultActivityIcon(); 102 } 103 104 public Drawable getFullResIcon(ResolveInfo info) { 105 Resources resources; 106 try { 107 resources = mPackageManager.getResourcesForApplication( 108 info.activityInfo.applicationInfo); 109 } catch (PackageManager.NameNotFoundException e) { 110 resources = null; 111 } 112 if (resources != null) { 113 int iconId = info.activityInfo.getIconResource(); 114 if (iconId != 0) { 115 return getFullResIcon(resources, iconId); 116 } 117 } 118 return getFullResDefaultActivityIcon(); 119 } 120 121 private Bitmap makeDefaultIcon() { 122 Drawable d = getFullResDefaultActivityIcon(); 123 Bitmap b = Bitmap.createBitmap(Math.max(d.getIntrinsicWidth(), 1), 124 Math.max(d.getIntrinsicHeight(), 1), 125 Bitmap.Config.ARGB_8888); 126 Canvas c = new Canvas(b); 127 d.setBounds(0, 0, b.getWidth(), b.getHeight()); 128 d.draw(c); 129 c.setBitmap(null); 130 return b; 131 } 132 133 /** 134 * Remove any records for the supplied ComponentName. 135 */ 136 public void remove(ComponentName componentName) { 137 synchronized (mCache) { 138 mCache.remove(componentName); 139 } 140 } 141 142 /** 143 * Empty out the cache. 144 */ 145 public void flush() { 146 synchronized (mCache) { 147 mCache.clear(); 148 } 149 } 150 151 /** 152 * Fill in "application" with the icon and label for "info." 153 */ 154 public void getTitleAndIcon(ApplicationInfo application, ResolveInfo info, 155 HashMap<Object, CharSequence> labelCache) { 156 synchronized (mCache) { 157 CacheEntry entry = cacheLocked(application.componentName, info, labelCache); 158 159 application.title = entry.title; 160 application.iconBitmap = entry.icon; 161 } 162 } 163 164 public Bitmap getIcon(Intent intent) { 165 synchronized (mCache) { 166 final ResolveInfo resolveInfo = mPackageManager.resolveActivity(intent, 0); 167 ComponentName component = intent.getComponent(); 168 169 if (resolveInfo == null || component == null) { 170 return mDefaultIcon; 171 } 172 173 CacheEntry entry = cacheLocked(component, resolveInfo, null); 174 return entry.icon; 175 } 176 } 177 178 public Bitmap getIcon(ComponentName component, ResolveInfo resolveInfo, 179 HashMap<Object, CharSequence> labelCache) { 180 synchronized (mCache) { 181 if (resolveInfo == null || component == null) { 182 return null; 183 } 184 185 CacheEntry entry = cacheLocked(component, resolveInfo, labelCache); 186 return entry.icon; 187 } 188 } 189 190 public boolean isDefaultIcon(Bitmap icon) { 191 return mDefaultIcon == icon; 192 } 193 194 private CacheEntry cacheLocked(ComponentName componentName, ResolveInfo info, 195 HashMap<Object, CharSequence> labelCache) { 196 CacheEntry entry = mCache.get(componentName); 197 if (entry == null) { 198 entry = new CacheEntry(); 199 200 mCache.put(componentName, entry); 201 202 ComponentName key = LauncherModel.getComponentNameFromResolveInfo(info); 203 if (labelCache != null && labelCache.containsKey(key)) { 204 entry.title = labelCache.get(key).toString(); 205 } else { 206 entry.title = info.loadLabel(mPackageManager).toString(); 207 if (labelCache != null) { 208 labelCache.put(key, entry.title); 209 } 210 } 211 if (entry.title == null) { 212 entry.title = info.activityInfo.name; 213 } 214 215 entry.icon = Utilities.createIconBitmap( 216 getFullResIcon(info), mContext); 217 } 218 return entry; 219 } 220 221 public HashMap<ComponentName,Bitmap> getAllIcons() { 222 synchronized (mCache) { 223 HashMap<ComponentName,Bitmap> set = new HashMap<ComponentName,Bitmap>(); 224 for (ComponentName cn : mCache.keySet()) { 225 final CacheEntry e = mCache.get(cn); 226 set.put(cn, e.icon); 227 } 228 return set; 229 } 230 } 231 } 232