Merge "Decouple Backup / Restore Error Codes" into main
diff --git a/src/com/android/launcher3/backuprestore/LauncherRestoreEventLogger.kt b/src/com/android/launcher3/backuprestore/LauncherRestoreEventLogger.kt
index b05539a..1502811 100644
--- a/src/com/android/launcher3/backuprestore/LauncherRestoreEventLogger.kt
+++ b/src/com/android/launcher3/backuprestore/LauncherRestoreEventLogger.kt
@@ -16,11 +16,16 @@
     @Retention(AnnotationRetention.SOURCE)
     @StringDef(
         RestoreError.PROFILE_DELETED,
-        RestoreError.MISSING_INFO,
         RestoreError.MISSING_WIDGET_PROVIDER,
-        RestoreError.INVALID_LOCATION,
+        RestoreError.OVERLAPPING_ITEM,
+        RestoreError.INVALID_WIDGET_SIZE,
+        RestoreError.INVALID_WIDGET_CONTAINER,
         RestoreError.SHORTCUT_NOT_FOUND,
-        RestoreError.APP_NOT_INSTALLED,
+        RestoreError.APP_NO_TARGET_PACKAGE,
+        RestoreError.APP_NO_DB_INTENT,
+        RestoreError.APP_NO_LAUNCH_INTENT,
+        RestoreError.APP_NOT_RESTORED_OR_INSTALLING,
+        RestoreError.APP_NOT_INSTALLED_EXTERNAL_MEDIA,
         RestoreError.WIDGETS_DISABLED,
         RestoreError.PROFILE_NOT_RESTORED,
         RestoreError.WIDGET_REMOVED,
@@ -28,15 +33,24 @@
         RestoreError.GRID_MIGRATION_FAILURE,
         RestoreError.NO_SEARCH_WIDGET,
         RestoreError.INVALID_WIDGET_ID,
+        RestoreError.OTHER_WIDGET_INFLATION_FAIL,
+        RestoreError.UNSPECIFIED_WIDGET_INFLATION_RESULT,
+        RestoreError.UNRESTORED_PENDING_WIDGET,
+        RestoreError.INVALID_CUSTOM_WIDGET_ID,
     )
     annotation class RestoreError {
         companion object {
             const val PROFILE_DELETED = "user_profile_deleted"
-            const val MISSING_INFO = "missing_information_when_loading"
             const val MISSING_WIDGET_PROVIDER = "missing_widget_provider"
-            const val INVALID_LOCATION = "invalid_size_or_location"
+            const val OVERLAPPING_ITEM = "overlapping_item"
+            const val INVALID_WIDGET_SIZE = "invalid_widget_size"
+            const val INVALID_WIDGET_CONTAINER = "invalid_widget_container"
             const val SHORTCUT_NOT_FOUND = "shortcut_not_found"
-            const val APP_NOT_INSTALLED = "app_not_installed"
+            const val APP_NO_TARGET_PACKAGE = "app_no_target_package"
+            const val APP_NO_DB_INTENT = "app_no_db_intent"
+            const val APP_NO_LAUNCH_INTENT = "app_no_launch_intent"
+            const val APP_NOT_RESTORED_OR_INSTALLING = "app_not_restored_or_installed"
+            const val APP_NOT_INSTALLED_EXTERNAL_MEDIA = "app_not_installed_external_media"
             const val WIDGETS_DISABLED = "widgets_disabled"
             const val PROFILE_NOT_RESTORED = "profile_not_restored"
             const val DATABASE_FILE_NOT_RESTORED = "db_file_not_restored"
@@ -44,6 +58,10 @@
             const val GRID_MIGRATION_FAILURE = "grid_migration_failed"
             const val NO_SEARCH_WIDGET = "no_search_widget"
             const val INVALID_WIDGET_ID = "invalid_widget_id"
+            const val OTHER_WIDGET_INFLATION_FAIL = "other_widget_fail"
+            const val UNSPECIFIED_WIDGET_INFLATION_RESULT = "unspecified_widget_inflation_result"
+            const val UNRESTORED_PENDING_WIDGET = "unrestored_pending_widget"
+            const val INVALID_CUSTOM_WIDGET_ID = "invalid_custom_widget_id"
         }
     }
 
