Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2280e278 authored by Sunny Goyal's avatar Sunny Goyal Committed by Android (Google) Code Review
Browse files

Merge "Avoiding blocking worker thread when adding icons to DB" into ub-launcher3-burnaby

parents 99d950fb 9ff98083
Loading
Loading
Loading
Loading
+58 −12
Original line number Diff line number Diff line
@@ -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();
    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;