/* * Copyright (C) 2008 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.launcher2; import android.content.ComponentName; import android.content.ContentResolver; import android.content.ContentValues; import android.content.Intent; import android.content.Context; import android.content.pm.ActivityInfo; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.content.res.Resources; import android.database.Cursor; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.drawable.Drawable; import android.graphics.drawable.BitmapDrawable; import android.net.Uri; import android.util.Log; import android.os.Process; import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.HashMap; import java.util.List; /** * Cache of application icons. Icons can be made from any thread. */ public class AppInfoCache { private static final String TAG = "Launcher.AppInfoCache"; private static final int INITIAL_ICON_CACHE_CAPACITY = 50; private static final HashMap sCache = new HashMap(INITIAL_ICON_CACHE_CAPACITY); /** * no public constructor. */ private AppInfoCache() { } /** * For the given ResolveInfo, return an ApplicationInfo and cache the result for later. */ public static ApplicationInfo cache(ResolveInfo info, Context context, Utilities.BubbleText bubble) { synchronized (sCache) { ComponentName componentName = new ComponentName( info.activityInfo.applicationInfo.packageName, info.activityInfo.name); ApplicationInfo application = sCache.get(componentName); if (application == null) { application = new ApplicationInfo(); application.container = ItemInfo.NO_ID; updateTitleAndIcon(info, application, context, bubble); application.setActivity(componentName, Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED); sCache.put(componentName, application); } return application; } } /** * Update the entry in the in the cache with its new metadata. */ public static void update(ResolveInfo info, ApplicationInfo applicationInfo, Context context, Utilities.BubbleText bubble) { synchronized (sCache) { updateTitleAndIcon(info, applicationInfo, context, bubble); ComponentName componentName = new ComponentName( info.activityInfo.applicationInfo.packageName, info.activityInfo.name); sCache.put(componentName, applicationInfo); } } /** * Remove any records for the supplied ComponentName. */ public static void remove(ComponentName componentName) { synchronized (sCache) { sCache.remove(componentName); } } /** * Empty out the cache. */ public static void flush() { synchronized (sCache) { sCache.clear(); } } /** * Get the icon for the supplied ApplicationInfo. If that activity already * exists in the cache, use that. */ public static Drawable getIconDrawable(PackageManager packageManager, ApplicationInfo info) { final ResolveInfo resolveInfo = packageManager.resolveActivity(info.intent, 0); if (resolveInfo == null) { return null; } ComponentName componentName = new ComponentName( resolveInfo.activityInfo.applicationInfo.packageName, resolveInfo.activityInfo.name); ApplicationInfo cached; synchronized (sCache) { cached = sCache.get(componentName); if (cached != null) { if (cached.icon == null) { cached.icon = resolveInfo.activityInfo.loadIcon(packageManager); } return cached.icon; } else { return resolveInfo.activityInfo.loadIcon(packageManager); } } } /** * Go through the cache and disconnect any of the callbacks in the drawables or we * leak the previous Home screen on orientation change. */ public static void unbindDrawables() { synchronized (sCache) { for (ApplicationInfo appInfo: sCache.values()) { if (appInfo.icon != null) { appInfo.icon.setCallback(null); } } } } /** * Update the title and icon. Don't keep a reference to the context! */ private static void updateTitleAndIcon(ResolveInfo info, ApplicationInfo application, Context context, Utilities.BubbleText bubble) { final PackageManager packageManager = context.getPackageManager(); application.title = info.loadLabel(packageManager); if (application.title == null) { application.title = info.activityInfo.name; } application.iconBitmap = Utilities.createAllAppsBitmap( info.activityInfo.loadIcon(packageManager), context); application.titleBitmap = bubble.createTextBitmap(application.title.toString()); } }