blob: 4d953ff10bd82300c034ea7f7fae4f8ea53d9e7b [file] [log] [blame]
Joe Onorato0589f0f2010-02-08 13:44:00 -08001/*
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
Daniel Sandler325dc232013-06-05 22:57:57 -040017package com.android.launcher3;
Joe Onorato0589f0f2010-02-08 13:44:00 -080018
Chris Wren6d0dde02014-02-10 12:16:54 -050019import com.android.launcher3.backup.BackupProtos;
20
Winson Chungd83f5f42012-02-13 14:27:42 -080021import android.app.ActivityManager;
Joe Onorato0589f0f2010-02-08 13:44:00 -080022import android.content.ComponentName;
Winson Chungd83f5f42012-02-13 14:27:42 -080023import android.content.Context;
Joe Onorato0589f0f2010-02-08 13:44:00 -080024import android.content.Intent;
Michael Jurkadac85912012-05-18 15:04:49 -070025import android.content.pm.ActivityInfo;
Joe Onorato0589f0f2010-02-08 13:44:00 -080026import android.content.pm.PackageManager;
27import android.content.pm.ResolveInfo;
Michael Jurkac9a96192010-11-01 11:52:08 -070028import android.content.res.Resources;
Joe Onorato0589f0f2010-02-08 13:44:00 -080029import android.graphics.Bitmap;
Chris Wren6d0dde02014-02-10 12:16:54 -050030import android.graphics.BitmapFactory;
Romain Guya28fd3f2010-03-15 14:44:42 -070031import android.graphics.Canvas;
Chris Wren6d0dde02014-02-10 12:16:54 -050032import android.graphics.Paint;
Joe Onorato0589f0f2010-02-08 13:44:00 -080033import android.graphics.drawable.Drawable;
Kenny Guyed131872014-04-30 03:02:21 +010034import android.os.Build;
Chris Wren6d0dde02014-02-10 12:16:54 -050035import android.util.Log;
Joe Onorato0589f0f2010-02-08 13:44:00 -080036
Kenny Guyed131872014-04-30 03:02:21 +010037import com.android.launcher3.compat.LauncherActivityInfoCompat;
38import com.android.launcher3.compat.LauncherAppsCompat;
39import com.android.launcher3.compat.UserHandleCompat;
40import com.android.launcher3.compat.UserManagerCompat;
41
Chris Wren6d0dde02014-02-10 12:16:54 -050042import java.io.ByteArrayOutputStream;
43import java.io.File;
44import java.io.FileInputStream;
45import java.io.FileNotFoundException;
46import java.io.FileOutputStream;
47import java.io.IOException;
Joe Onorato0589f0f2010-02-08 13:44:00 -080048import java.util.HashMap;
Chris Wren6d0dde02014-02-10 12:16:54 -050049import java.util.HashSet;
Adam Cohenb6d33df2013-10-15 10:18:02 -070050import java.util.Iterator;
51import java.util.Map.Entry;
Joe Onorato0589f0f2010-02-08 13:44:00 -080052
53/**
54 * Cache of application icons. Icons can be made from any thread.
55 */
56public class IconCache {
Michael Jurka3a9fced2012-04-13 14:44:29 -070057 @SuppressWarnings("unused")
Joe Onorato0589f0f2010-02-08 13:44:00 -080058 private static final String TAG = "Launcher.IconCache";
59
60 private static final int INITIAL_ICON_CACHE_CAPACITY = 50;
Chris Wren6d0dde02014-02-10 12:16:54 -050061 private static final String RESOURCE_FILE_PREFIX = "icon_";
62
63 private static final boolean DEBUG = true;
Joe Onorato0589f0f2010-02-08 13:44:00 -080064
65 private static class CacheEntry {
66 public Bitmap icon;
67 public String title;
Joe Onorato0589f0f2010-02-08 13:44:00 -080068 }
69
Kenny Guyed131872014-04-30 03:02:21 +010070 private static class CacheKey {
71 public ComponentName componentName;
72 public UserHandleCompat user;
73
74 CacheKey(ComponentName componentName, UserHandleCompat user) {
75 this.componentName = componentName;
76 this.user = user;
77 }
78
79 @Override
80 public int hashCode() {
81 return componentName.hashCode() + user.hashCode();
82 }
83
84 @Override
85 public boolean equals(Object o) {
86 CacheKey other = (CacheKey) o;
87 return other.componentName.equals(componentName) && other.user.equals(user);
88 }
89 }
90
91 private final HashMap<UserHandleCompat, Bitmap> mDefaultIcons =
92 new HashMap<UserHandleCompat, Bitmap>();
Daniel Sandlercc8befa2013-06-11 14:45:48 -040093 private final Context mContext;
Romain Guya28fd3f2010-03-15 14:44:42 -070094 private final PackageManager mPackageManager;
Kenny Guyed131872014-04-30 03:02:21 +010095 private final UserManagerCompat mUserManager;
96 private final LauncherAppsCompat mLauncherApps;
97 private final HashMap<CacheKey, CacheEntry> mCache =
98 new HashMap<CacheKey, CacheEntry>(INITIAL_ICON_CACHE_CAPACITY);
Michael Jurkac9a96192010-11-01 11:52:08 -070099 private int mIconDpi;
Joe Onorato0589f0f2010-02-08 13:44:00 -0800100
Daniel Sandlercc8befa2013-06-11 14:45:48 -0400101 public IconCache(Context context) {
Winson Chungd83f5f42012-02-13 14:27:42 -0800102 ActivityManager activityManager =
103 (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
104
Joe Onorato0589f0f2010-02-08 13:44:00 -0800105 mContext = context;
106 mPackageManager = context.getPackageManager();
Kenny Guyed131872014-04-30 03:02:21 +0100107 mUserManager = UserManagerCompat.getInstance(mContext);
108 mLauncherApps = LauncherAppsCompat.getInstance(mContext);
Winson Chungd83f5f42012-02-13 14:27:42 -0800109 mIconDpi = activityManager.getLauncherLargeIconDensity();
110
Michael Jurkac9a96192010-11-01 11:52:08 -0700111 // need to set mIconDpi before getting default icon
Kenny Guyed131872014-04-30 03:02:21 +0100112 UserHandleCompat myUser = UserHandleCompat.myUserHandle();
113 mDefaultIcons.put(myUser, makeDefaultIcon(myUser));
Romain Guya28fd3f2010-03-15 14:44:42 -0700114 }
115
Michael Jurkac9a96192010-11-01 11:52:08 -0700116 public Drawable getFullResDefaultActivityIcon() {
117 return getFullResIcon(Resources.getSystem(),
Michael Jurka8b805b12012-04-18 14:23:14 -0700118 android.R.mipmap.sym_def_app_icon);
Michael Jurkac9a96192010-11-01 11:52:08 -0700119 }
120
Michael Jurka4842ed02011-07-07 15:33:20 -0700121 public Drawable getFullResIcon(Resources resources, int iconId) {
Michael Jurka721d9722011-08-03 11:49:59 -0700122 Drawable d;
Michael Jurka4842ed02011-07-07 15:33:20 -0700123 try {
Michael Jurka721d9722011-08-03 11:49:59 -0700124 d = resources.getDrawableForDensity(iconId, mIconDpi);
Michael Jurka4842ed02011-07-07 15:33:20 -0700125 } catch (Resources.NotFoundException e) {
Michael Jurka721d9722011-08-03 11:49:59 -0700126 d = null;
Michael Jurka4842ed02011-07-07 15:33:20 -0700127 }
Michael Jurka721d9722011-08-03 11:49:59 -0700128
129 return (d != null) ? d : getFullResDefaultActivityIcon();
Michael Jurkac9a96192010-11-01 11:52:08 -0700130 }
131
Winson Chung0b9fcf52011-10-31 13:05:15 -0700132 public Drawable getFullResIcon(String packageName, int iconId) {
Michael Jurkac9a96192010-11-01 11:52:08 -0700133 Resources resources;
134 try {
Winson Chung0b9fcf52011-10-31 13:05:15 -0700135 resources = mPackageManager.getResourcesForApplication(packageName);
136 } catch (PackageManager.NameNotFoundException e) {
137 resources = null;
138 }
139 if (resources != null) {
140 if (iconId != 0) {
141 return getFullResIcon(resources, iconId);
142 }
143 }
144 return getFullResDefaultActivityIcon();
145 }
146
147 public Drawable getFullResIcon(ResolveInfo info) {
Michael Jurkadac85912012-05-18 15:04:49 -0700148 return getFullResIcon(info.activityInfo);
149 }
150
151 public Drawable getFullResIcon(ActivityInfo info) {
152
Winson Chung0b9fcf52011-10-31 13:05:15 -0700153 Resources resources;
154 try {
155 resources = mPackageManager.getResourcesForApplication(
Michael Jurkadac85912012-05-18 15:04:49 -0700156 info.applicationInfo);
Michael Jurkac9a96192010-11-01 11:52:08 -0700157 } catch (PackageManager.NameNotFoundException e) {
158 resources = null;
159 }
160 if (resources != null) {
Michael Jurkadac85912012-05-18 15:04:49 -0700161 int iconId = info.getIconResource();
Michael Jurkac9a96192010-11-01 11:52:08 -0700162 if (iconId != 0) {
163 return getFullResIcon(resources, iconId);
164 }
165 }
Chris Wren6d0dde02014-02-10 12:16:54 -0500166
Michael Jurkac9a96192010-11-01 11:52:08 -0700167 return getFullResDefaultActivityIcon();
168 }
169
Kenny Guyed131872014-04-30 03:02:21 +0100170 private Bitmap makeDefaultIcon(UserHandleCompat user) {
171 Drawable unbadged = getFullResDefaultActivityIcon();
172 Drawable d = mUserManager.getBadgedDrawableForUser(unbadged, user);
Romain Guya28fd3f2010-03-15 14:44:42 -0700173 Bitmap b = Bitmap.createBitmap(Math.max(d.getIntrinsicWidth(), 1),
174 Math.max(d.getIntrinsicHeight(), 1),
175 Bitmap.Config.ARGB_8888);
176 Canvas c = new Canvas(b);
177 d.setBounds(0, 0, b.getWidth(), b.getHeight());
178 d.draw(c);
Adam Cohenaaf473c2011-08-03 12:02:47 -0700179 c.setBitmap(null);
Romain Guya28fd3f2010-03-15 14:44:42 -0700180 return b;
Joe Onorato0589f0f2010-02-08 13:44:00 -0800181 }
182
183 /**
184 * Remove any records for the supplied ComponentName.
185 */
Kenny Guyed131872014-04-30 03:02:21 +0100186 public void remove(ComponentName componentName, UserHandleCompat user) {
Joe Onorato0589f0f2010-02-08 13:44:00 -0800187 synchronized (mCache) {
Kenny Guyed131872014-04-30 03:02:21 +0100188 mCache.remove(new CacheKey(componentName, user));
Joe Onorato0589f0f2010-02-08 13:44:00 -0800189 }
190 }
191
192 /**
Chris Wren6d0dde02014-02-10 12:16:54 -0500193 * Remove any records for the supplied package name.
194 */
Kenny Guyed131872014-04-30 03:02:21 +0100195 public void remove(String packageName, UserHandleCompat user) {
196 HashSet<CacheKey> forDeletion = new HashSet<CacheKey>();
197 for (CacheKey key: mCache.keySet()) {
198 if (key.componentName.getPackageName().equals(packageName)
199 && key.user.equals(user)) {
200 forDeletion.add(key);
Chris Wren6d0dde02014-02-10 12:16:54 -0500201 }
202 }
Kenny Guyed131872014-04-30 03:02:21 +0100203 for (CacheKey condemned: forDeletion) {
204 mCache.remove(condemned);
Chris Wren6d0dde02014-02-10 12:16:54 -0500205 }
206 }
207
208 /**
Joe Onorato0589f0f2010-02-08 13:44:00 -0800209 * Empty out the cache.
210 */
211 public void flush() {
212 synchronized (mCache) {
213 mCache.clear();
214 }
215 }
216
217 /**
Winson Chunge5467dc2013-10-14 17:03:04 -0700218 * Empty out the cache that aren't of the correct grid size
219 */
220 public void flushInvalidIcons(DeviceProfile grid) {
221 synchronized (mCache) {
Kenny Guyed131872014-04-30 03:02:21 +0100222 Iterator<Entry<CacheKey, CacheEntry>> it = mCache.entrySet().iterator();
Adam Cohenb6d33df2013-10-15 10:18:02 -0700223 while (it.hasNext()) {
224 final CacheEntry e = it.next().getValue();
Winson Chung6e1c0d32013-10-25 15:24:24 -0700225 if (e.icon.getWidth() < grid.iconSizePx || e.icon.getHeight() < grid.iconSizePx) {
Adam Cohenb6d33df2013-10-15 10:18:02 -0700226 it.remove();
Winson Chunge5467dc2013-10-14 17:03:04 -0700227 }
228 }
229 }
230 }
231
232 /**
Joe Onorato0589f0f2010-02-08 13:44:00 -0800233 * Fill in "application" with the icon and label for "info."
234 */
Kenny Guyed131872014-04-30 03:02:21 +0100235 public void getTitleAndIcon(AppInfo application, LauncherActivityInfoCompat info,
Winson Chungc3eecff2011-07-11 17:44:15 -0700236 HashMap<Object, CharSequence> labelCache) {
Joe Onorato0589f0f2010-02-08 13:44:00 -0800237 synchronized (mCache) {
Kenny Guyed131872014-04-30 03:02:21 +0100238 CacheEntry entry = cacheLocked(application.componentName, info, labelCache,
239 info.getUser());
Joe Onorato0589f0f2010-02-08 13:44:00 -0800240
241 application.title = entry.title;
Joe Onorato0589f0f2010-02-08 13:44:00 -0800242 application.iconBitmap = entry.icon;
243 }
244 }
245
Kenny Guyed131872014-04-30 03:02:21 +0100246 public Bitmap getIcon(Intent intent, UserHandleCompat user) {
247 return getIcon(intent, null, user);
Chris Wren6d0dde02014-02-10 12:16:54 -0500248 }
249
Kenny Guyed131872014-04-30 03:02:21 +0100250 public Bitmap getIcon(Intent intent, String title, UserHandleCompat user) {
Joe Onoratofad1fb52010-05-04 12:12:41 -0700251 synchronized (mCache) {
Chris Wren075f9f52014-05-13 16:18:21 -0400252 LauncherActivityInfoCompat launcherActInfo =
Kenny Guyed131872014-04-30 03:02:21 +0100253 mLauncherApps.resolveActivity(intent, user);
Joe Onoratofad1fb52010-05-04 12:12:41 -0700254 ComponentName component = intent.getComponent();
Joe Onorato0589f0f2010-02-08 13:44:00 -0800255
Chris Wren075f9f52014-05-13 16:18:21 -0400256 try {
257 launcherActInfo.getComponentName();
258 } catch (NullPointerException e) {
259 // launcherActInfo is invalid: b/14891460
260 launcherActInfo = null;
261 }
262
263 // null info means not installed, but if we have a component from the intent then
264 // we should still look in the cache for restored app icons.
265 if (launcherActInfo == null && component == null) {
Kenny Guyed131872014-04-30 03:02:21 +0100266 return getDefaultIcon(user);
Joe Onoratofad1fb52010-05-04 12:12:41 -0700267 }
268
Kenny Guyed131872014-04-30 03:02:21 +0100269 CacheEntry entry = cacheLocked(component, launcherActInfo, null, user);
Chris Wren6d0dde02014-02-10 12:16:54 -0500270 if (title != null) {
271 entry.title = title;
272 }
Joe Onoratofad1fb52010-05-04 12:12:41 -0700273 return entry.icon;
Joe Onorato0589f0f2010-02-08 13:44:00 -0800274 }
Joe Onorato0589f0f2010-02-08 13:44:00 -0800275 }
276
Kenny Guyed131872014-04-30 03:02:21 +0100277 public Bitmap getDefaultIcon(UserHandleCompat user) {
278 if (!mDefaultIcons.containsKey(user)) {
279 mDefaultIcons.put(user, makeDefaultIcon(user));
280 }
281 return mDefaultIcons.get(user);
282 }
283
284 public Bitmap getIcon(ComponentName component, LauncherActivityInfoCompat info,
Winson Chungaac01e12011-08-17 10:37:13 -0700285 HashMap<Object, CharSequence> labelCache) {
Joe Onoratofad1fb52010-05-04 12:12:41 -0700286 synchronized (mCache) {
Kenny Guyed131872014-04-30 03:02:21 +0100287 if (info == null || component == null) {
Joe Onoratofad1fb52010-05-04 12:12:41 -0700288 return null;
289 }
Joe Onorato0589f0f2010-02-08 13:44:00 -0800290
Kenny Guyed131872014-04-30 03:02:21 +0100291 CacheEntry entry = cacheLocked(component, info, labelCache, info.getUser());
Joe Onoratofad1fb52010-05-04 12:12:41 -0700292 return entry.icon;
293 }
Joe Onorato0589f0f2010-02-08 13:44:00 -0800294 }
295
Kenny Guyed131872014-04-30 03:02:21 +0100296 public boolean isDefaultIcon(Bitmap icon, UserHandleCompat user) {
297 return mDefaultIcons.get(user) == icon;
Joe Onoratoddc9c1f2010-08-30 18:30:15 -0700298 }
299
Kenny Guyed131872014-04-30 03:02:21 +0100300 private CacheEntry cacheLocked(ComponentName componentName, LauncherActivityInfoCompat info,
301 HashMap<Object, CharSequence> labelCache, UserHandleCompat user) {
302 CacheKey cacheKey = new CacheKey(componentName, user);
303 CacheEntry entry = mCache.get(cacheKey);
Joe Onorato0589f0f2010-02-08 13:44:00 -0800304 if (entry == null) {
305 entry = new CacheEntry();
306
Kenny Guyed131872014-04-30 03:02:21 +0100307 mCache.put(cacheKey, entry);
Joe Onorato84f6a8d2010-02-12 17:53:35 -0500308
Chris Wren6d0dde02014-02-10 12:16:54 -0500309 if (info != null) {
Kenny Guyed131872014-04-30 03:02:21 +0100310 ComponentName labelKey = info.getComponentName();
311 if (labelCache != null && labelCache.containsKey(labelKey)) {
312 entry.title = labelCache.get(labelKey).toString();
Chris Wren6d0dde02014-02-10 12:16:54 -0500313 } else {
Kenny Guyed131872014-04-30 03:02:21 +0100314 entry.title = info.getLabel().toString();
Chris Wren6d0dde02014-02-10 12:16:54 -0500315 if (labelCache != null) {
Kenny Guyed131872014-04-30 03:02:21 +0100316 labelCache.put(labelKey, entry.title);
Chris Wren6d0dde02014-02-10 12:16:54 -0500317 }
318 }
Chris Wren6d0dde02014-02-10 12:16:54 -0500319
320 entry.icon = Utilities.createIconBitmap(
Kenny Guyed131872014-04-30 03:02:21 +0100321 info.getBadgedIcon(mIconDpi), mContext);
Winson Chungc3eecff2011-07-11 17:44:15 -0700322 } else {
Chris Wren6d0dde02014-02-10 12:16:54 -0500323 entry.title = "";
Kenny Guyed131872014-04-30 03:02:21 +0100324 Bitmap preloaded = getPreloadedIcon(componentName, user);
Chris Wren6d0dde02014-02-10 12:16:54 -0500325 if (preloaded != null) {
326 if (DEBUG) Log.d(TAG, "using preloaded icon for " +
327 componentName.toShortString());
328 entry.icon = preloaded;
329 } else {
330 if (DEBUG) Log.d(TAG, "using default icon for " +
331 componentName.toShortString());
Kenny Guyed131872014-04-30 03:02:21 +0100332 entry.icon = getDefaultIcon(user);
Winson Chungc3eecff2011-07-11 17:44:15 -0700333 }
334 }
Joe Onorato0589f0f2010-02-08 13:44:00 -0800335 }
336 return entry;
337 }
Daniel Sandler4e1cd232011-05-12 00:06:32 -0400338
339 public HashMap<ComponentName,Bitmap> getAllIcons() {
340 synchronized (mCache) {
341 HashMap<ComponentName,Bitmap> set = new HashMap<ComponentName,Bitmap>();
Kenny Guyed131872014-04-30 03:02:21 +0100342 for (CacheKey ck : mCache.keySet()) {
343 final CacheEntry e = mCache.get(ck);
344 set.put(ck.componentName, e.icon);
Daniel Sandler4e1cd232011-05-12 00:06:32 -0400345 }
346 return set;
347 }
348 }
Chris Wren6d0dde02014-02-10 12:16:54 -0500349
350 /**
351 * Pre-load an icon into the persistent cache.
352 *
353 * <P>Queries for a component that does not exist in the package manager
354 * will be answered by the persistent cache.
355 *
356 * @param context application context
357 * @param componentName the icon should be returned for this component
358 * @param icon the icon to be persisted
359 * @param dpi the native density of the icon
360 */
361 public static void preloadIcon(Context context, ComponentName componentName, Bitmap icon,
362 int dpi) {
363 // TODO rescale to the correct native DPI
364 try {
365 PackageManager packageManager = context.getPackageManager();
366 packageManager.getActivityIcon(componentName);
367 // component is present on the system already, do nothing
368 return;
369 } catch (PackageManager.NameNotFoundException e) {
370 // pass
371 }
372
373 final String key = componentName.flattenToString();
374 FileOutputStream resourceFile = null;
375 try {
376 resourceFile = context.openFileOutput(getResourceFilename(componentName),
377 Context.MODE_PRIVATE);
378 ByteArrayOutputStream os = new ByteArrayOutputStream();
379 if (icon.compress(android.graphics.Bitmap.CompressFormat.PNG, 75, os)) {
380 byte[] buffer = os.toByteArray();
381 resourceFile.write(buffer, 0, buffer.length);
382 } else {
383 Log.w(TAG, "failed to encode cache for " + key);
384 return;
385 }
386 } catch (FileNotFoundException e) {
387 Log.w(TAG, "failed to pre-load cache for " + key, e);
388 } catch (IOException e) {
389 Log.w(TAG, "failed to pre-load cache for " + key, e);
390 } finally {
391 if (resourceFile != null) {
392 try {
393 resourceFile.close();
394 } catch (IOException e) {
395 Log.d(TAG, "failed to save restored icon for: " + key, e);
396 }
397 }
398 }
399 }
400
401 /**
402 * Read a pre-loaded icon from the persistent icon cache.
403 *
404 * @param componentName the component that should own the icon
405 * @returns a bitmap if one is cached, or null.
406 */
Kenny Guyed131872014-04-30 03:02:21 +0100407 private Bitmap getPreloadedIcon(ComponentName componentName, UserHandleCompat user) {
Chris Wren6d0dde02014-02-10 12:16:54 -0500408 final String key = componentName.flattenToShortString();
409
Kenny Guyed131872014-04-30 03:02:21 +0100410 // We don't keep icons for other profiles in persistent cache.
411 if (!user.equals(UserHandleCompat.myUserHandle())) {
412 return null;
413 }
414
Chris Wren6d0dde02014-02-10 12:16:54 -0500415 if (DEBUG) Log.v(TAG, "looking for pre-load icon for " + key);
416 Bitmap icon = null;
417 FileInputStream resourceFile = null;
418 try {
419 resourceFile = mContext.openFileInput(getResourceFilename(componentName));
420 byte[] buffer = new byte[1024];
421 ByteArrayOutputStream bytes = new ByteArrayOutputStream();
422 int bytesRead = 0;
423 while(bytesRead >= 0) {
424 bytes.write(buffer, 0, bytesRead);
425 bytesRead = resourceFile.read(buffer, 0, buffer.length);
426 }
427 if (DEBUG) Log.d(TAG, "read " + bytes.size());
428 icon = BitmapFactory.decodeByteArray(bytes.toByteArray(), 0, bytes.size());
429 if (icon == null) {
430 Log.w(TAG, "failed to decode pre-load icon for " + key);
431 }
432 } catch (FileNotFoundException e) {
433 if (DEBUG) Log.d(TAG, "there is no restored icon for: " + key, e);
434 } catch (IOException e) {
435 Log.w(TAG, "failed to read pre-load icon for: " + key, e);
436 } finally {
437 if(resourceFile != null) {
438 try {
439 resourceFile.close();
440 } catch (IOException e) {
441 Log.d(TAG, "failed to manage pre-load icon file: " + key, e);
442 }
443 }
444 }
445
Chris Wren6d0dde02014-02-10 12:16:54 -0500446 return icon;
447 }
448
449 /**
450 * Remove a pre-loaded icon from the persistent icon cache.
451 *
452 * @param componentName the component that should own the icon
453 * @returns true on success
454 */
Kenny Guyed131872014-04-30 03:02:21 +0100455 public boolean deletePreloadedIcon(ComponentName componentName, UserHandleCompat user) {
456 // We don't keep icons for other profiles in persistent cache.
457 if (!user.equals(UserHandleCompat.myUserHandle())) {
458 return false;
459 }
Chris Wren6d0dde02014-02-10 12:16:54 -0500460 if (componentName == null) {
461 return false;
462 }
463 if (mCache.remove(componentName) != null) {
464 if (DEBUG) Log.d(TAG, "removed pre-loaded icon from the in-memory cache");
465 }
466 boolean success = mContext.deleteFile(getResourceFilename(componentName));
467 if (DEBUG && success) Log.d(TAG, "removed pre-loaded icon from persistent cache");
468
469 return success;
470 }
471
472 private static String getResourceFilename(ComponentName component) {
473 String resourceName = component.flattenToShortString();
474 String filename = resourceName.replace(File.separatorChar, '_');
475 return RESOURCE_FILE_PREFIX + filename;
476 }
Joe Onorato0589f0f2010-02-08 13:44:00 -0800477}