Fix blank workspce icons on Launcher data refresh.

Clearing the launcher data with bulk workspace icon loading caused blank app icons to appear. Added fallback title and icon loading flows to the bulk icon loading flow.

Test: manually cleared launcher data
Fixes: 216590478
Bug: 195674813
Change-Id: I8e24a166be9f591155d538dfec865d047131b756
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.