Add wrapper for logging backup & restore metrics from Launcher
Bug: 25177913
Flag: ACONFIG com.android.launcher3.enable_launcher_br_metrics DEVELOPMENT
Test: locally
Change-Id: I220721f705eb7244a1f13ef8997682999d799f51
diff --git a/quickstep/res/values/override.xml b/quickstep/res/values/override.xml
index df32626..29779a7 100644
--- a/quickstep/res/values/override.xml
+++ b/quickstep/res/values/override.xml
@@ -35,4 +35,6 @@
<string name="assist_state_manager_class" translatable="false"></string>
+ <string name="launcher_restore_event_logger_class" translatable="false">com.android.quickstep.LauncherRestoreEventLoggerImpl</string>
+
</resources>
diff --git a/quickstep/src/com/android/quickstep/LauncherRestoreEventLoggerImpl.kt b/quickstep/src/com/android/quickstep/LauncherRestoreEventLoggerImpl.kt
new file mode 100644
index 0000000..645ecf4
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/LauncherRestoreEventLoggerImpl.kt
@@ -0,0 +1,136 @@
+package com.android.quickstep
+
+import android.app.backup.BackupManager
+import android.app.backup.BackupRestoreEventLogger
+import android.app.backup.BackupRestoreEventLogger.BackupRestoreDataType
+import android.app.backup.BackupRestoreEventLogger.BackupRestoreError
+import android.content.Context
+import com.android.launcher3.Flags
+import com.android.launcher3.LauncherSettings.Favorites
+import com.android.launcher3.backuprestore.LauncherRestoreEventLogger
+
+/**
+ * Concrete implementation for wrapper to log Restore event metrics for both success and failure to
+ * restore Launcher workspace from a backup. This implementation accesses SystemApis so is only
+ * available to QuickStep/NexusLauncher.
+ */
+class LauncherRestoreEventLoggerImpl(val context: Context) : LauncherRestoreEventLogger() {
+ companion object {
+ const val TAG = "LauncherRestoreEventLoggerImpl"
+
+ // Generic type for any possible workspace items, when specific type is not known.
+ @BackupRestoreDataType private const val DATA_TYPE_LAUNCHER_ITEM = "launcher_item"
+ // Specific workspace item types, based off of Favorites Table.
+ @BackupRestoreDataType private const val DATA_TYPE_APPLICATION = "application"
+ @BackupRestoreDataType private const val DATA_TYPE_FOLDER = "folder"
+ @BackupRestoreDataType private const val DATA_TYPE_APPWIDGET = "widget"
+ @BackupRestoreDataType private const val DATA_TYPE_CUSTOM_APPWIDGET = "custom_widget"
+ @BackupRestoreDataType private const val DATA_TYPE_DEEP_SHORTCUT = "deep_shortcut"
+ @BackupRestoreDataType private const val DATA_TYPE_APP_PAIR = "app_pair"
+ }
+
+ private val backupManager: BackupManager = BackupManager(context)
+ private val restoreEventLogger: BackupRestoreEventLogger = backupManager.delayedRestoreLogger
+
+ /**
+ * For logging when multiple items of a given data type failed to restore.
+ *
+ * @param dataType The data type that was not restored.
+ * @param count the number of data items that were not restored.
+ * @param error error type for why the data was not restored.
+ */
+ override fun logLauncherItemsRestoreFailed(
+ @BackupRestoreDataType dataType: String,
+ count: Int,
+ @BackupRestoreError error: String?
+ ) {
+ if (Flags.enableLauncherBrMetrics()) {
+ restoreEventLogger.logItemsRestoreFailed(dataType, count, error)
+ }
+ }
+
+ /**
+ * For logging when multiple items of a given data type were successfully restored.
+ *
+ * @param dataType The data type that was restored.
+ * @param count the number of data items restored.
+ */
+ override fun logLauncherItemsRestored(@BackupRestoreDataType dataType: String, count: Int) {
+ if (Flags.enableLauncherBrMetrics()) {
+ restoreEventLogger.logItemsRestored(dataType, count)
+ }
+ }
+
+ /**
+ * Helper to log successfully restoring a single item from the Favorites table.
+ *
+ * @param favoritesId The id of the item type from [Favorites] that was restored.
+ */
+ override fun logSingleFavoritesItemRestored(favoritesId: Int) {
+ if (Flags.enableLauncherBrMetrics()) {
+ restoreEventLogger.logItemsRestored(favoritesIdToDataType(favoritesId), 1)
+ }
+ }
+
+ /**
+ * Helper to log a failure to restore a single item from the Favorites table.
+ *
+ * @param favoritesId The id of the item type from [Favorites] that was not restored.
+ * @param error error type for why the data was not restored.
+ */
+ override fun logSingleFavoritesItemRestoreFailed(
+ favoritesId: Int,
+ @BackupRestoreError error: String?
+ ) {
+ if (Flags.enableLauncherBrMetrics()) {
+ restoreEventLogger.logItemsRestoreFailed(favoritesIdToDataType(favoritesId), 1, error)
+ }
+ }
+
+ /**
+ * Helper to log a failure to restore items from the Favorites table.
+ *
+ * @param favoritesId The id of the item type from [Favorites] that was not restored.
+ * @param count number of items that failed to restore.
+ * @param error error type for why the data was not restored.
+ */
+ override fun logFavoritesItemsRestoreFailed(
+ favoritesId: Int,
+ count: Int,
+ @BackupRestoreError error: String?
+ ) {
+ if (Flags.enableLauncherBrMetrics()) {
+ restoreEventLogger.logItemsRestoreFailed(
+ favoritesIdToDataType(favoritesId),
+ count,
+ error
+ )
+ }
+ }
+
+ /**
+ * Uses the current [restoreEventLogger] to report its results to the [backupManager]. Use when
+ * done restoring items for Launcher.
+ */
+ override fun reportLauncherRestoreResults() {
+ if (Flags.enableLauncherBrMetrics()) {
+ backupManager.reportDelayedRestoreResult(restoreEventLogger)
+ }
+ }
+
+ /**
+ * Helper method to convert item types from [Favorites] to B&R data types for logging. Also to
+ * avoid direct usage of @BackupRestoreDataType which is protected under @SystemApi.
+ */
+ @BackupRestoreDataType
+ private fun favoritesIdToDataType(favoritesId: Int): String =
+ when (favoritesId) {
+ Favorites.ITEM_TYPE_APPLICATION -> DATA_TYPE_APPLICATION
+ Favorites.ITEM_TYPE_FOLDER -> DATA_TYPE_FOLDER
+ Favorites.ITEM_TYPE_APPWIDGET -> DATA_TYPE_APPWIDGET
+ Favorites.ITEM_TYPE_CUSTOM_APPWIDGET -> DATA_TYPE_CUSTOM_APPWIDGET
+ Favorites.ITEM_TYPE_DEEP_SHORTCUT -> DATA_TYPE_DEEP_SHORTCUT
+ Favorites.ITEM_TYPE_APP_PAIR -> DATA_TYPE_APP_PAIR
+ else -> DATA_TYPE_LAUNCHER_ITEM
+ }
+}
diff --git a/res/values/config.xml b/res/values/config.xml
index 154312a..2980635 100644
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -86,6 +86,7 @@
<string name="widget_holder_factory_class" translatable="false"></string>
<string name="taskbar_search_session_controller_class" translatable="false"></string>
<string name="taskbar_model_callbacks_factory_class" translatable="false"></string>
+ <string name="launcher_restore_event_logger_class" translatable="false"></string>
<!-- View ID to use for QSB widget -->
<item type="id" name="qsb_widget" />
diff --git a/src/com/android/launcher3/backuprestore/LauncherRestoreEventLogger.kt b/src/com/android/launcher3/backuprestore/LauncherRestoreEventLogger.kt
new file mode 100644
index 0000000..16b1854
--- /dev/null
+++ b/src/com/android/launcher3/backuprestore/LauncherRestoreEventLogger.kt
@@ -0,0 +1,84 @@
+package com.android.launcher3.backuprestore
+
+import android.content.Context
+import com.android.launcher3.LauncherSettings.Favorites
+import com.android.launcher3.R
+import com.android.launcher3.util.ResourceBasedOverride
+
+/**
+ * Wrapper for logging Restore event metrics for both success and failure to restore the Launcher
+ * workspace from a backup.
+ */
+open class LauncherRestoreEventLogger : ResourceBasedOverride {
+
+ companion object {
+ const val TAG = "LauncherRestoreEventLogger"
+
+ fun newInstance(context: Context?): LauncherRestoreEventLogger {
+ return ResourceBasedOverride.Overrides.getObject(
+ LauncherRestoreEventLogger::class.java,
+ context,
+ R.string.launcher_restore_event_logger_class
+ )
+ }
+ }
+
+ /**
+ * For logging when multiple items of a given data type failed to restore.
+ *
+ * @param dataType The data type that was not restored.
+ * @param count the number of data items that were not restored.
+ * @param error error type for why the data was not restored.
+ */
+ open fun logLauncherItemsRestoreFailed(dataType: String, count: Int, error: String?) {
+ // no-op
+ }
+
+ /**
+ * For logging when multiple items of a given data type were successfully restored.
+ *
+ * @param dataType The data type that was restored.
+ * @param count the number of data items restored.
+ */
+ open fun logLauncherItemsRestored(dataType: String, count: Int) {
+ // no-op
+ }
+
+ /**
+ * Helper to log successfully restoring a single item from the Favorites table.
+ *
+ * @param favoritesId The id of the item type from [Favorites] that was restored.
+ */
+ open fun logSingleFavoritesItemRestored(favoritesId: Int) {
+ // no-op
+ }
+
+ /**
+ * Helper to log a failure to restore a single item from the Favorites table.
+ *
+ * @param favoritesId The id of the item type from [Favorites] that was not restored.
+ * @param error error type for why the data was not restored.
+ */
+ open fun logSingleFavoritesItemRestoreFailed(favoritesId: Int, error: String?) {
+ // no-op
+ }
+
+ /**
+ * Helper to log a failure to restore items from the Favorites table.
+ *
+ * @param favoritesId The id of the item type from [Favorites] that was not restored.
+ * @param count number of items that failed to restore.
+ * @param error error type for why the data was not restored.
+ */
+ open fun logFavoritesItemsRestoreFailed(favoritesId: Int, count: Int, error: String?) {
+ // no-op
+ }
+
+ /**
+ * Uses the current [restoreEventLogger] to report its results to the [backupManager]. Use when
+ * done restoring items for Launcher.
+ */
+ open fun reportLauncherRestoreResults() {
+ // no-op
+ }
+}