Home | History | Annotate | Download | only in launcher3
      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.launcher3;
     18 
     19 import android.app.ActivityManager;
     20 import android.content.ComponentName;
     21 import android.content.Context;
     22 import android.content.Intent;
     23 import android.content.pm.ActivityInfo;
     24 import android.content.pm.PackageManager;
     25 import android.content.pm.ResolveInfo;
     26 import android.content.res.Resources;
     27 import android.graphics.Bitmap;
     28 import android.graphics.Canvas;
     29 import android.graphics.drawable.Drawable;
     30 
     31 import java.util.HashMap;
     32 import java.util.Iterator;
     33 import java.util.Map.Entry;
     34 
     35 /**
     36  * Cache of application icons.  Icons can be made from any thread.
     37  */
     38 public class IconCache {
     39     @SuppressWarnings("unused")
     40     private static final String TAG = "Launcher.IconCache";
     41 
     42     private static final int INITIAL_ICON_CACHE_CAPACITY = 50;
     43 
     44     private static class CacheEntry {
     45         public Bitmap icon;
     46         public String title;
     47     }
     48 
     49     private final Bitmap mDefaultIcon;
     50     private final Context mContext;
     51     private final PackageManager mPackageManager;
     52     private final HashMap<ComponentName, CacheEntry> mCache =
     53             new HashMap<ComponentName, CacheEntry>(INITIAL_ICON_CACHE_CAPACITY);
     54     private int mIconDpi;
     55 
     56     public IconCache(Context context) {
     57         ActivityManager activityManager =
     58                 (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
     59 
     60         mContext = context;
     61         mPackageManager = context.getPackageManager();
     62         mIconDpi = activityManager.getLauncherLargeIconDensity();
     63 
     64         // need to set mIconDpi before getting default icon
     65         mDefaultIcon = makeDefaultIcon();
     66     }
     67 
     68     public Drawable getFullResDefaultActivityIcon() {
     69         return getFullResIcon(Resources.getSystem(),
     70                 android.R.mipmap.sym_def_app_icon);
     71     }
     72 
     73     public Drawable getFullResIcon(Resources resources, int iconId) {
     74         Drawable d;
     75         try {
     76             d = resources.getDrawableForDensity(iconId, mIconDpi);
     77         } catch (Resources.NotFoundException e) {
     78             d = null;
     79         }
     80 
     81         return (d != null) ? d : getFullResDefaultActivityIcon();
     82     }
     83 
     84     public Drawable getFullResIcon(String packageName, int iconId) {
     85         Resources resources;
     86         try {
     87             resources = mPackageManager.getResourcesForApplication(packageName);
     88         } catch (PackageManager.NameNotFoundException e) {
     89             resources = null;
     90         }
     91         if (resources != null) {
     92             if (iconId != 0) {
     93                 return getFullResIcon(resources, iconId);
     94             }
     95         }
     96         return getFullResDefaultActivityIcon();
     97     }
     98 
     99     public Drawable getFullResIcon(ResolveInfo info) {
    100         return getFullResIcon(info.activityInfo);
    101     }
    102 
    103     public Drawable getFullResIcon(ActivityInfo info) {
    104 
    105         Resources resources;
    106         try {
    107             resources = mPackageManager.getResourcesForApplication(
    108                     info.applicationInfo);
    109         } catch (PackageManager.NameNotFoundException e) {
    110             resources = null;
    111         }
    112         if (resources != null) {
    113             int iconId = info.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      * Empty out the cache that aren't of the correct grid size
    153      */
    154     public void flushInvalidIcons(DeviceProfile grid) {
    155         synchronized (mCache) {
    156             Iterator<Entry<ComponentName, CacheEntry>> it = mCache.entrySet().iterator();
    157             while (it.hasNext()) {
    158                 final CacheEntry e = it.next().getValue();
    159                 if (e.icon.getWidth() != grid.iconSizePx || e.icon.getHeight() != grid.iconSizePx) {
    160                     it.remove();
    161                 }
    162             }
    163         }
    164     }
    165 
    166     /**
    167      * Fill in "application" with the icon and label for "info."
    168      */
    169     public void getTitleAndIcon(AppInfo application, ResolveInfo info,
    170             HashMap<Object, CharSequence> labelCache) {
    171         synchronized (mCache) {
    172             CacheEntry entry = cacheLocked(application.componentName, info, labelCache);
    173 
    174             application.title = entry.title;
    175             application.iconBitmap = entry.icon;
    176         }
    177     }
    178 
    179     public Bitmap getIcon(Intent intent) {
    180         synchronized (mCache) {
    181             final ResolveInfo resolveInfo = mPackageManager.resolveActivity(intent, 0);
    182             ComponentName component = intent.getComponent();
    183 
    184             if (resolveInfo == null || component == null) {
    185                 return mDefaultIcon;
    186             }
    187 
    188             CacheEntry entry = cacheLocked(component, resolveInfo, null);
    189             return entry.icon;
    190         }
    191     }
    192 
    193     public Bitmap getIcon(ComponentName component, ResolveInfo resolveInfo,
    194             HashMap<Object, CharSequence> labelCache) {
    195         synchronized (mCache) {
    196             if (resolveInfo == null || component == null) {
    197                 return null;
    198             }
    199 
    200             CacheEntry entry = cacheLocked(component, resolveInfo, labelCache);
    201             return entry.icon;
    202         }
    203     }
    204 
    205     public boolean isDefaultIcon(Bitmap icon) {
    206         return mDefaultIcon == icon;
    207     }
    208 
    209     private CacheEntry cacheLocked(ComponentName componentName, ResolveInfo info,
    210             HashMap<Object, CharSequence> labelCache) {
    211         CacheEntry entry = mCache.get(componentName);
    212         if (entry == null) {
    213             entry = new CacheEntry();
    214 
    215             mCache.put(componentName, entry);
    216 
    217             ComponentName key = LauncherModel.getComponentNameFromResolveInfo(info);
    218             if (labelCache != null && labelCache.containsKey(key)) {
    219                 entry.title = labelCache.get(key).toString();
    220             } else {
    221                 entry.title = info.loadLabel(mPackageManager).toString();
    222                 if (labelCache != null) {
    223                     labelCache.put(key, entry.title);
    224                 }
    225             }
    226             if (entry.title == null) {
    227                 entry.title = info.activityInfo.name;
    228             }
    229 
    230             entry.icon = Utilities.createIconBitmap(
    231                     getFullResIcon(info), mContext);
    232         }
    233         return entry;
    234     }
    235 
    236     public HashMap<ComponentName,Bitmap> getAllIcons() {
    237         synchronized (mCache) {
    238             HashMap<ComponentName,Bitmap> set = new HashMap<ComponentName,Bitmap>();
    239             for (ComponentName cn : mCache.keySet()) {
    240                 final CacheEntry e = mCache.get(cn);
    241                 set.put(cn, e.icon);
    242             }
    243             return set;
    244         }
    245     }
    246 }
    247