diff options
author | Sunny Goyal <sunnygoyal@google.com> | 2015-05-20 22:34:41 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2015-05-20 22:34:42 +0000 |
commit | 2280e27842671d21fa29b6d7bd22b5912704471d (patch) | |
tree | a9d6f7593bc6958fbfde8df2cce13d2148266628 | |
parent | 99d950fb4dfb5cb9edaae572579fc25b2aca726f (diff) | |
parent | 9ff980833d392244586ead8c27bbbba114e11ebb (diff) | |
download | android_packages_apps_Trebuchet-2280e27842671d21fa29b6d7bd22b5912704471d.tar.gz android_packages_apps_Trebuchet-2280e27842671d21fa29b6d7bd22b5912704471d.tar.bz2 android_packages_apps_Trebuchet-2280e27842671d21fa29b6d7bd22b5912704471d.zip |
Merge "Avoiding blocking worker thread when adding icons to DB" into ub-launcher3-burnaby
-rw-r--r-- | src/com/android/launcher3/IconCache.java | 70 |
1 files changed, 58 insertions, 12 deletions
diff --git a/src/com/android/launcher3/IconCache.java b/src/com/android/launcher3/IconCache.java index fff07c6ed..1fac5a1c2 100644 --- a/src/com/android/launcher3/IconCache.java +++ b/src/com/android/launcher3/IconCache.java @@ -46,12 +46,14 @@ import com.android.launcher3.util.ComponentKey; import com.android.launcher3.util.Thunk; import com.android.launcher3.widget.PackageItemInfo; +import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Locale; import java.util.Map.Entry; +import java.util.Stack; /** * Cache of application icons. Icons can be made from any thread. @@ -281,7 +283,7 @@ public class IconCache { itemsToRemove.add(c.getInt(rowIndex)); continue; } - ContentValues values = updateCacheAndGetContentValues(app); + ContentValues values = updateCacheAndGetContentValues(app, true); mIconDb.getWritableDatabase().update(IconDB.TABLE_NAME, values, IconDB.COLUMN_COMPONENT + " = ? AND " + IconDB.COLUMN_USER + " = ?", new String[] {cn, Long.toString(userSerial)}); @@ -296,21 +298,19 @@ public class IconCache { } // Insert remaining apps. - for (LauncherActivityInfoCompat app : componentMap.values()) { - PackageInfo info = pkgInfoMap.get(app.getComponentName().getPackageName()); - if (info == null) { - continue; - } - addIconToDBAndMemCache(app, info, userSerial); + if (!componentMap.isEmpty()) { + mWorkerHandler.post(new SerializedIconAdditionTask(userSerial, pkgInfoMap, + componentMap.values())); } return updatedPackages; } private void addIconToDBAndMemCache(LauncherActivityInfoCompat app, PackageInfo info, long userSerial) { - ContentValues values = updateCacheAndGetContentValues(app); + // Reuse the existing entry if it already exists in the DB. This ensures that we do not + // create bitmap if it was already created during loader. + ContentValues values = updateCacheAndGetContentValues(app, false); addIconToDB(values, app.getComponentName(), info, userSerial); - values.put(IconDB.COLUMN_COMPONENT, app.getComponentName().flattenToString()); } /** @@ -327,9 +327,21 @@ public class IconCache { SQLiteDatabase.CONFLICT_REPLACE); } - private ContentValues updateCacheAndGetContentValues(LauncherActivityInfoCompat app) { - CacheEntry entry = new CacheEntry(); - entry.icon = Utilities.createIconBitmap(app.getBadgedIcon(mIconDpi), mContext); + private ContentValues updateCacheAndGetContentValues(LauncherActivityInfoCompat app, + boolean replaceExisting) { + final ComponentKey key = new ComponentKey(app.getComponentName(), app.getUser()); + CacheEntry entry = null; + if (!replaceExisting) { + entry = mCache.get(key); + // We can't reuse the entry if the high-res icon is not present. + if (entry == null || entry.isLowResIcon || entry.icon == null) { + entry = null; + } + } + if (entry == null) { + entry = new CacheEntry(); + entry.icon = Utilities.createIconBitmap(app.getBadgedIcon(mIconDpi), mContext); + } entry.title = app.getLabel(); entry.contentDescription = mUserManager.getBadgedLabelForUser(entry.title, app.getUser()); mCache.put(new ComponentKey(app.getComponentName(), app.getUser()), entry); @@ -671,6 +683,40 @@ public class IconCache { } } + /** + * A runnable that adds icons in the DB for the provided LauncherActivityInfoCompat list. + * Items are added one at a time, to that the worker thread does not get blocked. + */ + private class SerializedIconAdditionTask implements Runnable { + private final long mUserSerial; + private final HashMap<String, PackageInfo> mPkgInfoMap; + private final Stack<LauncherActivityInfoCompat> mAppsToAdd; + + private SerializedIconAdditionTask(long userSerial, HashMap<String, PackageInfo> pkgInfoMap, + Collection<LauncherActivityInfoCompat> appsToAdd) { + mUserSerial = userSerial; + mPkgInfoMap = pkgInfoMap; + mAppsToAdd = new Stack<LauncherActivityInfoCompat>(); + mAppsToAdd.addAll(appsToAdd); + } + + @Override + public void run() { + if (!mAppsToAdd.isEmpty()) { + LauncherActivityInfoCompat app = mAppsToAdd.pop(); + PackageInfo info = mPkgInfoMap.get(app.getComponentName().getPackageName()); + if (info != null) { + synchronized (IconCache.this) { + addIconToDBAndMemCache(app, info, mUserSerial); + } + } + } + if (!mAppsToAdd.isEmpty()) { + mWorkerHandler.post(this); + } + } + } + private static final class IconDB extends SQLiteOpenHelper { private final static int DB_VERSION = 4; |