diff --git a/quickstep/src/com/android/launcher3/model/AppEventProducer.java b/quickstep/src/com/android/launcher3/model/AppEventProducer.java index 3f29e433d9..5c669441c7 100644 --- a/quickstep/src/com/android/launcher3/model/AppEventProducer.java +++ b/quickstep/src/com/android/launcher3/model/AppEventProducer.java @@ -18,6 +18,7 @@ package com.android.launcher3.model; import static android.app.prediction.AppTargetEvent.ACTION_DISMISS; import static android.app.prediction.AppTargetEvent.ACTION_LAUNCH; import static android.app.prediction.AppTargetEvent.ACTION_PIN; +import static android.app.prediction.AppTargetEvent.ACTION_UNDISMISS; import static android.app.prediction.AppTargetEvent.ACTION_UNPIN; import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_HOTSEAT_PREDICTION; @@ -25,6 +26,7 @@ import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_PREDICT import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_WIDGETS_PREDICTION; import static com.android.launcher3.logger.LauncherAtomExtensions.ExtendedContainers.ContainerCase.DEVICE_SEARCH_RESULT_CONTAINER; import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_APP_LAUNCH_TAP; +import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_DISMISS_PREDICTION_UNDO; import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_FOLDER_CONVERTED_TO_ICON; import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_HOTSEAT_PREDICTION_PINNED; import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ITEM_DRAG_STARTED; @@ -176,6 +178,8 @@ public class AppEventProducer implements StatsLogConsumer { mContext.getPackageName(), Process.myUserHandle()) .build(); sendEvent(target, atomInfo, ACTION_LAUNCH, CONTAINER_PREDICTION); + } else if (event == LAUNCHER_DISMISS_PREDICTION_UNDO) { + sendEvent(atomInfo, ACTION_UNDISMISS, CONTAINER_HOTSEAT_PREDICTION); } } diff --git a/src/com/android/launcher3/SecondaryDropTarget.java b/src/com/android/launcher3/SecondaryDropTarget.java index cd06414d3f..5b037e4db8 100644 --- a/src/com/android/launcher3/SecondaryDropTarget.java +++ b/src/com/android/launcher3/SecondaryDropTarget.java @@ -8,6 +8,7 @@ import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_DESKTOP import static com.android.launcher3.accessibility.LauncherAccessibilityDelegate.DISMISS_PREDICTION; import static com.android.launcher3.accessibility.LauncherAccessibilityDelegate.RECONFIGURE; import static com.android.launcher3.accessibility.LauncherAccessibilityDelegate.UNINSTALL; +import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_DISMISS_PREDICTION_UNDO; import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ITEM_DROPPED_ON_DONT_SUGGEST; import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ITEM_DROPPED_ON_UNINSTALL; import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ITEM_UNINSTALL_CANCELLED; @@ -46,6 +47,7 @@ import com.android.launcher3.model.data.ItemInfoWithIcon; import com.android.launcher3.model.data.LauncherAppWidgetInfo; import com.android.launcher3.util.PackageManagerHelper; import com.android.launcher3.util.PendingRequestArgs; +import com.android.launcher3.views.Snackbar; import com.android.launcher3.widget.LauncherAppWidgetProviderInfo; import java.net.URISyntaxException; @@ -220,7 +222,8 @@ public class SecondaryDropTarget extends ButtonDropTarget implements OnAlarmList @Override public void completeDrop(final DragObject d) { - ComponentName target = performDropAction(getViewUnderDrag(d.dragInfo), d.dragInfo); + ComponentName target = performDropAction(getViewUnderDrag(d.dragInfo), d.dragInfo, + d.logInstanceId); if (d.dragSource instanceof DeferredOnComplete) { DeferredOnComplete deferred = (DeferredOnComplete) d.dragSource; if (target != null) { @@ -264,7 +267,7 @@ public class SecondaryDropTarget extends ButtonDropTarget implements OnAlarmList * Performs the drop action and returns the target component for the dragObject or null if * the action was not performed. */ - protected ComponentName performDropAction(View view, ItemInfo info) { + protected ComponentName performDropAction(View view, ItemInfo info, InstanceId instanceId) { if (mCurrentAccessibilityAction == RECONFIGURE) { int widgetId = getReconfigurableWidgetId(view); if (widgetId != INVALID_APPWIDGET_ID) { @@ -276,7 +279,16 @@ public class SecondaryDropTarget extends ButtonDropTarget implements OnAlarmList return null; } if (mCurrentAccessibilityAction == DISMISS_PREDICTION) { - // We sent the log event, nothing else left to do + if (FeatureFlags.ENABLE_DISMISS_PREDICTION_UNDO.get()) { + mLauncher.getDragLayer() + .announceForAccessibility(getContext().getString(R.string.item_removed)); + Snackbar.show(mLauncher, R.string.item_removed, R.string.undo, () -> { }, () -> { + mStatsLogManager.logger() + .withInstanceId(instanceId) + .withItemInfo(info) + .log(LAUNCHER_DISMISS_PREDICTION_UNDO); + }); + } return null; } // else: mCurrentAccessibilityAction == UNINSTALL @@ -303,8 +315,9 @@ public class SecondaryDropTarget extends ButtonDropTarget implements OnAlarmList @Override public void onAccessibilityDrop(View view, ItemInfo item) { - doLog(new InstanceIdSequence().newInstanceId(), item); - performDropAction(view, item); + InstanceId instanceId = new InstanceIdSequence().newInstanceId(); + doLog(instanceId, item); + performDropAction(view, item, instanceId); } /** diff --git a/src/com/android/launcher3/config/FeatureFlags.java b/src/com/android/launcher3/config/FeatureFlags.java index 420180b049..626e15cbff 100644 --- a/src/com/android/launcher3/config/FeatureFlags.java +++ b/src/com/android/launcher3/config/FeatureFlags.java @@ -265,6 +265,10 @@ public final class FeatureFlags { "USE_LOCAL_ICON_OVERRIDES", true, "Use inbuilt monochrome icons if app doesn't provide one"); + public static final BooleanFlag ENABLE_DISMISS_PREDICTION_UNDO = getDebugFlag( + "ENABLE_DISMISS_PREDICTION_UNDO", false, + "Show an 'Undo' snackbar when users dismiss a predicted hotseat item"); + public static void initialize(Context context) { synchronized (sDebugFlags) { for (DebugFlag flag : sDebugFlags) { diff --git a/src/com/android/launcher3/logging/StatsLogManager.java b/src/com/android/launcher3/logging/StatsLogManager.java index b8ecec1541..7e6f81cf49 100644 --- a/src/com/android/launcher3/logging/StatsLogManager.java +++ b/src/com/android/launcher3/logging/StatsLogManager.java @@ -579,7 +579,10 @@ public class StatsLogManager implements ResourceBasedOverride { LAUNCHER_TASKBAR_OVERVIEW_BUTTON_LONGPRESS(1010), @UiEvent(doc = "User tapped taskbar a11y button") - LAUNCHER_TASKBAR_A11Y_BUTTON_LONGPRESS(1011); + LAUNCHER_TASKBAR_A11Y_BUTTON_LONGPRESS(1011), + + @UiEvent(doc = "Show an 'Undo' snackbar when users dismiss a predicted hotseat item") + LAUNCHER_DISMISS_PREDICTION_UNDO(1035); // ADD MORE