private boolean getEntryFromDB(ComponentKey cacheKey, CacheEntry entry, boolean lowRes) { Cursor c = mIconDb .getReadableDatabase() .query( IconDB.TABLE_NAME, new String[] { lowRes ? IconDB.COLUMN_ICON_LOW_RES : IconDB.COLUMN_ICON, IconDB.COLUMN_LABEL }, IconDB.COLUMN_COMPONENT + " = ? AND " + IconDB.COLUMN_USER + " = ?", new String[] { cacheKey.componentName.flattenToString(), Long.toString(mUserManager.getSerialNumberForUser(cacheKey.user)) }, null, null, null); try { if (c.moveToNext()) { entry.icon = loadIconNoResize(c, 0, lowRes ? mLowResOptions : null); entry.isLowResIcon = lowRes; entry.title = c.getString(1); if (entry.title == null) { entry.title = ""; entry.contentDescription = ""; } else { entry.contentDescription = mUserManager.getBadgedLabelForUser(entry.title, cacheKey.user); } return true; } } finally { c.close(); } return false; }
/** * Pre-load an icon into the persistent cache. * * <p>Queries for a component that does not exist in the package manager will be answered by the * persistent cache. * * @param componentName the icon should be returned for this component * @param icon the icon to be persisted * @param dpi the native density of the icon */ public void preloadIcon( ComponentName componentName, Bitmap icon, int dpi, String label, long userSerial, InvariantDeviceProfile idp) { // TODO rescale to the correct native DPI try { PackageManager packageManager = mContext.getPackageManager(); packageManager.getActivityIcon(componentName); // component is present on the system already, do nothing return; } catch (PackageManager.NameNotFoundException e) { // pass } ContentValues values = newContentValues( Bitmap.createScaledBitmap(icon, idp.iconBitmapSize, idp.iconBitmapSize, true), label, Color.TRANSPARENT); values.put(IconDB.COLUMN_COMPONENT, componentName.flattenToString()); values.put(IconDB.COLUMN_USER, userSerial); mIconDb .getWritableDatabase() .insertWithOnConflict(IconDB.TABLE_NAME, null, values, SQLiteDatabase.CONFLICT_REPLACE); }
/** * Updates {@param values} to contain versoning information and adds it to the DB. * * @param values {@link ContentValues} containing icon & title */ private void addIconToDB( ContentValues values, ComponentName key, PackageInfo info, long userSerial) { values.put(IconDB.COLUMN_COMPONENT, key.flattenToString()); values.put(IconDB.COLUMN_USER, userSerial); values.put(IconDB.COLUMN_LAST_UPDATED, info.lastUpdateTime); values.put(IconDB.COLUMN_VERSION, info.versionCode); mIconDb .getWritableDatabase() .insertWithOnConflict(IconDB.TABLE_NAME, null, values, SQLiteDatabase.CONFLICT_REPLACE); }
/** Removes the entries related to the given package in memory and persistent DB. */ public synchronized void removeIconsForPkg(String packageName, UserHandleCompat user) { removeFromMemCacheLocked(packageName, user); long userSerial = mUserManager.getSerialNumberForUser(user); mIconDb .getWritableDatabase() .delete( IconDB.TABLE_NAME, IconDB.COLUMN_COMPONENT + " LIKE ? AND " + IconDB.COLUMN_USER + " = ?", new String[] {packageName + "/%", Long.toString(userSerial)}); }
/** * Updates the persistent DB, such that only entries corresponding to {@param apps} remain in the * DB and are updated. * * @return The set of packages for which icons have updated. */ private void updateDBIcons( UserHandleCompat user, List<LauncherActivityInfoCompat> apps, Set<String> ignorePackages) { long userSerial = mUserManager.getSerialNumberForUser(user); PackageManager pm = mContext.getPackageManager(); HashMap<String, PackageInfo> pkgInfoMap = new HashMap<String, PackageInfo>(); for (PackageInfo info : pm.getInstalledPackages(PackageManager.GET_UNINSTALLED_PACKAGES)) { pkgInfoMap.put(info.packageName, info); } HashMap<ComponentName, LauncherActivityInfoCompat> componentMap = new HashMap<>(); for (LauncherActivityInfoCompat app : apps) { componentMap.put(app.getComponentName(), app); } Cursor c = mIconDb .getReadableDatabase() .query( IconDB.TABLE_NAME, new String[] { IconDB.COLUMN_ROWID, IconDB.COLUMN_COMPONENT, IconDB.COLUMN_LAST_UPDATED, IconDB.COLUMN_VERSION, IconDB.COLUMN_SYSTEM_STATE }, IconDB.COLUMN_USER + " = ? ", new String[] {Long.toString(userSerial)}, null, null, null); final int indexComponent = c.getColumnIndex(IconDB.COLUMN_COMPONENT); final int indexLastUpdate = c.getColumnIndex(IconDB.COLUMN_LAST_UPDATED); final int indexVersion = c.getColumnIndex(IconDB.COLUMN_VERSION); final int rowIndex = c.getColumnIndex(IconDB.COLUMN_ROWID); final int systemStateIndex = c.getColumnIndex(IconDB.COLUMN_SYSTEM_STATE); HashSet<Integer> itemsToRemove = new HashSet<Integer>(); Stack<LauncherActivityInfoCompat> appsToUpdate = new Stack<>(); while (c.moveToNext()) { String cn = c.getString(indexComponent); ComponentName component = ComponentName.unflattenFromString(cn); PackageInfo info = pkgInfoMap.get(component.getPackageName()); if (info == null) { if (!ignorePackages.contains(component.getPackageName())) { remove(component, user); itemsToRemove.add(c.getInt(rowIndex)); } continue; } if ((info.applicationInfo.flags & ApplicationInfo.FLAG_IS_DATA_ONLY) != 0) { // Application is not present continue; } long updateTime = c.getLong(indexLastUpdate); int version = c.getInt(indexVersion); LauncherActivityInfoCompat app = componentMap.remove(component); if (version == info.versionCode && updateTime == info.lastUpdateTime && TextUtils.equals(mSystemState, c.getString(systemStateIndex))) { continue; } if (app == null) { remove(component, user); itemsToRemove.add(c.getInt(rowIndex)); } else { appsToUpdate.add(app); } } c.close(); if (!itemsToRemove.isEmpty()) { mIconDb .getWritableDatabase() .delete( IconDB.TABLE_NAME, Utilities.createDbSelectionQuery(IconDB.COLUMN_ROWID, itemsToRemove), null); } // Insert remaining apps. if (!componentMap.isEmpty() || !appsToUpdate.isEmpty()) { Stack<LauncherActivityInfoCompat> appsToAdd = new Stack<>(); appsToAdd.addAll(componentMap.values()); new SerializedIconUpdateTask(userSerial, pkgInfoMap, appsToAdd, appsToUpdate).scheduleNext(); } }