summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSunny Goyal <sunnygoyal@google.com>2015-05-20 22:34:41 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2015-05-20 22:34:42 +0000
commit2280e27842671d21fa29b6d7bd22b5912704471d (patch)
treea9d6f7593bc6958fbfde8df2cce13d2148266628
parent99d950fb4dfb5cb9edaae572579fc25b2aca726f (diff)
parent9ff980833d392244586ead8c27bbbba114e11ebb (diff)
downloadandroid_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.java70
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;