10589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato/*
20589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato * Copyright (C) 2008 The Android Open Source Project
30589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato *
40589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato * Licensed under the Apache License, Version 2.0 (the "License");
50589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato * you may not use this file except in compliance with the License.
60589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato * You may obtain a copy of the License at
70589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato *
80589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato *      http://www.apache.org/licenses/LICENSE-2.0
90589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato *
100589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato * Unless required by applicable law or agreed to in writing, software
110589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato * distributed under the License is distributed on an "AS IS" BASIS,
120589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
130589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato * See the License for the specific language governing permissions and
140589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato * limitations under the License.
150589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato */
160589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato
17325dc23624160689e59fbac708cf6f222b20d025Daniel Sandlerpackage com.android.launcher3;
180589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato
190589f0f66ce498512c6ee47482c649d88294c9d0Joe Onoratoimport android.content.ComponentName;
204fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyalimport android.content.ContentValues;
21d83f5f4db328fbd152491bbf9fa13abc94bd6f25Winson Chungimport android.content.Context;
220589f0f66ce498512c6ee47482c649d88294c9d0Joe Onoratoimport android.content.Intent;
23dac8591072959f69eaa8c6319311fd111ae75db6Michael Jurkaimport android.content.pm.ActivityInfo;
240fc1be164e982433e619bcbb16aa67e28ff681efSunny Goyalimport android.content.pm.ApplicationInfo;
254fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyalimport android.content.pm.PackageInfo;
260589f0f66ce498512c6ee47482c649d88294c9d0Joe Onoratoimport android.content.pm.PackageManager;
270fc1be164e982433e619bcbb16aa67e28ff681efSunny Goyalimport android.content.pm.PackageManager.NameNotFoundException;
28c9a961952d1a057029874f8426b90181f6876034Michael Jurkaimport android.content.res.Resources;
294fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyalimport android.database.Cursor;
304fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyalimport android.database.sqlite.SQLiteDatabase;
316f70936f7fb7cb45ef6a2a3d1019b6ecf3e49440Sunny Goyalimport android.database.sqlite.SQLiteException;
320589f0f66ce498512c6ee47482c649d88294c9d0Joe Onoratoimport android.graphics.Bitmap;
3334b6527cefd36fbd5da78464ce9771e379158552Sunny Goyalimport android.graphics.BitmapFactory;
34a28fd3fa7c82947d847c05ed11905f556b8dcfa2Romain Guyimport android.graphics.Canvas;
35360bc25ab6ae22869b867350b87ee7e82f06389aSunny Goyalimport android.graphics.Color;
36360bc25ab6ae22869b867350b87ee7e82f06389aSunny Goyalimport android.graphics.Paint;
37360bc25ab6ae22869b867350b87ee7e82f06389aSunny Goyalimport android.graphics.Rect;
380589f0f66ce498512c6ee47482c649d88294c9d0Joe Onoratoimport android.graphics.drawable.Drawable;
3934b6527cefd36fbd5da78464ce9771e379158552Sunny Goyalimport android.os.Handler;
4075b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyalimport android.os.SystemClock;
41349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyalimport android.text.TextUtils;
426d0dde01f307051ee1849481c989d9e87774b894Chris Wrenimport android.util.Log;
436d0dde01f307051ee1849481c989d9e87774b894Chris Wren
44ed13187a745866483139e2878037e1f8427ce567Kenny Guyimport com.android.launcher3.compat.LauncherActivityInfoCompat;
45ed13187a745866483139e2878037e1f8427ce567Kenny Guyimport com.android.launcher3.compat.LauncherAppsCompat;
46ed13187a745866483139e2878037e1f8427ce567Kenny Guyimport com.android.launcher3.compat.UserHandleCompat;
47ed13187a745866483139e2878037e1f8427ce567Kenny Guyimport com.android.launcher3.compat.UserManagerCompat;
48d896ee43cd9195a2a2742324733b036ee72875bbSunny Goyalimport com.android.launcher3.config.FeatureFlags;
492bd3d7d1cb5e4d8d826982d11b456739fed6b817Hyunyoung Songimport com.android.launcher3.model.PackageItemInfo;
50b4cd42a1df69ec887d0c66e8fe6fe1f27ebbf9bcSunny Goyalimport com.android.launcher3.util.ComponentKey;
516f70936f7fb7cb45ef6a2a3d1019b6ecf3e49440Sunny Goyalimport com.android.launcher3.util.SQLiteCacheHelper;
52091440a9cb9d4f42406631004aa484cbb79214caAdam Cohenimport com.android.launcher3.util.Thunk;
53ed13187a745866483139e2878037e1f8427ce567Kenny Guy
544e5cc64eaf1f63d866d51ce0a6bbafb3d4085c21Sunny Goyalimport java.util.Collections;
550589f0f66ce498512c6ee47482c649d88294c9d0Joe Onoratoimport java.util.HashMap;
566d0dde01f307051ee1849481c989d9e87774b894Chris Wrenimport java.util.HashSet;
574fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyalimport java.util.List;
580c9a354c9732585620569bafaec0973977baf614Sunny Goyalimport java.util.Locale;
594e5cc64eaf1f63d866d51ce0a6bbafb3d4085c21Sunny Goyalimport java.util.Set;
609ff980833d392244586ead8c27bbbba114e11ebbSunny Goyalimport java.util.Stack;
610589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato
620589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato/**
630589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato * Cache of application icons.  Icons can be made from any thread.
640589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato */
650589f0f66ce498512c6ee47482c649d88294c9d0Joe Onoratopublic class IconCache {
660fc1be164e982433e619bcbb16aa67e28ff681efSunny Goyal
670589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato    private static final String TAG = "Launcher.IconCache";
680589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato
690589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato    private static final int INITIAL_ICON_CACHE_CAPACITY = 50;
706d0dde01f307051ee1849481c989d9e87774b894Chris Wren
710fc1be164e982433e619bcbb16aa67e28ff681efSunny Goyal    // Empty class name is used for storing package default entry.
720fc1be164e982433e619bcbb16aa67e28ff681efSunny Goyal    private static final String EMPTY_CLASS_NAME = ".";
730fc1be164e982433e619bcbb16aa67e28ff681efSunny Goyal
74bbef77dbdf469c17f3be0817d0d09983a81b6123Sunny Goyal    private static final boolean DEBUG = false;
750589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato
76360bc25ab6ae22869b867350b87ee7e82f06389aSunny Goyal    private static final int LOW_RES_SCALE_FACTOR = 5;
7734b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal
78316490e636aad788fcfbfc2e04dd4f0e145bdd00Sunny Goyal    @Thunk static final Object ICON_UPDATE_TOKEN = new Object();
7975b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal
80091440a9cb9d4f42406631004aa484cbb79214caAdam Cohen    @Thunk static class CacheEntry {
810589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato        public Bitmap icon;
82cdefc631f8b4b3e56ea3bd238d46d0bc9e28eabeWinson Chung        public CharSequence title = "";
83cdefc631f8b4b3e56ea3bd238d46d0bc9e28eabeWinson Chung        public CharSequence contentDescription = "";
8434b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal        public boolean isLowResIcon;
850589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato    }
860589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato
878758ea050a9202e9733520898dda5d290644839eSunny Goyal    private final HashMap<UserHandleCompat, Bitmap> mDefaultIcons = new HashMap<>();
88316490e636aad788fcfbfc2e04dd4f0e145bdd00Sunny Goyal    @Thunk final MainThreadExecutor mMainThreadExecutor = new MainThreadExecutor();
898758ea050a9202e9733520898dda5d290644839eSunny Goyal
90cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler    private final Context mContext;
91a28fd3fa7c82947d847c05ed11905f556b8dcfa2Romain Guy    private final PackageManager mPackageManager;
92316490e636aad788fcfbfc2e04dd4f0e145bdd00Sunny Goyal    @Thunk final UserManagerCompat mUserManager;
93ed13187a745866483139e2878037e1f8427ce567Kenny Guy    private final LauncherAppsCompat mLauncherApps;
94b4cd42a1df69ec887d0c66e8fe6fe1f27ebbf9bcSunny Goyal    private final HashMap<ComponentKey, CacheEntry> mCache =
95b4cd42a1df69ec887d0c66e8fe6fe1f27ebbf9bcSunny Goyal            new HashMap<ComponentKey, CacheEntry>(INITIAL_ICON_CACHE_CAPACITY);
964fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal    private final int mIconDpi;
97316490e636aad788fcfbfc2e04dd4f0e145bdd00Sunny Goyal    @Thunk final IconDB mIconDb;
980589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato
99316490e636aad788fcfbfc2e04dd4f0e145bdd00Sunny Goyal    @Thunk final Handler mWorkerHandler;
10034b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal
101360bc25ab6ae22869b867350b87ee7e82f06389aSunny Goyal    // The background color used for activity icons. Since these icons are displayed in all-apps
102360bc25ab6ae22869b867350b87ee7e82f06389aSunny Goyal    // and folders, this would be same as the light quantum panel background. This color
103360bc25ab6ae22869b867350b87ee7e82f06389aSunny Goyal    // is used to convert icons to RGB_565.
104360bc25ab6ae22869b867350b87ee7e82f06389aSunny Goyal    private final int mActivityBgColor;
105360bc25ab6ae22869b867350b87ee7e82f06389aSunny Goyal    // The background color used for package icons. These are displayed in widget tray, which
106360bc25ab6ae22869b867350b87ee7e82f06389aSunny Goyal    // has a dark quantum panel background.
107360bc25ab6ae22869b867350b87ee7e82f06389aSunny Goyal    private final int mPackageBgColor;
108360bc25ab6ae22869b867350b87ee7e82f06389aSunny Goyal    private final BitmapFactory.Options mLowResOptions;
109360bc25ab6ae22869b867350b87ee7e82f06389aSunny Goyal
110360bc25ab6ae22869b867350b87ee7e82f06389aSunny Goyal    private String mSystemState;
111360bc25ab6ae22869b867350b87ee7e82f06389aSunny Goyal    private Bitmap mLowResBitmap;
112360bc25ab6ae22869b867350b87ee7e82f06389aSunny Goyal    private Canvas mLowResCanvas;
113360bc25ab6ae22869b867350b87ee7e82f06389aSunny Goyal    private Paint mLowResPaint;
114360bc25ab6ae22869b867350b87ee7e82f06389aSunny Goyal
1152e6da1539bc7286336b3c24d96ab76434939ce4dAdam Cohen    public IconCache(Context context, InvariantDeviceProfile inv) {
1160589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato        mContext = context;
1170589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato        mPackageManager = context.getPackageManager();
118ed13187a745866483139e2878037e1f8427ce567Kenny Guy        mUserManager = UserManagerCompat.getInstance(mContext);
119ed13187a745866483139e2878037e1f8427ce567Kenny Guy        mLauncherApps = LauncherAppsCompat.getInstance(mContext);
12053d7ee4285842732517edcccbdcaa92dccb1e107Sunny Goyal        mIconDpi = inv.fillResIconDpi;
12116affbdf30b51ada08391d1ece721dca61ba3deaSunny Goyal        mIconDb = new IconDB(context, inv.iconBitmapSize);
12234b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal
123756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal        mWorkerHandler = new Handler(LauncherModel.getWorkerLooper());
124360bc25ab6ae22869b867350b87ee7e82f06389aSunny Goyal
125360bc25ab6ae22869b867350b87ee7e82f06389aSunny Goyal        mActivityBgColor = context.getResources().getColor(R.color.quantum_panel_bg_color);
126360bc25ab6ae22869b867350b87ee7e82f06389aSunny Goyal        mPackageBgColor = context.getResources().getColor(R.color.quantum_panel_bg_color_dark);
127360bc25ab6ae22869b867350b87ee7e82f06389aSunny Goyal        mLowResOptions = new BitmapFactory.Options();
128360bc25ab6ae22869b867350b87ee7e82f06389aSunny Goyal        // Always prefer RGB_565 config for low res. If the bitmap has transparency, it will
129360bc25ab6ae22869b867350b87ee7e82f06389aSunny Goyal        // automatically be loaded as ALPHA_8888.
130360bc25ab6ae22869b867350b87ee7e82f06389aSunny Goyal        mLowResOptions.inPreferredConfig = Bitmap.Config.RGB_565;
131360bc25ab6ae22869b867350b87ee7e82f06389aSunny Goyal        updateSystemStateString();
132a28fd3fa7c82947d847c05ed11905f556b8dcfa2Romain Guy    }
133a28fd3fa7c82947d847c05ed11905f556b8dcfa2Romain Guy
1344fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal    private Drawable getFullResDefaultActivityIcon() {
135736f5af04cfb6f168c1f643874a7d3f82b5f51ccSunny Goyal        return getFullResIcon(Resources.getSystem(), android.R.mipmap.sym_def_app_icon);
136c9a961952d1a057029874f8426b90181f6876034Michael Jurka    }
137c9a961952d1a057029874f8426b90181f6876034Michael Jurka
138b50cc8c5d6125715b139d978887830a5341971aaSunny Goyal    private Drawable getFullResIcon(Resources resources, int iconId) {
139721d9725ad69b60ced5812ffce3afd1557f1180bMichael Jurka        Drawable d;
1404842ed029c5861b1696a9c69caa45f9a6e6e5f7eMichael Jurka        try {
141721d9725ad69b60ced5812ffce3afd1557f1180bMichael Jurka            d = resources.getDrawableForDensity(iconId, mIconDpi);
1424842ed029c5861b1696a9c69caa45f9a6e6e5f7eMichael Jurka        } catch (Resources.NotFoundException e) {
143721d9725ad69b60ced5812ffce3afd1557f1180bMichael Jurka            d = null;
1444842ed029c5861b1696a9c69caa45f9a6e6e5f7eMichael Jurka        }
145721d9725ad69b60ced5812ffce3afd1557f1180bMichael Jurka
146721d9725ad69b60ced5812ffce3afd1557f1180bMichael Jurka        return (d != null) ? d : getFullResDefaultActivityIcon();
147c9a961952d1a057029874f8426b90181f6876034Michael Jurka    }
148c9a961952d1a057029874f8426b90181f6876034Michael Jurka
1490b9fcf5686a24b237a1a52c13ef60ef776561b91Winson Chung    public Drawable getFullResIcon(String packageName, int iconId) {
150c9a961952d1a057029874f8426b90181f6876034Michael Jurka        Resources resources;
151c9a961952d1a057029874f8426b90181f6876034Michael Jurka        try {
1520b9fcf5686a24b237a1a52c13ef60ef776561b91Winson Chung            resources = mPackageManager.getResourcesForApplication(packageName);
1530b9fcf5686a24b237a1a52c13ef60ef776561b91Winson Chung        } catch (PackageManager.NameNotFoundException e) {
1540b9fcf5686a24b237a1a52c13ef60ef776561b91Winson Chung            resources = null;
1550b9fcf5686a24b237a1a52c13ef60ef776561b91Winson Chung        }
1560b9fcf5686a24b237a1a52c13ef60ef776561b91Winson Chung        if (resources != null) {
1570b9fcf5686a24b237a1a52c13ef60ef776561b91Winson Chung            if (iconId != 0) {
1580b9fcf5686a24b237a1a52c13ef60ef776561b91Winson Chung                return getFullResIcon(resources, iconId);
1590b9fcf5686a24b237a1a52c13ef60ef776561b91Winson Chung            }
1600b9fcf5686a24b237a1a52c13ef60ef776561b91Winson Chung        }
1610b9fcf5686a24b237a1a52c13ef60ef776561b91Winson Chung        return getFullResDefaultActivityIcon();
1620b9fcf5686a24b237a1a52c13ef60ef776561b91Winson Chung    }
1630b9fcf5686a24b237a1a52c13ef60ef776561b91Winson Chung
164dac8591072959f69eaa8c6319311fd111ae75db6Michael Jurka    public Drawable getFullResIcon(ActivityInfo info) {
1650b9fcf5686a24b237a1a52c13ef60ef776561b91Winson Chung        Resources resources;
1660b9fcf5686a24b237a1a52c13ef60ef776561b91Winson Chung        try {
1670b9fcf5686a24b237a1a52c13ef60ef776561b91Winson Chung            resources = mPackageManager.getResourcesForApplication(
168dac8591072959f69eaa8c6319311fd111ae75db6Michael Jurka                    info.applicationInfo);
169c9a961952d1a057029874f8426b90181f6876034Michael Jurka        } catch (PackageManager.NameNotFoundException e) {
170c9a961952d1a057029874f8426b90181f6876034Michael Jurka            resources = null;
171c9a961952d1a057029874f8426b90181f6876034Michael Jurka        }
172c9a961952d1a057029874f8426b90181f6876034Michael Jurka        if (resources != null) {
173dac8591072959f69eaa8c6319311fd111ae75db6Michael Jurka            int iconId = info.getIconResource();
174c9a961952d1a057029874f8426b90181f6876034Michael Jurka            if (iconId != 0) {
175c9a961952d1a057029874f8426b90181f6876034Michael Jurka                return getFullResIcon(resources, iconId);
176c9a961952d1a057029874f8426b90181f6876034Michael Jurka            }
177c9a961952d1a057029874f8426b90181f6876034Michael Jurka        }
1786d0dde01f307051ee1849481c989d9e87774b894Chris Wren
179c9a961952d1a057029874f8426b90181f6876034Michael Jurka        return getFullResDefaultActivityIcon();
180c9a961952d1a057029874f8426b90181f6876034Michael Jurka    }
181c9a961952d1a057029874f8426b90181f6876034Michael Jurka
182ed13187a745866483139e2878037e1f8427ce567Kenny Guy    private Bitmap makeDefaultIcon(UserHandleCompat user) {
183ed13187a745866483139e2878037e1f8427ce567Kenny Guy        Drawable unbadged = getFullResDefaultActivityIcon();
1840b621156f336b40418120948aa93933dd26e548dSunny Goyal        return Utilities.createBadgedIconBitmap(unbadged, user, mContext);
1850589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato    }
1860589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato
1870589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato    /**
1880589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato     * Remove any records for the supplied ComponentName.
1890589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato     */
190736f5af04cfb6f168c1f643874a7d3f82b5f51ccSunny Goyal    public synchronized void remove(ComponentName componentName, UserHandleCompat user) {
191b4cd42a1df69ec887d0c66e8fe6fe1f27ebbf9bcSunny Goyal        mCache.remove(new ComponentKey(componentName, user));
1920589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato    }
1930589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato
1940589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato    /**
1954fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal     * Remove any records for the supplied package name from memory.
1966d0dde01f307051ee1849481c989d9e87774b894Chris Wren     */
1974fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal    private void removeFromMemCacheLocked(String packageName, UserHandleCompat user) {
198b4cd42a1df69ec887d0c66e8fe6fe1f27ebbf9bcSunny Goyal        HashSet<ComponentKey> forDeletion = new HashSet<ComponentKey>();
199b4cd42a1df69ec887d0c66e8fe6fe1f27ebbf9bcSunny Goyal        for (ComponentKey key: mCache.keySet()) {
200ed13187a745866483139e2878037e1f8427ce567Kenny Guy            if (key.componentName.getPackageName().equals(packageName)
201ed13187a745866483139e2878037e1f8427ce567Kenny Guy                    && key.user.equals(user)) {
202ed13187a745866483139e2878037e1f8427ce567Kenny Guy                forDeletion.add(key);
2036d0dde01f307051ee1849481c989d9e87774b894Chris Wren            }
2046d0dde01f307051ee1849481c989d9e87774b894Chris Wren        }
205b4cd42a1df69ec887d0c66e8fe6fe1f27ebbf9bcSunny Goyal        for (ComponentKey condemned: forDeletion) {
206ed13187a745866483139e2878037e1f8427ce567Kenny Guy            mCache.remove(condemned);
2076d0dde01f307051ee1849481c989d9e87774b894Chris Wren        }
2086d0dde01f307051ee1849481c989d9e87774b894Chris Wren    }
2096d0dde01f307051ee1849481c989d9e87774b894Chris Wren
2106d0dde01f307051ee1849481c989d9e87774b894Chris Wren    /**
2114fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal     * Updates the entries related to the given package in memory and persistent DB.
2124fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal     */
2134fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal    public synchronized void updateIconsForPkg(String packageName, UserHandleCompat user) {
2144fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal        removeIconsForPkg(packageName, user);
2154fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal        try {
2164fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal            PackageInfo info = mPackageManager.getPackageInfo(packageName,
2174fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal                    PackageManager.GET_UNINSTALLED_PACKAGES);
2184fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal            long userSerial = mUserManager.getSerialNumberForUser(user);
2194fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal            for (LauncherActivityInfoCompat app : mLauncherApps.getActivityList(packageName, user)) {
220d180cf7e16d8dbd7d33980078baac7d09709b6cdSunny Goyal                addIconToDBAndMemCache(app, info, userSerial);
2214fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal            }
2224fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal        } catch (NameNotFoundException e) {
2234fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal            Log.d(TAG, "Package not found", e);
2244fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal            return;
2254fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal        }
2264fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal    }
2274fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal
2284fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal    /**
2294fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal     * Removes the entries related to the given package in memory and persistent DB.
2304fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal     */
2314fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal    public synchronized void removeIconsForPkg(String packageName, UserHandleCompat user) {
2324fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal        removeFromMemCacheLocked(packageName, user);
2334fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal        long userSerial = mUserManager.getSerialNumberForUser(user);
2346f70936f7fb7cb45ef6a2a3d1019b6ecf3e49440Sunny Goyal        mIconDb.delete(
2354fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal                IconDB.COLUMN_COMPONENT + " LIKE ? AND " + IconDB.COLUMN_USER + " = ?",
2366f70936f7fb7cb45ef6a2a3d1019b6ecf3e49440Sunny Goyal                new String[]{packageName + "/%", Long.toString(userSerial)});
2374fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal    }
2384fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal
2394e5cc64eaf1f63d866d51ce0a6bbafb3d4085c21Sunny Goyal    public void updateDbIcons(Set<String> ignorePackagesForMainUser) {
24075b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal        // Remove all active icon update tasks.
24175b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal        mWorkerHandler.removeCallbacksAndMessages(ICON_UPDATE_TOKEN);
24275b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal
243360bc25ab6ae22869b867350b87ee7e82f06389aSunny Goyal        updateSystemStateString();
24475b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal        for (UserHandleCompat user : mUserManager.getUserProfiles()) {
24575b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal            // Query for the set of apps
24675b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal            final List<LauncherActivityInfoCompat> apps = mLauncherApps.getActivityList(null, user);
24775b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal            // Fail if we don't have any apps
24875b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal            // TODO: Fix this. Only fail for the current user.
24975b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal            if (apps == null || apps.isEmpty()) {
25075b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal                return;
25175b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal            }
25275b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal
25375b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal            // Update icon cache. This happens in segments and {@link #onPackageIconsUpdated}
25475b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal            // is called by the icon cache when the job is complete.
2554e5cc64eaf1f63d866d51ce0a6bbafb3d4085c21Sunny Goyal            updateDBIcons(user, apps, UserHandleCompat.myUserHandle().equals(user)
2564e5cc64eaf1f63d866d51ce0a6bbafb3d4085c21Sunny Goyal                    ? ignorePackagesForMainUser : Collections.<String>emptySet());
25775b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal        }
25875b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal    }
25975b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal
2604fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal    /**
2614fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal     * Updates the persistent DB, such that only entries corresponding to {@param apps} remain in
2624fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal     * the DB and are updated.
2634fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal     * @return The set of packages for which icons have updated.
2644fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal     */
2654e5cc64eaf1f63d866d51ce0a6bbafb3d4085c21Sunny Goyal    private void updateDBIcons(UserHandleCompat user, List<LauncherActivityInfoCompat> apps,
2664e5cc64eaf1f63d866d51ce0a6bbafb3d4085c21Sunny Goyal            Set<String> ignorePackages) {
2674fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal        long userSerial = mUserManager.getSerialNumberForUser(user);
2684fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal        PackageManager pm = mContext.getPackageManager();
2694fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal        HashMap<String, PackageInfo> pkgInfoMap = new HashMap<String, PackageInfo>();
2704fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal        for (PackageInfo info : pm.getInstalledPackages(PackageManager.GET_UNINSTALLED_PACKAGES)) {
2714fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal            pkgInfoMap.put(info.packageName, info);
2724fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal        }
2734fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal
2744fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal        HashMap<ComponentName, LauncherActivityInfoCompat> componentMap = new HashMap<>();
2754fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal        for (LauncherActivityInfoCompat app : apps) {
2764fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal            componentMap.put(app.getComponentName(), app);
2774fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal        }
2784fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal
2794fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal        HashSet<Integer> itemsToRemove = new HashSet<Integer>();
28075b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal        Stack<LauncherActivityInfoCompat> appsToUpdate = new Stack<>();
2814fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal
2826f70936f7fb7cb45ef6a2a3d1019b6ecf3e49440Sunny Goyal        Cursor c = null;
2836f70936f7fb7cb45ef6a2a3d1019b6ecf3e49440Sunny Goyal        try {
2846f70936f7fb7cb45ef6a2a3d1019b6ecf3e49440Sunny Goyal            c = mIconDb.query(
2856f70936f7fb7cb45ef6a2a3d1019b6ecf3e49440Sunny Goyal                    new String[]{IconDB.COLUMN_ROWID, IconDB.COLUMN_COMPONENT,
2866f70936f7fb7cb45ef6a2a3d1019b6ecf3e49440Sunny Goyal                            IconDB.COLUMN_LAST_UPDATED, IconDB.COLUMN_VERSION,
2876f70936f7fb7cb45ef6a2a3d1019b6ecf3e49440Sunny Goyal                            IconDB.COLUMN_SYSTEM_STATE},
2886f70936f7fb7cb45ef6a2a3d1019b6ecf3e49440Sunny Goyal                    IconDB.COLUMN_USER + " = ? ",
2896f70936f7fb7cb45ef6a2a3d1019b6ecf3e49440Sunny Goyal                    new String[]{Long.toString(userSerial)});
2906f70936f7fb7cb45ef6a2a3d1019b6ecf3e49440Sunny Goyal
2916f70936f7fb7cb45ef6a2a3d1019b6ecf3e49440Sunny Goyal            final int indexComponent = c.getColumnIndex(IconDB.COLUMN_COMPONENT);
2926f70936f7fb7cb45ef6a2a3d1019b6ecf3e49440Sunny Goyal            final int indexLastUpdate = c.getColumnIndex(IconDB.COLUMN_LAST_UPDATED);
2936f70936f7fb7cb45ef6a2a3d1019b6ecf3e49440Sunny Goyal            final int indexVersion = c.getColumnIndex(IconDB.COLUMN_VERSION);
2946f70936f7fb7cb45ef6a2a3d1019b6ecf3e49440Sunny Goyal            final int rowIndex = c.getColumnIndex(IconDB.COLUMN_ROWID);
2956f70936f7fb7cb45ef6a2a3d1019b6ecf3e49440Sunny Goyal            final int systemStateIndex = c.getColumnIndex(IconDB.COLUMN_SYSTEM_STATE);
2966f70936f7fb7cb45ef6a2a3d1019b6ecf3e49440Sunny Goyal
2976f70936f7fb7cb45ef6a2a3d1019b6ecf3e49440Sunny Goyal            while (c.moveToNext()) {
2986f70936f7fb7cb45ef6a2a3d1019b6ecf3e49440Sunny Goyal                String cn = c.getString(indexComponent);
2996f70936f7fb7cb45ef6a2a3d1019b6ecf3e49440Sunny Goyal                ComponentName component = ComponentName.unflattenFromString(cn);
3006f70936f7fb7cb45ef6a2a3d1019b6ecf3e49440Sunny Goyal                PackageInfo info = pkgInfoMap.get(component.getPackageName());
3016f70936f7fb7cb45ef6a2a3d1019b6ecf3e49440Sunny Goyal                if (info == null) {
3026f70936f7fb7cb45ef6a2a3d1019b6ecf3e49440Sunny Goyal                    if (!ignorePackages.contains(component.getPackageName())) {
3036f70936f7fb7cb45ef6a2a3d1019b6ecf3e49440Sunny Goyal                        remove(component, user);
3046f70936f7fb7cb45ef6a2a3d1019b6ecf3e49440Sunny Goyal                        itemsToRemove.add(c.getInt(rowIndex));
3056f70936f7fb7cb45ef6a2a3d1019b6ecf3e49440Sunny Goyal                    }
3066f70936f7fb7cb45ef6a2a3d1019b6ecf3e49440Sunny Goyal                    continue;
3076f70936f7fb7cb45ef6a2a3d1019b6ecf3e49440Sunny Goyal                }
3086f70936f7fb7cb45ef6a2a3d1019b6ecf3e49440Sunny Goyal                if ((info.applicationInfo.flags & ApplicationInfo.FLAG_IS_DATA_ONLY) != 0) {
3096f70936f7fb7cb45ef6a2a3d1019b6ecf3e49440Sunny Goyal                    // Application is not present
3106f70936f7fb7cb45ef6a2a3d1019b6ecf3e49440Sunny Goyal                    continue;
3116f70936f7fb7cb45ef6a2a3d1019b6ecf3e49440Sunny Goyal                }
3126f70936f7fb7cb45ef6a2a3d1019b6ecf3e49440Sunny Goyal
3136f70936f7fb7cb45ef6a2a3d1019b6ecf3e49440Sunny Goyal                long updateTime = c.getLong(indexLastUpdate);
3146f70936f7fb7cb45ef6a2a3d1019b6ecf3e49440Sunny Goyal                int version = c.getInt(indexVersion);
3156f70936f7fb7cb45ef6a2a3d1019b6ecf3e49440Sunny Goyal                LauncherActivityInfoCompat app = componentMap.remove(component);
3166f70936f7fb7cb45ef6a2a3d1019b6ecf3e49440Sunny Goyal                if (version == info.versionCode && updateTime == info.lastUpdateTime &&
3176f70936f7fb7cb45ef6a2a3d1019b6ecf3e49440Sunny Goyal                        TextUtils.equals(mSystemState, c.getString(systemStateIndex))) {
3186f70936f7fb7cb45ef6a2a3d1019b6ecf3e49440Sunny Goyal                    continue;
3196f70936f7fb7cb45ef6a2a3d1019b6ecf3e49440Sunny Goyal                }
3206f70936f7fb7cb45ef6a2a3d1019b6ecf3e49440Sunny Goyal                if (app == null) {
3214e5cc64eaf1f63d866d51ce0a6bbafb3d4085c21Sunny Goyal                    remove(component, user);
3224e5cc64eaf1f63d866d51ce0a6bbafb3d4085c21Sunny Goyal                    itemsToRemove.add(c.getInt(rowIndex));
3236f70936f7fb7cb45ef6a2a3d1019b6ecf3e49440Sunny Goyal                } else {
3246f70936f7fb7cb45ef6a2a3d1019b6ecf3e49440Sunny Goyal                    appsToUpdate.add(app);
3254e5cc64eaf1f63d866d51ce0a6bbafb3d4085c21Sunny Goyal                }
3264fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal            }
3276f70936f7fb7cb45ef6a2a3d1019b6ecf3e49440Sunny Goyal        } catch (SQLiteException e) {
3286f70936f7fb7cb45ef6a2a3d1019b6ecf3e49440Sunny Goyal            Log.d(TAG, "Error reading icon cache", e);
3296f70936f7fb7cb45ef6a2a3d1019b6ecf3e49440Sunny Goyal            // Continue updating whatever we have read so far
3306f70936f7fb7cb45ef6a2a3d1019b6ecf3e49440Sunny Goyal        } finally {
3316f70936f7fb7cb45ef6a2a3d1019b6ecf3e49440Sunny Goyal            if (c != null) {
3326f70936f7fb7cb45ef6a2a3d1019b6ecf3e49440Sunny Goyal                c.close();
3334fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal            }
3344fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal        }
3354fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal        if (!itemsToRemove.isEmpty()) {
3366f70936f7fb7cb45ef6a2a3d1019b6ecf3e49440Sunny Goyal            mIconDb.delete(
3376f70936f7fb7cb45ef6a2a3d1019b6ecf3e49440Sunny Goyal                    Utilities.createDbSelectionQuery(IconDB.COLUMN_ROWID, itemsToRemove), null);
3384fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal        }
3394fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal
3404fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal        // Insert remaining apps.
34175b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal        if (!componentMap.isEmpty() || !appsToUpdate.isEmpty()) {
34275b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal            Stack<LauncherActivityInfoCompat> appsToAdd = new Stack<>();
34375b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal            appsToAdd.addAll(componentMap.values());
34475b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal            new SerializedIconUpdateTask(userSerial, pkgInfoMap,
34575b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal                    appsToAdd, appsToUpdate).scheduleNext();
3464fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal        }
3474fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal    }
3484fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal
349316490e636aad788fcfbfc2e04dd4f0e145bdd00Sunny Goyal    @Thunk void addIconToDBAndMemCache(LauncherActivityInfoCompat app, PackageInfo info,
350d180cf7e16d8dbd7d33980078baac7d09709b6cdSunny Goyal            long userSerial) {
3519ff980833d392244586ead8c27bbbba114e11ebbSunny Goyal        // Reuse the existing entry if it already exists in the DB. This ensures that we do not
3529ff980833d392244586ead8c27bbbba114e11ebbSunny Goyal        // create bitmap if it was already created during loader.
3539ff980833d392244586ead8c27bbbba114e11ebbSunny Goyal        ContentValues values = updateCacheAndGetContentValues(app, false);
354d180cf7e16d8dbd7d33980078baac7d09709b6cdSunny Goyal        addIconToDB(values, app.getComponentName(), info, userSerial);
355d180cf7e16d8dbd7d33980078baac7d09709b6cdSunny Goyal    }
356d180cf7e16d8dbd7d33980078baac7d09709b6cdSunny Goyal
357d180cf7e16d8dbd7d33980078baac7d09709b6cdSunny Goyal    /**
358d180cf7e16d8dbd7d33980078baac7d09709b6cdSunny Goyal     * Updates {@param values} to contain versoning information and adds it to the DB.
359d180cf7e16d8dbd7d33980078baac7d09709b6cdSunny Goyal     * @param values {@link ContentValues} containing icon & title
360d180cf7e16d8dbd7d33980078baac7d09709b6cdSunny Goyal     */
361d180cf7e16d8dbd7d33980078baac7d09709b6cdSunny Goyal    private void addIconToDB(ContentValues values, ComponentName key,
362d180cf7e16d8dbd7d33980078baac7d09709b6cdSunny Goyal            PackageInfo info, long userSerial) {
363d180cf7e16d8dbd7d33980078baac7d09709b6cdSunny Goyal        values.put(IconDB.COLUMN_COMPONENT, key.flattenToString());
3644fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal        values.put(IconDB.COLUMN_USER, userSerial);
3654fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal        values.put(IconDB.COLUMN_LAST_UPDATED, info.lastUpdateTime);
3664fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal        values.put(IconDB.COLUMN_VERSION, info.versionCode);
3676f70936f7fb7cb45ef6a2a3d1019b6ecf3e49440Sunny Goyal        mIconDb.insertOrReplace(values);
3684fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal    }
3694fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal
370316490e636aad788fcfbfc2e04dd4f0e145bdd00Sunny Goyal    @Thunk ContentValues updateCacheAndGetContentValues(LauncherActivityInfoCompat app,
3719ff980833d392244586ead8c27bbbba114e11ebbSunny Goyal            boolean replaceExisting) {
3729ff980833d392244586ead8c27bbbba114e11ebbSunny Goyal        final ComponentKey key = new ComponentKey(app.getComponentName(), app.getUser());
3739ff980833d392244586ead8c27bbbba114e11ebbSunny Goyal        CacheEntry entry = null;
3749ff980833d392244586ead8c27bbbba114e11ebbSunny Goyal        if (!replaceExisting) {
3759ff980833d392244586ead8c27bbbba114e11ebbSunny Goyal            entry = mCache.get(key);
3769ff980833d392244586ead8c27bbbba114e11ebbSunny Goyal            // We can't reuse the entry if the high-res icon is not present.
3779ff980833d392244586ead8c27bbbba114e11ebbSunny Goyal            if (entry == null || entry.isLowResIcon || entry.icon == null) {
3789ff980833d392244586ead8c27bbbba114e11ebbSunny Goyal                entry = null;
3799ff980833d392244586ead8c27bbbba114e11ebbSunny Goyal            }
3809ff980833d392244586ead8c27bbbba114e11ebbSunny Goyal        }
3819ff980833d392244586ead8c27bbbba114e11ebbSunny Goyal        if (entry == null) {
3829ff980833d392244586ead8c27bbbba114e11ebbSunny Goyal            entry = new CacheEntry();
3830b621156f336b40418120948aa93933dd26e548dSunny Goyal            entry.icon = Utilities.createBadgedIconBitmap(
3840b621156f336b40418120948aa93933dd26e548dSunny Goyal                    app.getIcon(mIconDpi), app.getUser(), mContext);
3859ff980833d392244586ead8c27bbbba114e11ebbSunny Goyal        }
3864fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal        entry.title = app.getLabel();
3874fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal        entry.contentDescription = mUserManager.getBadgedLabelForUser(entry.title, app.getUser());
388b4cd42a1df69ec887d0c66e8fe6fe1f27ebbf9bcSunny Goyal        mCache.put(new ComponentKey(app.getComponentName(), app.getUser()), entry);
3894fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal
390360bc25ab6ae22869b867350b87ee7e82f06389aSunny Goyal        return newContentValues(entry.icon, entry.title.toString(), mActivityBgColor);
3914fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal    }
3924fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal
3934fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal    /**
39434b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal     * Fetches high-res icon for the provided ItemInfo and updates the caller when done.
39534b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal     * @return a request ID that can be used to cancel the request.
3960589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato     */
39734b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal    public IconLoadRequest updateIconInBackground(final BubbleTextView caller, final ItemInfo info) {
39834b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal        Runnable request = new Runnable() {
39934b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal
40034b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal            @Override
40134b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal            public void run() {
40234b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal                if (info instanceof AppInfo) {
40334b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal                    getTitleAndIcon((AppInfo) info, null, false);
40434b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal                } else if (info instanceof ShortcutInfo) {
40534b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal                    ShortcutInfo st = (ShortcutInfo) info;
40634b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal                    getTitleAndIcon(st,
40734b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal                            st.promisedIntent != null ? st.promisedIntent : st.intent,
40834b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal                            st.user, false);
4090e08f166fafd5e2a0d32e27ea510516e3f762221Sunny Goyal                } else if (info instanceof PackageItemInfo) {
4100e08f166fafd5e2a0d32e27ea510516e3f762221Sunny Goyal                    PackageItemInfo pti = (PackageItemInfo) info;
4110e08f166fafd5e2a0d32e27ea510516e3f762221Sunny Goyal                    getTitleAndIconForApp(pti.packageName, pti.user, false, pti);
41234b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal                }
4138758ea050a9202e9733520898dda5d290644839eSunny Goyal                mMainThreadExecutor.execute(new Runnable() {
41434b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal
41534b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal                    @Override
41634b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal                    public void run() {
41734b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal                        caller.reapplyItemInfo(info);
41834b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal                    }
41934b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal                });
42034b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal            }
42134b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal        };
42234b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal        mWorkerHandler.post(request);
42334b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal        return new IconLoadRequest(request, mWorkerHandler);
42434b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal    }
4250589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato
426756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal    private Bitmap getNonNullIcon(CacheEntry entry, UserHandleCompat user) {
427756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal        return entry.icon == null ? getDefaultIcon(user) : entry.icon;
428756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal    }
429756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal
43034b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal    /**
43134b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal     * Fill in "application" with the icon and label for "info."
43234b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal     */
43334b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal    public synchronized void getTitleAndIcon(AppInfo application,
43434b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal            LauncherActivityInfoCompat info, boolean useLowResIcon) {
435756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal        UserHandleCompat user = info == null ? application.user : info.getUser();
436756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal        CacheEntry entry = cacheLocked(application.componentName, info, user,
43734b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal                false, useLowResIcon);
43882b016cb56540fe26213e817dd0dd668099c8e20Winson Chung        application.title = Utilities.trim(entry.title);
439756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal        application.iconBitmap = getNonNullIcon(entry, user);
440736f5af04cfb6f168c1f643874a7d3f82b5f51ccSunny Goyal        application.contentDescription = entry.contentDescription;
44134b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal        application.usingLowResIcon = entry.isLowResIcon;
4426d0dde01f307051ee1849481c989d9e87774b894Chris Wren    }
4436d0dde01f307051ee1849481c989d9e87774b894Chris Wren
44434b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal    /**
44577919b93b98f5afa1b39546861197d6065847224Sunny Goyal     * Updates {@param application} only if a valid entry is found.
44677919b93b98f5afa1b39546861197d6065847224Sunny Goyal     */
44777919b93b98f5afa1b39546861197d6065847224Sunny Goyal    public synchronized void updateTitleAndIcon(AppInfo application) {
44877919b93b98f5afa1b39546861197d6065847224Sunny Goyal        CacheEntry entry = cacheLocked(application.componentName, null, application.user,
44977919b93b98f5afa1b39546861197d6065847224Sunny Goyal                false, application.usingLowResIcon);
45077919b93b98f5afa1b39546861197d6065847224Sunny Goyal        if (entry.icon != null && !isDefaultIcon(entry.icon, application.user)) {
45182b016cb56540fe26213e817dd0dd668099c8e20Winson Chung            application.title = Utilities.trim(entry.title);
45277919b93b98f5afa1b39546861197d6065847224Sunny Goyal            application.iconBitmap = entry.icon;
45377919b93b98f5afa1b39546861197d6065847224Sunny Goyal            application.contentDescription = entry.contentDescription;
45477919b93b98f5afa1b39546861197d6065847224Sunny Goyal            application.usingLowResIcon = entry.isLowResIcon;
45577919b93b98f5afa1b39546861197d6065847224Sunny Goyal        }
45677919b93b98f5afa1b39546861197d6065847224Sunny Goyal    }
45777919b93b98f5afa1b39546861197d6065847224Sunny Goyal
45877919b93b98f5afa1b39546861197d6065847224Sunny Goyal    /**
45934b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal     * Returns a high res icon for the given intent and user
46034b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal     */
461736f5af04cfb6f168c1f643874a7d3f82b5f51ccSunny Goyal    public synchronized Bitmap getIcon(Intent intent, UserHandleCompat user) {
462736f5af04cfb6f168c1f643874a7d3f82b5f51ccSunny Goyal        ComponentName component = intent.getComponent();
463736f5af04cfb6f168c1f643874a7d3f82b5f51ccSunny Goyal        // null info means not installed, but if we have a component from the intent then
464736f5af04cfb6f168c1f643874a7d3f82b5f51ccSunny Goyal        // we should still look in the cache for restored app icons.
465736f5af04cfb6f168c1f643874a7d3f82b5f51ccSunny Goyal        if (component == null) {
466736f5af04cfb6f168c1f643874a7d3f82b5f51ccSunny Goyal            return getDefaultIcon(user);
467fad1fb5ed46473af0a6da4324e9e3fa45bd9f6e8Joe Onorato        }
468736f5af04cfb6f168c1f643874a7d3f82b5f51ccSunny Goyal
469736f5af04cfb6f168c1f643874a7d3f82b5f51ccSunny Goyal        LauncherActivityInfoCompat launcherActInfo = mLauncherApps.resolveActivity(intent, user);
47009d70195d7398f467f7efc5e0ed320b066865c76Sunny Goyal        CacheEntry entry = cacheLocked(component, launcherActInfo, user, true, false /* useLowRes */);
471736f5af04cfb6f168c1f643874a7d3f82b5f51ccSunny Goyal        return entry.icon;
4720589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato    }
4730589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato
474349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyal    /**
4754fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal     * Fill in {@param shortcutInfo} with the icon and label for {@param intent}. If the
4764fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal     * corresponding activity is not found, it reverts to the package icon.
477349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyal     */
478736f5af04cfb6f168c1f643874a7d3f82b5f51ccSunny Goyal    public synchronized void getTitleAndIcon(ShortcutInfo shortcutInfo, Intent intent,
47934b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal            UserHandleCompat user, boolean useLowResIcon) {
480736f5af04cfb6f168c1f643874a7d3f82b5f51ccSunny Goyal        ComponentName component = intent.getComponent();
481736f5af04cfb6f168c1f643874a7d3f82b5f51ccSunny Goyal        // null info means not installed, but if we have a component from the intent then
482736f5af04cfb6f168c1f643874a7d3f82b5f51ccSunny Goyal        // we should still look in the cache for restored app icons.
483736f5af04cfb6f168c1f643874a7d3f82b5f51ccSunny Goyal        if (component == null) {
484736f5af04cfb6f168c1f643874a7d3f82b5f51ccSunny Goyal            shortcutInfo.setIcon(getDefaultIcon(user));
485736f5af04cfb6f168c1f643874a7d3f82b5f51ccSunny Goyal            shortcutInfo.title = "";
486736f5af04cfb6f168c1f643874a7d3f82b5f51ccSunny Goyal            shortcutInfo.usingFallbackIcon = true;
48734b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal            shortcutInfo.usingLowResIcon = false;
488736f5af04cfb6f168c1f643874a7d3f82b5f51ccSunny Goyal        } else {
4894fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal            LauncherActivityInfoCompat info = mLauncherApps.resolveActivity(intent, user);
49034b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal            getTitleAndIcon(shortcutInfo, component, info, user, true, useLowResIcon);
491349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyal        }
492349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyal    }
493349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyal
4944fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal    /**
4954fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal     * Fill in {@param shortcutInfo} with the icon and label for {@param info}
4964fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal     */
4974fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal    public synchronized void getTitleAndIcon(
4984fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal            ShortcutInfo shortcutInfo, ComponentName component, LauncherActivityInfoCompat info,
49934b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal            UserHandleCompat user, boolean usePkgIcon, boolean useLowResIcon) {
50034b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal        CacheEntry entry = cacheLocked(component, info, user, usePkgIcon, useLowResIcon);
501756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal        shortcutInfo.setIcon(getNonNullIcon(entry, user));
50282b016cb56540fe26213e817dd0dd668099c8e20Winson Chung        shortcutInfo.title = Utilities.trim(entry.title);
5034fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal        shortcutInfo.usingFallbackIcon = isDefaultIcon(entry.icon, user);
50434b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal        shortcutInfo.usingLowResIcon = entry.isLowResIcon;
5054fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal    }
506349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyal
507d180cf7e16d8dbd7d33980078baac7d09709b6cdSunny Goyal    /**
508d180cf7e16d8dbd7d33980078baac7d09709b6cdSunny Goyal     * Fill in {@param appInfo} with the icon and label for {@param packageName}
509d180cf7e16d8dbd7d33980078baac7d09709b6cdSunny Goyal     */
510d180cf7e16d8dbd7d33980078baac7d09709b6cdSunny Goyal    public synchronized void getTitleAndIconForApp(
5113f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song            String packageName, UserHandleCompat user, boolean useLowResIcon,
5123f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song            PackageItemInfo infoOut) {
513d180cf7e16d8dbd7d33980078baac7d09709b6cdSunny Goyal        CacheEntry entry = getEntryForPackageLocked(packageName, user, useLowResIcon);
514756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal        infoOut.iconBitmap = getNonNullIcon(entry, user);
51582b016cb56540fe26213e817dd0dd668099c8e20Winson Chung        infoOut.title = Utilities.trim(entry.title);
5163f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song        infoOut.usingLowResIcon = entry.isLowResIcon;
5173f471440a8b6b71d4c15501a96befd3b715c9e8fHyunyoung Song        infoOut.contentDescription = entry.contentDescription;
518d180cf7e16d8dbd7d33980078baac7d09709b6cdSunny Goyal    }
519d180cf7e16d8dbd7d33980078baac7d09709b6cdSunny Goyal
520736f5af04cfb6f168c1f643874a7d3f82b5f51ccSunny Goyal    public synchronized Bitmap getDefaultIcon(UserHandleCompat user) {
521ed13187a745866483139e2878037e1f8427ce567Kenny Guy        if (!mDefaultIcons.containsKey(user)) {
522ed13187a745866483139e2878037e1f8427ce567Kenny Guy            mDefaultIcons.put(user, makeDefaultIcon(user));
523ed13187a745866483139e2878037e1f8427ce567Kenny Guy        }
524ed13187a745866483139e2878037e1f8427ce567Kenny Guy        return mDefaultIcons.get(user);
525ed13187a745866483139e2878037e1f8427ce567Kenny Guy    }
526ed13187a745866483139e2878037e1f8427ce567Kenny Guy
527ed13187a745866483139e2878037e1f8427ce567Kenny Guy    public boolean isDefaultIcon(Bitmap icon, UserHandleCompat user) {
528ed13187a745866483139e2878037e1f8427ce567Kenny Guy        return mDefaultIcons.get(user) == icon;
529ddc9c1fb1ab426772add520d277ea9c2cd674094Joe Onorato    }
530ddc9c1fb1ab426772add520d277ea9c2cd674094Joe Onorato
531736f5af04cfb6f168c1f643874a7d3f82b5f51ccSunny Goyal    /**
532736f5af04cfb6f168c1f643874a7d3f82b5f51ccSunny Goyal     * Retrieves the entry from the cache. If the entry is not present, it creates a new entry.
533736f5af04cfb6f168c1f643874a7d3f82b5f51ccSunny Goyal     * This method is not thread safe, it must be called from a synchronized method.
534736f5af04cfb6f168c1f643874a7d3f82b5f51ccSunny Goyal     */
535ed13187a745866483139e2878037e1f8427ce567Kenny Guy    private CacheEntry cacheLocked(ComponentName componentName, LauncherActivityInfoCompat info,
53634b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal            UserHandleCompat user, boolean usePackageIcon, boolean useLowResIcon) {
537b4cd42a1df69ec887d0c66e8fe6fe1f27ebbf9bcSunny Goyal        ComponentKey cacheKey = new ComponentKey(componentName, user);
538ed13187a745866483139e2878037e1f8427ce567Kenny Guy        CacheEntry entry = mCache.get(cacheKey);
53934b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal        if (entry == null || (entry.isLowResIcon && !useLowResIcon)) {
5400589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato            entry = new CacheEntry();
541ed13187a745866483139e2878037e1f8427ce567Kenny Guy            mCache.put(cacheKey, entry);
54284f6a8d613cef3227afa508c77221959dcf2f2d7Joe Onorato
5434fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal            // Check the DB first.
54453f9672b30b8a36bfae9f6492f732ccfb87723a4Sunny Goyal            if (!getEntryFromDB(cacheKey, entry, useLowResIcon)) {
5454fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal                if (info != null) {
5460b621156f336b40418120948aa93933dd26e548dSunny Goyal                    entry.icon = Utilities.createBadgedIconBitmap(
5470b621156f336b40418120948aa93933dd26e548dSunny Goyal                            info.getIcon(mIconDpi), info.getUser(), mContext);
5486d0dde01f307051ee1849481c989d9e87774b894Chris Wren                } else {
5490fc1be164e982433e619bcbb16aa67e28ff681efSunny Goyal                    if (usePackageIcon) {
550d180cf7e16d8dbd7d33980078baac7d09709b6cdSunny Goyal                        CacheEntry packageEntry = getEntryForPackageLocked(
551d180cf7e16d8dbd7d33980078baac7d09709b6cdSunny Goyal                                componentName.getPackageName(), user, false);
552349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyal                        if (packageEntry != null) {
5530fc1be164e982433e619bcbb16aa67e28ff681efSunny Goyal                            if (DEBUG) Log.d(TAG, "using package default icon for " +
5540fc1be164e982433e619bcbb16aa67e28ff681efSunny Goyal                                    componentName.toShortString());
5550fc1be164e982433e619bcbb16aa67e28ff681efSunny Goyal                            entry.icon = packageEntry.icon;
556349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyal                            entry.title = packageEntry.title;
5574fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal                            entry.contentDescription = packageEntry.contentDescription;
5580fc1be164e982433e619bcbb16aa67e28ff681efSunny Goyal                        }
5590fc1be164e982433e619bcbb16aa67e28ff681efSunny Goyal                    }
5600fc1be164e982433e619bcbb16aa67e28ff681efSunny Goyal                    if (entry.icon == null) {
5610fc1be164e982433e619bcbb16aa67e28ff681efSunny Goyal                        if (DEBUG) Log.d(TAG, "using default icon for " +
5620fc1be164e982433e619bcbb16aa67e28ff681efSunny Goyal                                componentName.toShortString());
5630fc1be164e982433e619bcbb16aa67e28ff681efSunny Goyal                        entry.icon = getDefaultIcon(user);
5640fc1be164e982433e619bcbb16aa67e28ff681efSunny Goyal                    }
565c3eecff9043759926df124483b45fe8f4436ae7cWinson Chung                }
566c3eecff9043759926df124483b45fe8f4436ae7cWinson Chung            }
5674fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal
5684fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal            if (TextUtils.isEmpty(entry.title) && info != null) {
56982b016cb56540fe26213e817dd0dd668099c8e20Winson Chung                entry.title = info.getLabel();
5704fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal                entry.contentDescription = mUserManager.getBadgedLabelForUser(entry.title, user);
5714fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal            }
5720589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato        }
5730589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato        return entry;
5740589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato    }
5754e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler
5760fc1be164e982433e619bcbb16aa67e28ff681efSunny Goyal    /**
577349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyal     * Adds a default package entry in the cache. This entry is not persisted and will be removed
578349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyal     * when the cache is flushed.
579349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyal     */
580736f5af04cfb6f168c1f643874a7d3f82b5f51ccSunny Goyal    public synchronized void cachePackageInstallInfo(String packageName, UserHandleCompat user,
581349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyal            Bitmap icon, CharSequence title) {
5824fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal        removeFromMemCacheLocked(packageName, user);
583a22666f68151269853e7ab6ab696ee6361bac793Sunny Goyal
58453f9672b30b8a36bfae9f6492f732ccfb87723a4Sunny Goyal        ComponentKey cacheKey = getPackageKey(packageName, user);
58553f9672b30b8a36bfae9f6492f732ccfb87723a4Sunny Goyal        CacheEntry entry = mCache.get(cacheKey);
58653f9672b30b8a36bfae9f6492f732ccfb87723a4Sunny Goyal
58753f9672b30b8a36bfae9f6492f732ccfb87723a4Sunny Goyal        // For icon caching, do not go through DB. Just update the in-memory entry.
58853f9672b30b8a36bfae9f6492f732ccfb87723a4Sunny Goyal        if (entry == null) {
58953f9672b30b8a36bfae9f6492f732ccfb87723a4Sunny Goyal            entry = new CacheEntry();
59053f9672b30b8a36bfae9f6492f732ccfb87723a4Sunny Goyal            mCache.put(cacheKey, entry);
59153f9672b30b8a36bfae9f6492f732ccfb87723a4Sunny Goyal        }
592349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyal        if (!TextUtils.isEmpty(title)) {
593349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyal            entry.title = title;
594349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyal        }
595349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyal        if (icon != null) {
5962fce90c38a79d318e96a28107dea287e42509861Sunny Goyal            entry.icon = Utilities.createIconBitmap(icon, mContext);
597349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyal        }
598349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyal    }
599349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyal
60053f9672b30b8a36bfae9f6492f732ccfb87723a4Sunny Goyal    private static ComponentKey getPackageKey(String packageName, UserHandleCompat user) {
60153f9672b30b8a36bfae9f6492f732ccfb87723a4Sunny Goyal        ComponentName cn = new ComponentName(packageName, packageName + EMPTY_CLASS_NAME);
60253f9672b30b8a36bfae9f6492f732ccfb87723a4Sunny Goyal        return new ComponentKey(cn, user);
60353f9672b30b8a36bfae9f6492f732ccfb87723a4Sunny Goyal    }
60453f9672b30b8a36bfae9f6492f732ccfb87723a4Sunny Goyal
605349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyal    /**
6060fc1be164e982433e619bcbb16aa67e28ff681efSunny Goyal     * Gets an entry for the package, which can be used as a fallback entry for various components.
607736f5af04cfb6f168c1f643874a7d3f82b5f51ccSunny Goyal     * This method is not thread safe, it must be called from a synchronized method.
6080fc1be164e982433e619bcbb16aa67e28ff681efSunny Goyal     */
609d180cf7e16d8dbd7d33980078baac7d09709b6cdSunny Goyal    private CacheEntry getEntryForPackageLocked(String packageName, UserHandleCompat user,
610d180cf7e16d8dbd7d33980078baac7d09709b6cdSunny Goyal            boolean useLowResIcon) {
61153f9672b30b8a36bfae9f6492f732ccfb87723a4Sunny Goyal        ComponentKey cacheKey = getPackageKey(packageName, user);
6120fc1be164e982433e619bcbb16aa67e28ff681efSunny Goyal        CacheEntry entry = mCache.get(cacheKey);
613091f0ffd929f7a0a9a6af7d202eae13c48c07daaSunny Goyal
614d180cf7e16d8dbd7d33980078baac7d09709b6cdSunny Goyal        if (entry == null || (entry.isLowResIcon && !useLowResIcon)) {
6150fc1be164e982433e619bcbb16aa67e28ff681efSunny Goyal            entry = new CacheEntry();
616cdefc631f8b4b3e56ea3bd238d46d0bc9e28eabeWinson Chung            boolean entryUpdated = true;
6170fc1be164e982433e619bcbb16aa67e28ff681efSunny Goyal
618d180cf7e16d8dbd7d33980078baac7d09709b6cdSunny Goyal            // Check the DB first.
61953f9672b30b8a36bfae9f6492f732ccfb87723a4Sunny Goyal            if (!getEntryFromDB(cacheKey, entry, useLowResIcon)) {
620d180cf7e16d8dbd7d33980078baac7d09709b6cdSunny Goyal                try {
621a8b244e5b83e4e773411c134c7a8df2a2392fb44Sunny Goyal                    int flags = UserHandleCompat.myUserHandle().equals(user) ? 0 :
622a8b244e5b83e4e773411c134c7a8df2a2392fb44Sunny Goyal                        PackageManager.GET_UNINSTALLED_PACKAGES;
623a8b244e5b83e4e773411c134c7a8df2a2392fb44Sunny Goyal                    PackageInfo info = mPackageManager.getPackageInfo(packageName, flags);
624d180cf7e16d8dbd7d33980078baac7d09709b6cdSunny Goyal                    ApplicationInfo appInfo = info.applicationInfo;
625d180cf7e16d8dbd7d33980078baac7d09709b6cdSunny Goyal                    if (appInfo == null) {
626d180cf7e16d8dbd7d33980078baac7d09709b6cdSunny Goyal                        throw new NameNotFoundException("ApplicationInfo is null");
627d180cf7e16d8dbd7d33980078baac7d09709b6cdSunny Goyal                    }
6280b621156f336b40418120948aa93933dd26e548dSunny Goyal                    entry.icon = Utilities.createBadgedIconBitmap(
6290b621156f336b40418120948aa93933dd26e548dSunny Goyal                            appInfo.loadIcon(mPackageManager), user, mContext);
630d180cf7e16d8dbd7d33980078baac7d09709b6cdSunny Goyal                    entry.title = appInfo.loadLabel(mPackageManager);
631d180cf7e16d8dbd7d33980078baac7d09709b6cdSunny Goyal                    entry.contentDescription = mUserManager.getBadgedLabelForUser(entry.title, user);
632d180cf7e16d8dbd7d33980078baac7d09709b6cdSunny Goyal                    entry.isLowResIcon = false;
633d180cf7e16d8dbd7d33980078baac7d09709b6cdSunny Goyal
634d180cf7e16d8dbd7d33980078baac7d09709b6cdSunny Goyal                    // Add the icon in the DB here, since these do not get written during
635d180cf7e16d8dbd7d33980078baac7d09709b6cdSunny Goyal                    // package updates.
636d180cf7e16d8dbd7d33980078baac7d09709b6cdSunny Goyal                    ContentValues values =
637360bc25ab6ae22869b867350b87ee7e82f06389aSunny Goyal                            newContentValues(entry.icon, entry.title.toString(), mPackageBgColor);
63853f9672b30b8a36bfae9f6492f732ccfb87723a4Sunny Goyal                    addIconToDB(values, cacheKey.componentName, info,
63953f9672b30b8a36bfae9f6492f732ccfb87723a4Sunny Goyal                            mUserManager.getSerialNumberForUser(user));
640d180cf7e16d8dbd7d33980078baac7d09709b6cdSunny Goyal
641d180cf7e16d8dbd7d33980078baac7d09709b6cdSunny Goyal                } catch (NameNotFoundException e) {
642d180cf7e16d8dbd7d33980078baac7d09709b6cdSunny Goyal                    if (DEBUG) Log.d(TAG, "Application not installed " + packageName);
643cdefc631f8b4b3e56ea3bd238d46d0bc9e28eabeWinson Chung                    entryUpdated = false;
644d180cf7e16d8dbd7d33980078baac7d09709b6cdSunny Goyal                }
6450fc1be164e982433e619bcbb16aa67e28ff681efSunny Goyal            }
646cdefc631f8b4b3e56ea3bd238d46d0bc9e28eabeWinson Chung
647cdefc631f8b4b3e56ea3bd238d46d0bc9e28eabeWinson Chung            // Only add a filled-out entry to the cache
648cdefc631f8b4b3e56ea3bd238d46d0bc9e28eabeWinson Chung            if (entryUpdated) {
649cdefc631f8b4b3e56ea3bd238d46d0bc9e28eabeWinson Chung                mCache.put(cacheKey, entry);
650cdefc631f8b4b3e56ea3bd238d46d0bc9e28eabeWinson Chung            }
6510fc1be164e982433e619bcbb16aa67e28ff681efSunny Goyal        }
6520fc1be164e982433e619bcbb16aa67e28ff681efSunny Goyal        return entry;
6530fc1be164e982433e619bcbb16aa67e28ff681efSunny Goyal    }
6540fc1be164e982433e619bcbb16aa67e28ff681efSunny Goyal
6556d0dde01f307051ee1849481c989d9e87774b894Chris Wren    /**
6566d0dde01f307051ee1849481c989d9e87774b894Chris Wren     * Pre-load an icon into the persistent cache.
6576d0dde01f307051ee1849481c989d9e87774b894Chris Wren     *
6586d0dde01f307051ee1849481c989d9e87774b894Chris Wren     * <P>Queries for a component that does not exist in the package manager
6596d0dde01f307051ee1849481c989d9e87774b894Chris Wren     * will be answered by the persistent cache.
6606d0dde01f307051ee1849481c989d9e87774b894Chris Wren     *
6616d0dde01f307051ee1849481c989d9e87774b894Chris Wren     * @param componentName the icon should be returned for this component
6626d0dde01f307051ee1849481c989d9e87774b894Chris Wren     * @param icon the icon to be persisted
6636d0dde01f307051ee1849481c989d9e87774b894Chris Wren     * @param dpi the native density of the icon
6646d0dde01f307051ee1849481c989d9e87774b894Chris Wren     */
6654fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal    public void preloadIcon(ComponentName componentName, Bitmap icon, int dpi, String label,
666df6ccf81960ab73d46570d56443e94c4df48e0c8Sunny Goyal            long userSerial, InvariantDeviceProfile idp) {
6676d0dde01f307051ee1849481c989d9e87774b894Chris Wren        // TODO rescale to the correct native DPI
6686d0dde01f307051ee1849481c989d9e87774b894Chris Wren        try {
6694fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal            PackageManager packageManager = mContext.getPackageManager();
6706d0dde01f307051ee1849481c989d9e87774b894Chris Wren            packageManager.getActivityIcon(componentName);
6716d0dde01f307051ee1849481c989d9e87774b894Chris Wren            // component is present on the system already, do nothing
6726d0dde01f307051ee1849481c989d9e87774b894Chris Wren            return;
6736d0dde01f307051ee1849481c989d9e87774b894Chris Wren        } catch (PackageManager.NameNotFoundException e) {
6746d0dde01f307051ee1849481c989d9e87774b894Chris Wren            // pass
6756d0dde01f307051ee1849481c989d9e87774b894Chris Wren        }
6766d0dde01f307051ee1849481c989d9e87774b894Chris Wren
677df6ccf81960ab73d46570d56443e94c4df48e0c8Sunny Goyal        ContentValues values = newContentValues(
678df6ccf81960ab73d46570d56443e94c4df48e0c8Sunny Goyal                Bitmap.createScaledBitmap(icon, idp.iconBitmapSize, idp.iconBitmapSize, true),
679df6ccf81960ab73d46570d56443e94c4df48e0c8Sunny Goyal                label, Color.TRANSPARENT);
6804fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal        values.put(IconDB.COLUMN_COMPONENT, componentName.flattenToString());
6814fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal        values.put(IconDB.COLUMN_USER, userSerial);
6826f70936f7fb7cb45ef6a2a3d1019b6ecf3e49440Sunny Goyal        mIconDb.insertOrReplace(values);
6834fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal    }
6844fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal
68553f9672b30b8a36bfae9f6492f732ccfb87723a4Sunny Goyal    private boolean getEntryFromDB(ComponentKey cacheKey, CacheEntry entry, boolean lowRes) {
6866f70936f7fb7cb45ef6a2a3d1019b6ecf3e49440Sunny Goyal        Cursor c = null;
6876f70936f7fb7cb45ef6a2a3d1019b6ecf3e49440Sunny Goyal        try {
6886f70936f7fb7cb45ef6a2a3d1019b6ecf3e49440Sunny Goyal            c = mIconDb.query(
6896f70936f7fb7cb45ef6a2a3d1019b6ecf3e49440Sunny Goyal                new String[]{lowRes ? IconDB.COLUMN_ICON_LOW_RES : IconDB.COLUMN_ICON,
69034b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal                        IconDB.COLUMN_LABEL},
6914fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal                IconDB.COLUMN_COMPONENT + " = ? AND " + IconDB.COLUMN_USER + " = ?",
6926f70936f7fb7cb45ef6a2a3d1019b6ecf3e49440Sunny Goyal                new String[]{cacheKey.componentName.flattenToString(),
6936f70936f7fb7cb45ef6a2a3d1019b6ecf3e49440Sunny Goyal                        Long.toString(mUserManager.getSerialNumberForUser(cacheKey.user))});
6944fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal            if (c.moveToNext()) {
695360bc25ab6ae22869b867350b87ee7e82f06389aSunny Goyal                entry.icon = loadIconNoResize(c, 0, lowRes ? mLowResOptions : null);
69634b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal                entry.isLowResIcon = lowRes;
6974fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal                entry.title = c.getString(1);
6984fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal                if (entry.title == null) {
6994fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal                    entry.title = "";
7004fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal                    entry.contentDescription = "";
7014fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal                } else {
70253f9672b30b8a36bfae9f6492f732ccfb87723a4Sunny Goyal                    entry.contentDescription = mUserManager.getBadgedLabelForUser(
70353f9672b30b8a36bfae9f6492f732ccfb87723a4Sunny Goyal                            entry.title, cacheKey.user);
7046d0dde01f307051ee1849481c989d9e87774b894Chris Wren                }
7054fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal                return true;
7066d0dde01f307051ee1849481c989d9e87774b894Chris Wren            }
7076f70936f7fb7cb45ef6a2a3d1019b6ecf3e49440Sunny Goyal        } catch (SQLiteException e) {
7086f70936f7fb7cb45ef6a2a3d1019b6ecf3e49440Sunny Goyal            Log.d(TAG, "Error reading icon cache", e);
7094fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal        } finally {
7106f70936f7fb7cb45ef6a2a3d1019b6ecf3e49440Sunny Goyal            if (c != null) {
7116f70936f7fb7cb45ef6a2a3d1019b6ecf3e49440Sunny Goyal                c.close();
7126f70936f7fb7cb45ef6a2a3d1019b6ecf3e49440Sunny Goyal            }
7136d0dde01f307051ee1849481c989d9e87774b894Chris Wren        }
7144fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal        return false;
7156d0dde01f307051ee1849481c989d9e87774b894Chris Wren    }
7166d0dde01f307051ee1849481c989d9e87774b894Chris Wren
71734b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal    public static class IconLoadRequest {
71834b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal        private final Runnable mRunnable;
71934b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal        private final Handler mHandler;
72034b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal
72134b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal        IconLoadRequest(Runnable runnable, Handler handler) {
72234b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal            mRunnable = runnable;
72334b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal            mHandler = handler;
72434b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal        }
72534b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal
72634b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal        public void cancel() {
72734b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal            mHandler.removeCallbacks(mRunnable);
72834b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal        }
72934b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal    }
73034b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal
7319ff980833d392244586ead8c27bbbba114e11ebbSunny Goyal    /**
73275b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal     * A runnable that updates invalid icons and adds missing icons in the DB for the provided
73375b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal     * LauncherActivityInfoCompat list. Items are updated/added one at a time, so that the
73475b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal     * worker thread doesn't get blocked.
7359ff980833d392244586ead8c27bbbba114e11ebbSunny Goyal     */
736316490e636aad788fcfbfc2e04dd4f0e145bdd00Sunny Goyal    @Thunk class SerializedIconUpdateTask implements Runnable {
7379ff980833d392244586ead8c27bbbba114e11ebbSunny Goyal        private final long mUserSerial;
7389ff980833d392244586ead8c27bbbba114e11ebbSunny Goyal        private final HashMap<String, PackageInfo> mPkgInfoMap;
7399ff980833d392244586ead8c27bbbba114e11ebbSunny Goyal        private final Stack<LauncherActivityInfoCompat> mAppsToAdd;
74075b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal        private final Stack<LauncherActivityInfoCompat> mAppsToUpdate;
74175b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal        private final HashSet<String> mUpdatedPackages = new HashSet<String>();
7429ff980833d392244586ead8c27bbbba114e11ebbSunny Goyal
743316490e636aad788fcfbfc2e04dd4f0e145bdd00Sunny Goyal        @Thunk SerializedIconUpdateTask(long userSerial, HashMap<String, PackageInfo> pkgInfoMap,
74475b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal                Stack<LauncherActivityInfoCompat> appsToAdd,
74575b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal                Stack<LauncherActivityInfoCompat> appsToUpdate) {
7469ff980833d392244586ead8c27bbbba114e11ebbSunny Goyal            mUserSerial = userSerial;
7479ff980833d392244586ead8c27bbbba114e11ebbSunny Goyal            mPkgInfoMap = pkgInfoMap;
74875b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal            mAppsToAdd = appsToAdd;
74975b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal            mAppsToUpdate = appsToUpdate;
7509ff980833d392244586ead8c27bbbba114e11ebbSunny Goyal        }
7519ff980833d392244586ead8c27bbbba114e11ebbSunny Goyal
7529ff980833d392244586ead8c27bbbba114e11ebbSunny Goyal        @Override
7539ff980833d392244586ead8c27bbbba114e11ebbSunny Goyal        public void run() {
75475b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal            if (!mAppsToUpdate.isEmpty()) {
75575b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal                LauncherActivityInfoCompat app = mAppsToUpdate.pop();
75675b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal                String cn = app.getComponentName().flattenToString();
75775b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal                ContentValues values = updateCacheAndGetContentValues(app, true);
7586f70936f7fb7cb45ef6a2a3d1019b6ecf3e49440Sunny Goyal                mIconDb.update(values,
75975b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal                        IconDB.COLUMN_COMPONENT + " = ? AND " + IconDB.COLUMN_USER + " = ?",
7606f70936f7fb7cb45ef6a2a3d1019b6ecf3e49440Sunny Goyal                        new String[]{cn, Long.toString(mUserSerial)});
76175b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal                mUpdatedPackages.add(app.getComponentName().getPackageName());
76275b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal
76375b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal                if (mAppsToUpdate.isEmpty() && !mUpdatedPackages.isEmpty()) {
76475b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal                    // No more app to update. Notify model.
76575b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal                    LauncherAppState.getInstance().getModel().onPackageIconsUpdated(
76675b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal                            mUpdatedPackages, mUserManager.getUserForSerialNumber(mUserSerial));
76775b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal                }
76875b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal
76975b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal                // Let it run one more time.
77075b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal                scheduleNext();
77175b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal            } else if (!mAppsToAdd.isEmpty()) {
7729ff980833d392244586ead8c27bbbba114e11ebbSunny Goyal                LauncherActivityInfoCompat app = mAppsToAdd.pop();
7739ff980833d392244586ead8c27bbbba114e11ebbSunny Goyal                PackageInfo info = mPkgInfoMap.get(app.getComponentName().getPackageName());
7749ff980833d392244586ead8c27bbbba114e11ebbSunny Goyal                if (info != null) {
7759ff980833d392244586ead8c27bbbba114e11ebbSunny Goyal                    synchronized (IconCache.this) {
7769ff980833d392244586ead8c27bbbba114e11ebbSunny Goyal                        addIconToDBAndMemCache(app, info, mUserSerial);
7779ff980833d392244586ead8c27bbbba114e11ebbSunny Goyal                    }
7789ff980833d392244586ead8c27bbbba114e11ebbSunny Goyal                }
77975b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal
78075b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal                if (!mAppsToAdd.isEmpty()) {
78175b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal                    scheduleNext();
78275b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal                }
7839ff980833d392244586ead8c27bbbba114e11ebbSunny Goyal            }
78475b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal        }
78575b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal
78675b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal        public void scheduleNext() {
78775b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal            mWorkerHandler.postAtTime(this, ICON_UPDATE_TOKEN, SystemClock.uptimeMillis() + 1);
7889ff980833d392244586ead8c27bbbba114e11ebbSunny Goyal        }
7899ff980833d392244586ead8c27bbbba114e11ebbSunny Goyal    }
7909ff980833d392244586ead8c27bbbba114e11ebbSunny Goyal
791360bc25ab6ae22869b867350b87ee7e82f06389aSunny Goyal    private void updateSystemStateString() {
792360bc25ab6ae22869b867350b87ee7e82f06389aSunny Goyal        mSystemState = Locale.getDefault().toString();
793360bc25ab6ae22869b867350b87ee7e82f06389aSunny Goyal    }
794360bc25ab6ae22869b867350b87ee7e82f06389aSunny Goyal
7956f70936f7fb7cb45ef6a2a3d1019b6ecf3e49440Sunny Goyal    private static final class IconDB extends SQLiteCacheHelper {
7962b84b652b33977d82e0af4ab9fdc7a97cb8d5a33Sunny Goyal        private final static int DB_VERSION = 7;
7976d0dde01f307051ee1849481c989d9e87774b894Chris Wren
798d896ee43cd9195a2a2742324733b036ee72875bbSunny Goyal        private final static int RELEASE_VERSION = DB_VERSION +
799d896ee43cd9195a2a2742324733b036ee72875bbSunny Goyal                (FeatureFlags.LAUNCHER3_ICON_NORMALIZATION ? 1 : 0);
800d896ee43cd9195a2a2742324733b036ee72875bbSunny Goyal
8014fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal        private final static String TABLE_NAME = "icons";
8024fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal        private final static String COLUMN_ROWID = "rowid";
8034fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal        private final static String COLUMN_COMPONENT = "componentName";
8044fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal        private final static String COLUMN_USER = "profileId";
8054fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal        private final static String COLUMN_LAST_UPDATED = "lastUpdated";
8064fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal        private final static String COLUMN_VERSION = "version";
8074fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal        private final static String COLUMN_ICON = "icon";
80834b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal        private final static String COLUMN_ICON_LOW_RES = "icon_low_res";
8094fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal        private final static String COLUMN_LABEL = "label";
8100c9a354c9732585620569bafaec0973977baf614Sunny Goyal        private final static String COLUMN_SYSTEM_STATE = "system_state";
8110c9a354c9732585620569bafaec0973977baf614Sunny Goyal
81216affbdf30b51ada08391d1ece721dca61ba3deaSunny Goyal        public IconDB(Context context, int iconPixelSize) {
81316affbdf30b51ada08391d1ece721dca61ba3deaSunny Goyal            super(context, LauncherFiles.APP_ICONS_DB,
81416affbdf30b51ada08391d1ece721dca61ba3deaSunny Goyal                    (RELEASE_VERSION << 16) + iconPixelSize,
81516affbdf30b51ada08391d1ece721dca61ba3deaSunny Goyal                    TABLE_NAME);
816ed13187a745866483139e2878037e1f8427ce567Kenny Guy        }
817ed13187a745866483139e2878037e1f8427ce567Kenny Guy
8184fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal        @Override
8196f70936f7fb7cb45ef6a2a3d1019b6ecf3e49440Sunny Goyal        protected void onCreateTable(SQLiteDatabase db) {
8204fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal            db.execSQL("CREATE TABLE IF NOT EXISTS " + TABLE_NAME + " (" +
8214fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal                    COLUMN_COMPONENT + " TEXT NOT NULL, " +
8224fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal                    COLUMN_USER + " INTEGER NOT NULL, " +
8234fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal                    COLUMN_LAST_UPDATED + " INTEGER NOT NULL DEFAULT 0, " +
8244fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal                    COLUMN_VERSION + " INTEGER NOT NULL DEFAULT 0, " +
8254fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal                    COLUMN_ICON + " BLOB, " +
82634b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal                    COLUMN_ICON_LOW_RES + " BLOB, " +
8274fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal                    COLUMN_LABEL + " TEXT, " +
8280c9a354c9732585620569bafaec0973977baf614Sunny Goyal                    COLUMN_SYSTEM_STATE + " TEXT, " +
8294fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal                    "PRIMARY KEY (" + COLUMN_COMPONENT + ", " + COLUMN_USER + ") " +
8304fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal                    ");");
8316d0dde01f307051ee1849481c989d9e87774b894Chris Wren        }
832360bc25ab6ae22869b867350b87ee7e82f06389aSunny Goyal    }
833360bc25ab6ae22869b867350b87ee7e82f06389aSunny Goyal
834360bc25ab6ae22869b867350b87ee7e82f06389aSunny Goyal    private ContentValues newContentValues(Bitmap icon, String label, int lowResBackgroundColor) {
835360bc25ab6ae22869b867350b87ee7e82f06389aSunny Goyal        ContentValues values = new ContentValues();
836360bc25ab6ae22869b867350b87ee7e82f06389aSunny Goyal        values.put(IconDB.COLUMN_ICON, Utilities.flattenBitmap(icon));
837360bc25ab6ae22869b867350b87ee7e82f06389aSunny Goyal
838360bc25ab6ae22869b867350b87ee7e82f06389aSunny Goyal        values.put(IconDB.COLUMN_LABEL, label);
839360bc25ab6ae22869b867350b87ee7e82f06389aSunny Goyal        values.put(IconDB.COLUMN_SYSTEM_STATE, mSystemState);
84034b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal
841360bc25ab6ae22869b867350b87ee7e82f06389aSunny Goyal        if (lowResBackgroundColor == Color.TRANSPARENT) {
842360bc25ab6ae22869b867350b87ee7e82f06389aSunny Goyal          values.put(IconDB.COLUMN_ICON_LOW_RES, Utilities.flattenBitmap(
843360bc25ab6ae22869b867350b87ee7e82f06389aSunny Goyal          Bitmap.createScaledBitmap(icon,
844360bc25ab6ae22869b867350b87ee7e82f06389aSunny Goyal                  icon.getWidth() / LOW_RES_SCALE_FACTOR,
845360bc25ab6ae22869b867350b87ee7e82f06389aSunny Goyal                  icon.getHeight() / LOW_RES_SCALE_FACTOR, true)));
846360bc25ab6ae22869b867350b87ee7e82f06389aSunny Goyal        } else {
847360bc25ab6ae22869b867350b87ee7e82f06389aSunny Goyal            synchronized (this) {
848360bc25ab6ae22869b867350b87ee7e82f06389aSunny Goyal                if (mLowResBitmap == null) {
849360bc25ab6ae22869b867350b87ee7e82f06389aSunny Goyal                    mLowResBitmap = Bitmap.createBitmap(icon.getWidth() / LOW_RES_SCALE_FACTOR,
850360bc25ab6ae22869b867350b87ee7e82f06389aSunny Goyal                            icon.getHeight() / LOW_RES_SCALE_FACTOR, Bitmap.Config.RGB_565);
851360bc25ab6ae22869b867350b87ee7e82f06389aSunny Goyal                    mLowResCanvas = new Canvas(mLowResBitmap);
852360bc25ab6ae22869b867350b87ee7e82f06389aSunny Goyal                    mLowResPaint = new Paint(Paint.FILTER_BITMAP_FLAG | Paint.ANTI_ALIAS_FLAG);
853360bc25ab6ae22869b867350b87ee7e82f06389aSunny Goyal                }
854360bc25ab6ae22869b867350b87ee7e82f06389aSunny Goyal                mLowResCanvas.drawColor(lowResBackgroundColor);
855360bc25ab6ae22869b867350b87ee7e82f06389aSunny Goyal                mLowResCanvas.drawBitmap(icon, new Rect(0, 0, icon.getWidth(), icon.getHeight()),
856360bc25ab6ae22869b867350b87ee7e82f06389aSunny Goyal                        new Rect(0, 0, mLowResBitmap.getWidth(), mLowResBitmap.getHeight()),
857360bc25ab6ae22869b867350b87ee7e82f06389aSunny Goyal                        mLowResPaint);
858360bc25ab6ae22869b867350b87ee7e82f06389aSunny Goyal                values.put(IconDB.COLUMN_ICON_LOW_RES, Utilities.flattenBitmap(mLowResBitmap));
859360bc25ab6ae22869b867350b87ee7e82f06389aSunny Goyal            }
86034b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal        }
861360bc25ab6ae22869b867350b87ee7e82f06389aSunny Goyal        return values;
86234b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal    }
86334b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal
864360bc25ab6ae22869b867350b87ee7e82f06389aSunny Goyal    private static Bitmap loadIconNoResize(Cursor c, int iconIndex, BitmapFactory.Options options) {
86534b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal        byte[] data = c.getBlob(iconIndex);
86634b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal        try {
867360bc25ab6ae22869b867350b87ee7e82f06389aSunny Goyal            return BitmapFactory.decodeByteArray(data, 0, data.length, options);
86834b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal        } catch (Exception e) {
86934b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal            return null;
87034b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal        }
8716d0dde01f307051ee1849481c989d9e87774b894Chris Wren    }
8720589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato}
873