diff --git a/src/com/android/launcher3/model/LoaderCursor.java b/src/com/android/launcher3/model/LoaderCursor.java
index 84130c7..c01b1b6 100644
--- a/src/com/android/launcher3/model/LoaderCursor.java
+++ b/src/com/android/launcher3/model/LoaderCursor.java
@@ -498,7 +498,7 @@
                 mRestoreEventLogger.logSingleFavoritesItemRestored(itemType);
             }
         } else {
-            markDeleted("Item position overlap", RestoreError.INVALID_LOCATION);
+            markDeleted("Item position overlap", RestoreError.OVERLAPPING_ITEM);
         }
     }
 
diff --git a/src/com/android/launcher3/model/WorkspaceItemProcessor.kt b/src/com/android/launcher3/model/WorkspaceItemProcessor.kt
index c02336e..e86b592 100644
--- a/src/com/android/launcher3/model/WorkspaceItemProcessor.kt
+++ b/src/com/android/launcher3/model/WorkspaceItemProcessor.kt
@@ -141,7 +141,7 @@
         var allowMissingTarget = false
         var intent = c.parseIntent()
         if (intent == null) {
-            c.markDeleted("Null intent from db for item id=${c.id}", RestoreError.MISSING_INFO)
+            c.markDeleted("Null intent from db for item id=${c.id}", RestoreError.APP_NO_DB_INTENT)
             return
         }
         var disabledState =
@@ -151,7 +151,10 @@
         val cn = intent.component
         val targetPkg = cn?.packageName ?: intent.getPackage()
         if (targetPkg.isNullOrEmpty()) {
-            c.markDeleted("No target package for item id=${c.id}", RestoreError.MISSING_INFO)
+            c.markDeleted(
+                "No target package for item id=${c.id}",
+                RestoreError.APP_NO_TARGET_PACKAGE,
+            )
             return
         }
         val appInfoWrapper = ApplicationInfoWrapper(app.context, targetPkg, c.user)
@@ -180,7 +183,7 @@
                     c.markDeleted(
                         "No Activities found for id=${c.id}, targetPkg=$targetPkg, component=$cn." +
                             " Unable to create launch Intent.",
-                        RestoreError.MISSING_INFO,
+                        RestoreError.APP_NO_LAUNCH_INTENT,
                     )
                     return
                 }
@@ -215,7 +218,7 @@
                             else -> {
                                 c.markDeleted(
                                     "removing app that is not restored and not installing. package: $targetPkg",
-                                    RestoreError.APP_NOT_INSTALLED,
+                                    RestoreError.APP_NOT_RESTORED_OR_INSTALLING,
                                 )
                                 return
                             }
@@ -240,7 +243,7 @@
                         // Do not wait for external media load anymore.
                         c.markDeleted(
                             "Invalid package removed: $targetPkg",
-                            RestoreError.APP_NOT_INSTALLED,
+                            RestoreError.APP_NOT_INSTALLED_EXTERNAL_MEDIA,
                         )
                         return
                     }
@@ -448,7 +451,7 @@
                     ", id=${c.id}," +
                     ", appWidgetId=${c.appWidgetId}," +
                     ", component=${component}",
-                RestoreError.INVALID_LOCATION,
+                RestoreError.INVALID_WIDGET_SIZE,
             )
             return
         }
@@ -459,7 +462,7 @@
                     ", appWidgetId=${c.appWidgetId}," +
                     ", component=${component}," +
                     ", container=${c.container}",
-                RestoreError.INVALID_LOCATION,
+                RestoreError.INVALID_WIDGET_CONTAINER,
             )
             return
         }
@@ -500,7 +503,7 @@
                             ", appWidgetId=${c.appWidgetId}" +
                             ", component=${component}" +
                             ", restoreFlag:=${c.restoreFlag}",
