summaryrefslogtreecommitdiffstats
path: root/src/com/android/launcher3/LauncherModel.java
diff options
context:
space:
mode:
authorSunny Goyal <sunnygoyal@google.com>2015-02-18 16:46:50 -0800
committerSunny Goyal <sunnygoyal@google.com>2015-02-26 19:08:44 +0000
commit4fbc3828c5ae1e8c5789ede974447fa365f3c5a1 (patch)
tree9e570b85d5550537b17c85fd1d579fcc43b6136f /src/com/android/launcher3/LauncherModel.java
parented46c093cf1f34a2056846ac826b19fa2335ec18 (diff)
downloadandroid_packages_apps_Trebuchet-4fbc3828c5ae1e8c5789ede974447fa365f3c5a1.tar.gz
android_packages_apps_Trebuchet-4fbc3828c5ae1e8c5789ede974447fa365f3c5a1.tar.bz2
android_packages_apps_Trebuchet-4fbc3828c5ae1e8c5789ede974447fa365f3c5a1.zip
Updating IconCache to maintain a persistent of icons
> IconDB maintains a DB of icons keyed on ComponentName + User > During loader, icons & labels are loaded first from the DB, and if the entry doesn't exist, loaded using packageManager > After the loader completes, IconDB updates any entry which might have changed, while the launcher was dead. Change-Id: I7a6021cb6d1ca1e66fa5a0bdd21e1543e0cf66fc
Diffstat (limited to 'src/com/android/launcher3/LauncherModel.java')
-rw-r--r--src/com/android/launcher3/LauncherModel.java234
1 files changed, 60 insertions, 174 deletions
diff --git a/src/com/android/launcher3/LauncherModel.java b/src/com/android/launcher3/LauncherModel.java
index 3983835dc..489e3299d 100644
--- a/src/com/android/launcher3/LauncherModel.java
+++ b/src/com/android/launcher3/LauncherModel.java
@@ -36,7 +36,6 @@ import android.content.res.Configuration;
import android.content.res.Resources;
import android.database.Cursor;
import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
import android.graphics.Rect;
import android.net.Uri;
import android.os.Environment;
@@ -163,9 +162,6 @@ public class LauncherModel extends BroadcastReceiver
// sBgFolders is all FolderInfos created by LauncherModel. Passed to bindFolders()
static final HashMap<Long, FolderInfo> sBgFolders = new HashMap<Long, FolderInfo>();
- // sBgDbIconCache is the set of ItemInfos that need to have their icons updated in the database
- static final HashMap<Object, byte[]> sBgDbIconCache = new HashMap<Object, byte[]>();
-
// sBgWorkspaceScreens is the ordered set of workspace screens.
static final ArrayList<Long> sBgWorkspaceScreens = new ArrayList<Long>();
@@ -1131,7 +1127,6 @@ public class LauncherModel extends BroadcastReceiver
break;
}
sBgItemsIdMap.remove(item.id);
- sBgDbIconCache.remove(item);
}
}
}
@@ -1204,7 +1199,6 @@ public class LauncherModel extends BroadcastReceiver
synchronized (sBgLock) {
sBgItemsIdMap.remove(info.id);
sBgFolders.remove(info.id);
- sBgDbIconCache.remove(info);
sBgWorkspaceItems.remove(info);
}
@@ -1214,7 +1208,6 @@ public class LauncherModel extends BroadcastReceiver
synchronized (sBgLock) {
for (ItemInfo childInfo : info.contents) {
sBgItemsIdMap.remove(childInfo.id);
- sBgDbIconCache.remove(childInfo);
}
}
}
@@ -1481,12 +1474,9 @@ public class LauncherModel extends BroadcastReceiver
private boolean mLoadAndBindStepFinished;
private int mFlags;
- private HashMap<Object, CharSequence> mLabelCache;
-
LoaderTask(Context context, boolean isLaunching, int flags) {
mContext = context;
mIsLaunching = isLaunching;
- mLabelCache = new HashMap<Object, CharSequence>();
mFlags = flags;
}
@@ -1635,15 +1625,6 @@ public class LauncherModel extends BroadcastReceiver
}
}
- // Update the saved icons if necessary
- if (DEBUG_LOADERS) Log.d(TAG, "Comparing loaded icons to database icons");
- synchronized (sBgLock) {
- for (Object key : sBgDbIconCache.keySet()) {
- updateSavedIcon(mContext, (ShortcutInfo) key, sBgDbIconCache.get(key));
- }
- sBgDbIconCache.clear();
- }
-
if (LauncherAppState.isDisableAllApps()) {
// Ensure that all the applications that are in the system are
// represented on the home screen.
@@ -1819,7 +1800,6 @@ public class LauncherModel extends BroadcastReceiver
sBgAppWidgets.clear();
sBgFolders.clear();
sBgItemsIdMap.clear();
- sBgDbIconCache.clear();
sBgWorkspaceScreens.clear();
}
}
@@ -2068,8 +2048,8 @@ public class LauncherModel extends BroadcastReceiver
if (itemReplaced) {
if (user.equals(UserHandleCompat.myUserHandle())) {
- info = getShortcutInfo(manager, intent, user, context, null,
- iconIndex, titleIndex, mLabelCache, false);
+ info = getAppShortcutInfo(manager, intent, user, context, null,
+ iconIndex, titleIndex, false);
} else {
// Don't replace items for other profiles.
itemsToRemove.add(id);
@@ -2089,8 +2069,8 @@ public class LauncherModel extends BroadcastReceiver
}
} else if (itemType ==
LauncherSettings.Favorites.ITEM_TYPE_APPLICATION) {
- info = getShortcutInfo(manager, intent, user, context, c,
- iconIndex, titleIndex, mLabelCache, allowMissingTarget);
+ info = getAppShortcutInfo(manager, intent, user, context, c,
+ iconIndex, titleIndex, allowMissingTarget);
} else {
info = getShortcutInfo(c, context, iconTypeIndex,
iconPackageIndex, iconResourceIndex, iconIndex,
@@ -2145,10 +2125,6 @@ public class LauncherModel extends BroadcastReceiver
break;
}
sBgItemsIdMap.put(info.id, info);
-
- // now that we've loaded everthing re-save it with the
- // icon in case it disappears somehow.
- queueIconToBeChecked(sBgDbIconCache, info, c, iconIndex);
} else {
throw new RuntimeException("Unexpected null ShortcutInfo");
}
@@ -2842,20 +2818,48 @@ public class LauncherModel extends BroadcastReceiver
if (apps == null || apps.isEmpty()) {
return;
}
- // Sort the applications by name
- final long sortTime = DEBUG_LOADERS ? SystemClock.uptimeMillis() : 0;
- Collections.sort(apps,
- new LauncherModel.ShortcutNameComparator(mLabelCache));
- if (DEBUG_LOADERS) {
- Log.d(TAG, "sort took "
- + (SystemClock.uptimeMillis()-sortTime) + "ms");
+
+ // Update icon cache
+ HashSet<String> updatedPackages = mIconCache.updateDBIcons(user, apps);
+
+ // If any package icon has changed (app was updated while launcher was dead),
+ // update the corresponding shortcuts.
+ if (!updatedPackages.isEmpty()) {
+ final ArrayList<ShortcutInfo> updates = new ArrayList<ShortcutInfo>();
+ synchronized (sBgLock) {
+ for (ItemInfo info : sBgItemsIdMap.values()) {
+ if (info instanceof ShortcutInfo && user.equals(info.user)
+ && info.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION) {
+ ShortcutInfo si = (ShortcutInfo) info;
+ ComponentName cn = si.getTargetComponent();
+ if (cn != null && updatedPackages.contains(cn.getPackageName())) {
+ si.updateIcon(mIconCache);
+ updates.add(si);
+ }
+ }
+ }
+ }
+
+ if (!updates.isEmpty()) {
+ final UserHandleCompat userFinal = user;
+ mHandler.post(new Runnable() {
+
+ public void run() {
+ Callbacks cb = getCallback();
+ if (cb != null) {
+ cb.bindShortcutsChanged(
+ updates, new ArrayList<ShortcutInfo>(), userFinal);
+ }
+ }
+ });
+ }
}
// Create the ApplicationInfos
for (int i = 0; i < apps.size(); i++) {
LauncherActivityInfoCompat app = apps.get(i);
// This builds the icon bitmaps.
- mBgAllAppsList.add(new AppInfo(mContext, app, user, mIconCache, mLabelCache));
+ mBgAllAppsList.add(new AppInfo(mContext, app, user, mIconCache));
}
if (ADD_MANAGED_PROFILE_SHORTCUTS && !user.equals(UserHandleCompat.myUserHandle())) {
@@ -2987,7 +2991,7 @@ public class LauncherModel extends BroadcastReceiver
case OP_ADD:
for (int i=0; i<N; i++) {
if (DEBUG_LOADERS) Log.d(TAG, "mAllAppsList.addPackage " + packages[i]);
- mIconCache.remove(packages[i], mUser);
+ mIconCache.updateIconsForPkg(packages[i], mUser);
mBgAllAppsList.addPackage(context, packages[i], mUser);
}
@@ -3019,6 +3023,7 @@ public class LauncherModel extends BroadcastReceiver
case OP_UPDATE:
for (int i=0; i<N; i++) {
if (DEBUG_LOADERS) Log.d(TAG, "mAllAppsList.updatePackage " + packages[i]);
+ mIconCache.updateIconsForPkg(packages[i], mUser);
mBgAllAppsList.updatePackage(context, packages[i], mUser);
WidgetPreviewLoader.removePackageFromDb(
mApp.getWidgetPreviewCacheDb(), packages[i]);
@@ -3038,12 +3043,15 @@ public class LauncherModel extends BroadcastReceiver
shortcutSet.removeAll(Arrays.asList(mPackages));
prefs.edit().putStringSet(shortcutsSetKey, shortcutSet).commit();
}
+ for (int i=0; i<N; i++) {
+ if (DEBUG_LOADERS) Log.d(TAG, "mAllAppsList.removePackage " + packages[i]);
+ mIconCache.removeIconsForPkg(packages[i], mUser);
+ }
// Fall through
case OP_UNAVAILABLE:
- boolean clearCache = mOp == OP_REMOVE;
for (int i=0; i<N; i++) {
if (DEBUG_LOADERS) Log.d(TAG, "mAllAppsList.removePackage " + packages[i]);
- mBgAllAppsList.removePackage(packages[i], mUser, clearCache);
+ mBgAllAppsList.removePackage(packages[i], mUser);
WidgetPreviewLoader.removePackageFromDb(
mApp.getWidgetPreviewCacheDb(), packages[i]);
}
@@ -3136,7 +3144,6 @@ public class LauncherModel extends BroadcastReceiver
AppInfo appInfo = addedOrUpdatedApps.get(cn);
if (si.isPromise()) {
- mIconCache.deletePreloadedIcon(cn, mUser);
if (si.hasStatusFlag(ShortcutInfo.FLAG_AUTOINTALL_ICON)) {
// Auto install icon
PackageManager pm = context.getPackageManager();
@@ -3381,7 +3388,7 @@ public class LauncherModel extends BroadcastReceiver
int promiseType) {
final ShortcutInfo info = new ShortcutInfo();
info.user = UserHandleCompat.myUserHandle();
- mIconCache.getTitleAndIcon(info, intent, info.user, true);
+ mIconCache.getTitleAndIcon(info, intent, info.user);
if ((promiseType & ShortcutInfo.FLAG_RESTORED_ICON) != 0) {
String title = (cursor != null) ? cursor.getString(titleIndex) : null;
@@ -3424,22 +3431,13 @@ public class LauncherModel extends BroadcastReceiver
}
/**
- * This is called from the code that adds shortcuts from the intent receiver. This
- * doesn't have a Cursor, but
- */
- public ShortcutInfo getShortcutInfo(PackageManager manager, Intent intent,
- UserHandleCompat user, Context context) {
- return getShortcutInfo(manager, intent, user, context, null, -1, -1, null, false);
- }
-
- /**
* Make an ShortcutInfo object for a shortcut that is an application.
*
* If c is not null, then it will be used to fill in missing data like the title and icon.
*/
- public ShortcutInfo getShortcutInfo(PackageManager manager, Intent intent,
+ public ShortcutInfo getAppShortcutInfo(PackageManager manager, Intent intent,
UserHandleCompat user, Context context, Cursor c, int iconIndex, int titleIndex,
- HashMap<Object, CharSequence> labelCache, boolean allowMissingTarget) {
+ boolean allowMissingTarget) {
if (user == null) {
Log.d(TAG, "Null user found in getShortcutInfo");
return null;
@@ -3461,48 +3459,22 @@ public class LauncherModel extends BroadcastReceiver
}
final ShortcutInfo info = new ShortcutInfo();
-
- // the resource -- This may implicitly give us back the fallback icon,
- // but don't worry about that. All we're doing with usingFallbackIcon is
- // to avoid saving lots of copies of that in the database, and most apps
- // have icons anyway.
- Bitmap icon = mIconCache.getIcon(componentName, lai, labelCache);
-
- // the db
- if (icon == null) {
- if (c != null) {
- icon = getIconFromCursor(c, iconIndex, context);
- }
- }
- // the fallback icon
- if (icon == null) {
- icon = mIconCache.getDefaultIcon(user);
- info.usingFallbackIcon = true;
- }
- info.setIcon(icon);
-
- // From the cache.
- if (labelCache != null) {
- info.title = labelCache.get(componentName);
+ mIconCache.getTitleAndIcon(info, componentName, lai, user, false);
+ if (mIconCache.isDefaultIcon(info.getIcon(mIconCache), user) && c != null) {
+ Bitmap icon = Utilities.createIconBitmap(c, iconIndex, context);
+ info.setIcon(icon == null ? mIconCache.getDefaultIcon(user) : icon);
}
- // from the resource
- if (info.title == null && lai != null) {
- info.title = lai.getLabel();
- if (labelCache != null) {
- labelCache.put(componentName, info.title);
- }
- }
// from the db
- if (info.title == null) {
- if (c != null) {
- info.title = c.getString(titleIndex);
- }
+ if (TextUtils.isEmpty(info.title) && c != null) {
+ info.title = c.getString(titleIndex);
}
+
// fall back to the class name of the activity
if (info.title == null) {
info.title = componentName.getClassName();
}
+
info.itemType = LauncherSettings.Favorites.ITEM_TYPE_APPLICATION;
info.user = user;
info.contentDescription = mUserManager.getBadgedLabelForUser(
@@ -3581,7 +3553,7 @@ public class LauncherModel extends BroadcastReceiver
icon = Utilities.createIconBitmap(packageName, resourceName, mIconCache, context);
// the db
if (icon == null) {
- icon = getIconFromCursor(c, iconIndex, context);
+ icon = Utilities.createIconBitmap(c, iconIndex, context);
}
// the fallback icon
if (icon == null) {
@@ -3590,7 +3562,7 @@ public class LauncherModel extends BroadcastReceiver
}
break;
case LauncherSettings.Favorites.ICON_TYPE_BITMAP:
- icon = getIconFromCursor(c, iconIndex, context);
+ icon = Utilities.createIconBitmap(c, iconIndex, context);
if (icon == null) {
icon = mIconCache.getDefaultIcon(info.user);
info.customIcon = false;
@@ -3609,22 +3581,6 @@ public class LauncherModel extends BroadcastReceiver
return info;
}
- Bitmap getIconFromCursor(Cursor c, int iconIndex, Context context) {
- @SuppressWarnings("all") // suppress dead code warning
- final boolean debug = false;
- if (debug) {
- Log.d(TAG, "getIconFromCursor app="
- + c.getString(c.getColumnIndexOrThrow(LauncherSettings.Favorites.TITLE)));
- }
- byte[] data = c.getBlob(iconIndex);
- try {
- return Utilities.createIconBitmap(
- BitmapFactory.decodeByteArray(data, 0, data.length), context);
- } catch (Exception e) {
- return null;
- }
- }
-
ShortcutInfo infoFromShortcutIntent(Context context, Intent data) {
Intent intent = data.getParcelableExtra(Intent.EXTRA_SHORTCUT_INTENT);
String name = data.getStringExtra(Intent.EXTRA_SHORTCUT_NAME);
@@ -3673,45 +3629,6 @@ public class LauncherModel extends BroadcastReceiver
return info;
}
- boolean queueIconToBeChecked(HashMap<Object, byte[]> cache, ShortcutInfo info, Cursor c,
- int iconIndex) {
- // If apps can't be on SD, don't even bother.
- if (!mAppsCanBeOnRemoveableStorage) {
- return false;
- }
- // If this icon doesn't have a custom icon, check to see
- // what's stored in the DB, and if it doesn't match what
- // we're going to show, store what we are going to show back
- // into the DB. We do this so when we're loading, if the
- // package manager can't find an icon (for example because
- // the app is on SD) then we can use that instead.
- if (!info.customIcon && !info.usingFallbackIcon) {
- cache.put(info, c.getBlob(iconIndex));
- return true;
- }
- return false;
- }
- void updateSavedIcon(Context context, ShortcutInfo info, byte[] data) {
- boolean needSave = false;
- try {
- if (data != null) {
- Bitmap saved = BitmapFactory.decodeByteArray(data, 0, data.length);
- Bitmap loaded = info.getIcon(mIconCache);
- needSave = !saved.sameAs(loaded);
- } else {
- needSave = true;
- }
- } catch (Exception e) {
- needSave = true;
- }
- if (needSave) {
- Log.d(TAG, "going to save icon bitmap for info=" + info);
- // This is slower than is ideal, but this only happens once
- // or when the app is updated with a new icon.
- updateItemInDatabase(context, info);
- }
- }
-
/**
* Return an existing FolderInfo object if we have encountered this ID previously,
* or make a new one.
@@ -3761,38 +3678,7 @@ public class LauncherModel extends BroadcastReceiver
return new ComponentName(info.serviceInfo.packageName, info.serviceInfo.name);
}
}
- public static class ShortcutNameComparator implements Comparator<LauncherActivityInfoCompat> {
- private Collator mCollator;
- private HashMap<Object, CharSequence> mLabelCache;
- ShortcutNameComparator(PackageManager pm) {
- mLabelCache = new HashMap<Object, CharSequence>();
- mCollator = Collator.getInstance();
- }
- ShortcutNameComparator(HashMap<Object, CharSequence> labelCache) {
- mLabelCache = labelCache;
- mCollator = Collator.getInstance();
- }
- public final int compare(LauncherActivityInfoCompat a, LauncherActivityInfoCompat b) {
- String labelA, labelB;
- ComponentName keyA = a.getComponentName();
- ComponentName keyB = b.getComponentName();
- if (mLabelCache.containsKey(keyA)) {
- labelA = mLabelCache.get(keyA).toString();
- } else {
- labelA = a.getLabel().toString().trim();
-
- mLabelCache.put(keyA, labelA);
- }
- if (mLabelCache.containsKey(keyB)) {
- labelB = mLabelCache.get(keyB).toString();
- } else {
- labelB = b.getLabel().toString().trim();
- mLabelCache.put(keyB, labelB);
- }
- return mCollator.compare(labelA, labelB);
- }
- };
public static class WidgetAndShortcutNameComparator implements Comparator<Object> {
private final AppWidgetManagerCompat mManager;
private final PackageManager mPackageManager;