Merge "Fix blank workspce icons on Launcher data refresh."
diff --git a/src/com/android/launcher3/icons/IconCache.java b/src/com/android/launcher3/icons/IconCache.java
index f512ced..3129e2a 100644
--- a/src/com/android/launcher3/icons/IconCache.java
+++ b/src/com/android/launcher3/icons/IconCache.java
@@ -350,41 +350,101 @@
                                     iconRequest.itemInfo.getTargetComponent()));
 
             Trace.beginSection("loadIconSubsectionInBulk");
-            try (Cursor c = createBulkQueryCursor(
-                    filteredList,
-                    /* user = */ sectionKey.first,
-                    /* useLowResIcons = */ sectionKey.second)) {
-                int componentNameColumnIndex = c.getColumnIndexOrThrow(IconDB.COLUMN_COMPONENT);
-                while (c.moveToNext()) {
-                    ComponentName cn = ComponentName.unflattenFromString(
-                            c.getString(componentNameColumnIndex));
-                    List<IconRequestInfo<T>> duplicateIconRequests =
-                            duplicateIconRequestsMap.get(cn);
-
-                    if (cn != null) {
-                        CacheEntry entry = cacheLocked(
-                                cn,
-                                /* user = */ sectionKey.first,
-                                () -> duplicateIconRequests.get(0).launcherActivityInfo,
-                                mLauncherActivityInfoCachingLogic,
-                                c,
-                                /* usePackageIcon= */ false,
-                                /* useLowResIcons = */ sectionKey.second);
-
-                        for (IconRequestInfo<T> iconRequest : duplicateIconRequests) {
-                            applyCacheEntry(entry, iconRequest.itemInfo);
-                        }
-                    }
-                }
-            } catch (SQLiteException e) {
-                Log.d(TAG, "Error reading icon cache", e);
-            } finally {
-                Trace.endSection();
-            }
+            loadIconSubsection(sectionKey, filteredList, duplicateIconRequestsMap);
+            Trace.endSection();
         });
         Trace.endSection();
     }
 
+    private <T extends ItemInfoWithIcon> void loadIconSubsection(
+            Pair<UserHandle, Boolean> sectionKey,
+            List<IconRequestInfo<T>> filteredList,
+            Map<ComponentName, List<IconRequestInfo<T>>> duplicateIconRequestsMap) {
+        Trace.beginSection("loadIconSubsectionWithDatabase");
+        try (Cursor c = createBulkQueryCursor(
+                filteredList,
+                /* user = */ sectionKey.first,
+                /* useLowResIcons = */ sectionKey.second)) {
+            // Database title and icon loading
+            int componentNameColumnIndex = c.getColumnIndexOrThrow(IconDB.COLUMN_COMPONENT);
+            while (c.moveToNext()) {
+                ComponentName cn = ComponentName.unflattenFromString(
+                        c.getString(componentNameColumnIndex));
+                List<IconRequestInfo<T>> duplicateIconRequests =
+                        duplicateIconRequestsMap.get(cn);
+
+                if (cn != null) {
+                    CacheEntry entry = cacheLocked(
+                            cn,
+                            /* user = */ sectionKey.first,
+                            () -> duplicateIconRequests.get(0).launcherActivityInfo,
+                            mLauncherActivityInfoCachingLogic,
+                            c,
+                            /* usePackageIcon= */ false,
+                            /* useLowResIcons = */ sectionKey.second);
+
+                    for (IconRequestInfo<T> iconRequest : duplicateIconRequests) {
+                        applyCacheEntry(entry, iconRequest.itemInfo);
+                    }
+                }
+            }
+        } catch (SQLiteException e) {
+            Log.d(TAG, "Error reading icon cache", e);
+        } finally {
+            Trace.endSection();
+        }
+
+        Trace.beginSection("loadIconSubsectionWithFallback");
+        // Fallback title and icon loading
+        for (ComponentName cn : duplicateIconRequestsMap.keySet()) {
+            IconRequestInfo<T> iconRequestInfo = duplicateIconRequestsMap.get(cn).get(0);
+            ItemInfoWithIcon itemInfo = iconRequestInfo.itemInfo;
+            BitmapInfo icon = itemInfo.bitmap;
+            boolean loadFallbackTitle = TextUtils.isEmpty(itemInfo.title);
+            boolean loadFallbackIcon = icon == null
+                    || isDefaultIcon(icon, itemInfo.user)
+                    || icon == BitmapInfo.LOW_RES_INFO;
+
+            if (loadFallbackTitle || loadFallbackIcon) {
+                Log.i(TAG,
+                        "Database bulk icon loading failed, using fallback bulk icon loading "
+                                + "for: " + cn);
+                CacheEntry entry = new CacheEntry();
+                LauncherActivityInfo lai = iconRequestInfo.launcherActivityInfo;
+
+                // Fill fields that are not updated below so they are not subsequently
+                // deleted.
+                entry.title = itemInfo.title;
+                if (icon != null) {
+                    entry.bitmap = icon;
+                }
+                entry.contentDescription = itemInfo.contentDescription;
+
+                if (loadFallbackIcon) {
+                    loadFallbackIcon(
+                            lai,
+                            entry,
+                            mLauncherActivityInfoCachingLogic,
+                            /* usePackageIcon= */ false,
+                            /* usePackageTitle= */ loadFallbackTitle,
+                            cn,
+                            sectionKey.first);
+                }
+                if (loadFallbackTitle && TextUtils.isEmpty(entry.title)) {
+                    loadFallbackTitle(
+                            lai,
+                            entry,
+                            mLauncherActivityInfoCachingLogic,
+                            sectionKey.first);
+                }
+
+                for (IconRequestInfo<T> iconRequest : duplicateIconRequestsMap.get(cn)) {
+                    applyCacheEntry(entry, iconRequest.itemInfo);
+                }
+            }
+        }
+        Trace.endSection();
+    }
 
     /**
      * Fill in {@param infoInOut} with the corresponding icon and label.