-                        RestoreError.APP_NOT_INSTALLED,
+                        RestoreError.UNRESTORED_PENDING_WIDGET,
                     )
                     return
                 } else if (
diff --git a/src/com/android/launcher3/widget/WidgetInflater.kt b/src/com/android/launcher3/widget/WidgetInflater.kt
index 271c9c2..d6cadc7 100644
--- a/src/com/android/launcher3/widget/WidgetInflater.kt
+++ b/src/com/android/launcher3/widget/WidgetInflater.kt
@@ -30,16 +30,14 @@
 
     private val widgetHelper = WidgetManagerHelper(context)
 
-    fun inflateAppWidget(
-        item: LauncherAppWidgetInfo,
-    ): InflationResult {
+    fun inflateAppWidget(item: LauncherAppWidgetInfo): InflationResult {
         if (item.hasOptionFlag(LauncherAppWidgetInfo.OPTION_SEARCH_WIDGET)) {
             item.providerName = QsbContainerView.getSearchComponentName(context)
             if (item.providerName == null) {
                 return InflationResult(
                     TYPE_DELETE,
                     reason = "search widget removed because search component cannot be found",
-                    restoreErrorType = RestoreError.NO_SEARCH_WIDGET
+                    restoreErrorType = RestoreError.NO_SEARCH_WIDGET,
                 )
             }
         }
@@ -48,7 +46,7 @@
         }
         val appWidgetInfo: LauncherAppWidgetProviderInfo?
         var removalReason = ""
-        @RestoreError var logReason = RestoreError.APP_NOT_INSTALLED
+        @RestoreError var logReason = RestoreError.OTHER_WIDGET_INFLATION_FAIL
         var update = false
 
         if (item.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_ID_NOT_VALID)) {
@@ -74,7 +72,7 @@
             if (appWidgetInfo == null) {
                 if (item.appWidgetId <= LauncherAppWidgetInfo.CUSTOM_WIDGET_ID) {
                     removalReason = "CustomWidgetManager cannot find provider from that widget id."
-                    logReason = RestoreError.MISSING_INFO
+                    logReason = RestoreError.INVALID_CUSTOM_WIDGET_ID
                 } else {
                     removalReason =
                         ("AppWidgetManager cannot find provider for that widget id." +
@@ -96,7 +94,7 @@
                     type = TYPE_DELETE,
                     reason =
                         "Removing restored widget: id=${item.appWidgetId} belongs to component ${item.providerName} user ${item.user}, as the provider is null and $removalReason",
-                    restoreErrorType = logReason
+                    restoreErrorType = logReason,
                 )
             }
 
@@ -132,7 +130,7 @@
                         widgetHelper.bindAppWidgetIdIfAllowed(
                             item.appWidgetId,
                             appWidgetInfo,
-                            options
+                            options,
                         )
 
                     // We tried to bind once. If we were not able to bind, we would need to
@@ -189,9 +187,10 @@
     data class InflationResult(
         val type: Int,
         val reason: String? = null,
-        @RestoreError val restoreErrorType: String = RestoreError.APP_NOT_INSTALLED,
+        @RestoreError
+        val restoreErrorType: String = RestoreError.UNSPECIFIED_WIDGET_INFLATION_RESULT,
         val isUpdate: Boolean = false,
-        val widgetInfo: LauncherAppWidgetProviderInfo? = null
+        val widgetInfo: LauncherAppWidgetProviderInfo? = null,
     )
 
     companion object {
diff --git a/tests/multivalentTests/src/com/android/launcher3/model/WorkspaceItemProcessorTest.kt b/tests/multivalentTests/src/com/android/launcher3/model/WorkspaceItemProcessorTest.kt
index ed8b397..7099d38 100644
--- a/tests/multivalentTests/src/com/android/launcher3/model/WorkspaceItemProcessorTest.kt
+++ b/tests/multivalentTests/src/com/android/launcher3/model/WorkspaceItemProcessorTest.kt
@@ -36,10 +36,7 @@
 import com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT
 import com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_FOLDER
 import com.android.launcher3.Utilities.EMPTY_PERSON_ARRAY
-import com.android.launcher3.backuprestore.LauncherRestoreEventLogger
-import com.android.launcher3.backuprestore.LauncherRestoreEventLogger.RestoreError.Companion.MISSING_INFO
-import com.android.launcher3.backuprestore.LauncherRestoreEventLogger.RestoreError.Companion.MISSING_WIDGET_PROVIDER
-import com.android.launcher3.backuprestore.LauncherRestoreEventLogger.RestoreError.Companion.PROFILE_DELETED
+import com.android.launcher3.backuprestore.LauncherRestoreEventLogger.RestoreError
 import com.android.launcher3.icons.CacheableShortcutInfo
 import com.android.launcher3.model.data.FolderInfo
 import com.android.launcher3.model.data.IconRequestInfo
@@ -224,7 +221,8 @@
         itemProcessorUnderTest.processItem()
 
         // Then
-        verify(mockCursor).markDeleted("User has been deleted for item id=1", PROFILE_DELETED)
+        verify(mockCursor)
+            .markDeleted("User has been deleted for item id=1", RestoreError.PROFILE_DELETED)
         verify(mockCursor, times(0)).checkAndAddItem(any(), any(), anyOrNull())
     }
 
@@ -237,7 +235,8 @@
         itemProcessorUnderTest = createWorkspaceItemProcessorUnderTest()
         itemProcessorUnderTest.processItem()
         // Then
-        verify(mockCursor).markDeleted("Null intent from db for item id=1", MISSING_INFO)
+        verify(mockCursor)
+            .markDeleted("Null intent from db for item id=1", RestoreError.APP_NO_DB_INTENT)
         verify(mockCursor, times(0)).checkAndAddItem(any(), any(), anyOrNull())
     }
 
@@ -255,7 +254,8 @@
         itemProcessorUnderTest.processItem()
 
         // Then
-        verify(mockCursor).markDeleted("No target package for item id=1", MISSING_INFO)
+        verify(mockCursor)
+            .markDeleted("No target package for item id=1", RestoreError.APP_NO_TARGET_PACKAGE)
         verify(mockCursor, times(0)).checkAndAddItem(any(), any(), anyOrNull())
     }
 
@@ -272,7 +272,8 @@
         itemProcessorUnderTest.processItem()
 
         // Then
-        verify(mockCursor).markDeleted("No target package for item id=1", MISSING_INFO)
+        verify(mockCursor)
+            .markDeleted("No target package for item id=1", RestoreError.APP_NO_TARGET_PACKAGE)
         verify(mockCursor, times(0)).checkAndAddItem(any(), any(), anyOrNull())
     }
 
@@ -350,7 +351,7 @@
                     " targetPkg=package," +
                     " component=ComponentInfo{package/class}." +
                     " Unable to create launch Intent.",
-                MISSING_INFO,
+                RestoreError.APP_NO_LAUNCH_INTENT,
             )
         verify(mockCursor, times(0)).checkAndAddItem(any(), any(), anyOrNull())
     }
@@ -663,7 +664,7 @@
         verify(mockCursor)
             .markDeleted(
                 "processWidget: Unrestored Pending widget removed: id=1, appWidgetId=0, component=$expectedComponentName, restoreFlag:=4",
-                LauncherRestoreEventLogger.RestoreError.APP_NOT_INSTALLED,
+                RestoreError.UNRESTORED_PENDING_WIDGET,
             )
     }
 
@@ -689,7 +690,7 @@
                 type = WidgetInflater.TYPE_DELETE,
                 widgetInfo = null,
                 reason = "test_delete_reason",
-                restoreErrorType = MISSING_WIDGET_PROVIDER,
+                restoreErrorType = RestoreError.MISSING_WIDGET_PROVIDER,
             )
         mockWidgetInflater =
             mock<WidgetInflater>().apply {