Report app pin/unpin to AppPredictor
Test: Manual
Bug: 142753423
Change-Id: I380e58f31ed508d812d0bf8dfc35905a752dc029
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/HotseatPredictionController.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/HotseatPredictionController.java
index 424333c..fe9fd60 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/HotseatPredictionController.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/HotseatPredictionController.java
@@ -23,7 +23,10 @@
import android.app.prediction.AppPredictionManager;
import android.app.prediction.AppPredictor;
import android.app.prediction.AppTarget;
+import android.app.prediction.AppTargetEvent;
+import android.app.prediction.AppTargetId;
import android.content.ComponentName;
+import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
@@ -60,9 +63,12 @@
private static final String TAG = "PredictiveHotseat";
private static final boolean DEBUG = false;
+ //TODO: replace this with AppTargetEvent.ACTION_UNPIN (b/144119543)
+ private static final int APPTARGET_ACTION_UNPIN = 4;
+
private static final String PREDICTION_CLIENT = "hotseat";
- private boolean mDragStarted = false;
+ private DropTarget.DragObject mDragObject;
private int mHotSeatItemsCount;
private Launcher mLauncher;
@@ -84,7 +90,6 @@
mHotSeatItemsCount = mLauncher.getDeviceProfile().inv.numHotseatIcons;
launcher.getDeviceProfile().inv.addOnChangeListener(this);
mHotseat.addOnAttachStateChangeListener(this);
- createPredictor();
}
@Override
@@ -101,7 +106,7 @@
* Fills gaps in the hotseat with predictions
*/
public void fillGapsWithPrediction(boolean animate) {
- if (mDragStarted) {
+ if (mDragObject != null) {
return;
}
List<WorkspaceItemInfo> predictedApps = mapToWorkspaceItemInfo(mComponentKeyMappers);
@@ -155,7 +160,10 @@
}
}
- private void createPredictor() {
+ /**
+ * Creates App Predictor with all the current apps pinned on the hotseat
+ */
+ public void createPredictor() {
AppPredictionManager apm = mLauncher.getSystemService(AppPredictionManager.class);
if (apm == null) {
return;
@@ -167,12 +175,28 @@
new AppPredictionContext.Builder(mLauncher)
.setUiSurface(PREDICTION_CLIENT)
.setPredictedTargetCount(mHotSeatItemsCount)
+ .setExtras(getAppPredictionContextExtra())
.build());
mAppPredictor.registerPredictionUpdates(mLauncher.getMainExecutor(),
this::setPredictedApps);
mAppPredictor.requestPredictionUpdate();
}
+ private Bundle getAppPredictionContextExtra() {
+ Bundle bundle = new Bundle();
+ ViewGroup vg = mHotseat.getShortcutsAndWidgets();
+ ArrayList<AppTarget> pinnedApps = new ArrayList<>();
+ for (int i = 0; i < vg.getChildCount(); i++) {
+ View child = vg.getChildAt(i);
+ if (isPinnedIcon(child)) {
+ WorkspaceItemInfo itemInfo = (WorkspaceItemInfo) child.getTag();
+ pinnedApps.add(getAppTargetFromItemInfo(itemInfo));
+ }
+ }
+ bundle.putParcelableArrayList("pinned_apps", pinnedApps);
+ return bundle;
+ }
+
private void setPredictedApps(List<AppTarget> appTargets) {
mComponentKeyMappers.clear();
for (AppTarget appTarget : appTargets) {
@@ -209,6 +233,8 @@
icon.reset();
icon.applyFromWorkspaceItem(workspaceItemInfo);
icon.setOnLongClickListener(ItemLongClickListener.INSTANCE_WORKSPACE);
+ AppTarget appTarget = getAppTargetFromItemInfo(workspaceItemInfo);
+ notifyItemAction(appTarget, AppTargetEvent.ACTION_PIN);
}
private List<WorkspaceItemInfo> mapToWorkspaceItemInfo(
@@ -270,18 +296,32 @@
}
}
+ private void notifyItemAction(AppTarget target, int action) {
+ if (mAppPredictor != null) {
+ mAppPredictor.notifyAppTargetEvent(new AppTargetEvent.Builder(target, action).build());
+ }
+ }
+
@Override
public void onDragStart(DropTarget.DragObject dragObject, DragOptions options) {
removePredictedApps(true);
- mDragStarted = true;
+ mDragObject = dragObject;
}
@Override
public void onDragEnd() {
- if (!mDragStarted) {
+ if (mDragObject == null) {
return;
}
- mDragStarted = false;
+ ItemInfo dragInfo = mDragObject.dragInfo;
+ if (dragInfo instanceof WorkspaceItemInfo && dragInfo.getTargetComponent() != null) {
+ if (isInHotseat(dragInfo) && !isInHotseat(mDragObject.originalDragInfo)) {
+ notifyItemAction(getAppTargetFromItemInfo(dragInfo), AppTargetEvent.ACTION_PIN);
+ } else if (!isInHotseat(dragInfo) && isInHotseat(mDragObject.originalDragInfo)) {
+ notifyItemAction(getAppTargetFromItemInfo(dragInfo), APPTARGET_ACTION_UNPIN);
+ }
+ }
+ mDragObject = null;
fillGapsWithPrediction(true);
}
@@ -339,4 +379,26 @@
&& ((WorkspaceItemInfo) view.getTag()).container
== LauncherSettings.Favorites.CONTAINER_HOTSEAT_PREDICTION;
}
+
+ private static boolean isPinnedIcon(View view) {
+ if (!(view instanceof BubbleTextView && view.getTag() instanceof WorkspaceItemInfo)) {
+ return false;
+ }
+ ItemInfo info = (ItemInfo) view.getTag();
+ return info.container == LauncherSettings.Favorites.CONTAINER_HOTSEAT && (
+ info.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION
+ || info.itemType == LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT);
+ }
+
+ private static boolean isInHotseat(ItemInfo itemInfo) {
+ return itemInfo.container == LauncherSettings.Favorites.CONTAINER_HOTSEAT;
+ }
+
+ private static AppTarget getAppTargetFromItemInfo(ItemInfo info) {
+ if (info.getTargetComponent() == null) return null;
+ return new AppTarget.Builder(
+ new AppTargetId("app:" + info.getTargetComponent().getPackageName()),
+ info.getTargetComponent().getPackageName(), info.user).setClassName(
+ info.getTargetComponent().getClassName()).build();
+ }
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/QuickstepLauncher.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
index eefb7dc..9144d5d 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
@@ -195,7 +195,7 @@
public void finishBindingItems(int pageBoundFirst) {
super.finishBindingItems(pageBoundFirst);
if (mHotseatPredictionController != null) {
- mHotseatPredictionController.fillGapsWithPrediction(false);
+ mHotseatPredictionController.createPredictor();
}
}