Merge "Hide shelf in 2-Button Landscape" into ub-launcher3-rvc-dev
diff --git a/quickstep/recents_ui_overrides/res/values/override.xml b/quickstep/recents_ui_overrides/res/values/override.xml
index ed3ba92..6aa9619 100644
--- a/quickstep/recents_ui_overrides/res/values/override.xml
+++ b/quickstep/recents_ui_overrides/res/values/override.xml
@@ -26,5 +26,7 @@
<string name="main_process_initializer_class" translatable="false">com.android.quickstep.QuickstepProcessInitializer</string>
<string name="user_event_dispatcher_class" translatable="false">com.android.quickstep.logging.UserEventDispatcherAppPredictionExtension</string>
+
+ <string name="prediction_model_class" translatable="false">com.android.launcher3.hybridhotseat.HotseatPredictionModel</string>
</resources>
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionUiStateManager.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionUiStateManager.java
index ab3c71a..b6a8206 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionUiStateManager.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionUiStateManager.java
@@ -211,8 +211,11 @@
}
private void dispatchOnChange(boolean changed) {
- PredictionState newState = changed ? parseLastState() :
- (mPendingState == null ? mCurrentState : mPendingState);
+ PredictionState newState = changed
+ ? parseLastState()
+ : mPendingState != null && canApplyPredictions(mPendingState)
+ ? mPendingState
+ : mCurrentState;
if (changed && mAppsView != null && !canApplyPredictions(newState)) {
scheduleApplyPredictedApps(newState);
} else {
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatPredictionController.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatPredictionController.java
index e9f3534..1fe3643 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatPredictionController.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatPredictionController.java
@@ -25,10 +25,7 @@
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.os.Process;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
@@ -36,8 +33,6 @@
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
-import com.android.launcher3.BubbleTextView;
-import com.android.launcher3.CellLayout;
import com.android.launcher3.DragSource;
import com.android.launcher3.DropTarget;
import com.android.launcher3.Hotseat;
@@ -48,7 +43,6 @@
import com.android.launcher3.LauncherState;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
-import com.android.launcher3.Workspace;
import com.android.launcher3.allapps.AllAppsStore;
import com.android.launcher3.anim.AnimationSuccessListener;
import com.android.launcher3.appprediction.ComponentKeyMapper;
@@ -57,12 +51,10 @@
import com.android.launcher3.dragndrop.DragOptions;
import com.android.launcher3.icons.IconCache;
import com.android.launcher3.logging.FileLog;
-import com.android.launcher3.model.PredictionModel;
import com.android.launcher3.model.data.AppInfo;
import com.android.launcher3.model.data.FolderInfo;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.model.data.ItemInfoWithIcon;
-import com.android.launcher3.model.data.LauncherAppWidgetInfo;
import com.android.launcher3.model.data.WorkspaceItemInfo;
import com.android.launcher3.popup.SystemShortcut;
import com.android.launcher3.shortcuts.ShortcutKey;
@@ -77,7 +69,6 @@
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
-import java.util.Locale;
import java.util.OptionalInt;
import java.util.stream.IntStream;
@@ -93,17 +84,6 @@
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 APP_LOCATION_HOTSEAT = "hotseat";
- private static final String APP_LOCATION_WORKSPACE = "workspace";
-
- private static final String BUNDLE_KEY_HOTSEAT = "hotseat_apps";
- private static final String BUNDLE_KEY_WORKSPACE = "workspace_apps";
-
- private static final String BUNDLE_KEY_PIN_EVENTS = "pin_events";
-
private static final String PREDICTION_CLIENT = "hotseat";
private DropTarget.DragObject mDragObject;
private int mHotSeatItemsCount;
@@ -116,13 +96,14 @@
private DynamicItemCache mDynamicItemCache;
- private final PredictionModel mPredictionModel;
+ private final HotseatPredictionModel mPredictionModel;
private AppPredictor mAppPredictor;
private AllAppsStore mAllAppsStore;
private AnimatorSet mIconRemoveAnimators;
private boolean mUIUpdatePaused = false;
private boolean mRequiresCacheUpdate = true;
private boolean mIsCacheEmpty;
+ private boolean mIsDestroyed = false;
private HotseatEduController mHotseatEduController;
@@ -141,13 +122,13 @@
mLauncher = launcher;
mHotseat = launcher.getHotseat();
mAllAppsStore = mLauncher.getAppsView().getAppsStore();
- mPredictionModel = LauncherAppState.INSTANCE.get(launcher).getPredictionModel();
+ LauncherAppState appState = LauncherAppState.getInstance(launcher);
+ mPredictionModel = (HotseatPredictionModel) appState.getPredictionModel();
mAllAppsStore.addUpdateListener(this);
mDynamicItemCache = new DynamicItemCache(mLauncher, this::fillGapsWithPrediction);
mHotSeatItemsCount = mLauncher.getDeviceProfile().inv.numHotseatIcons;
launcher.getDeviceProfile().inv.addOnChangeListener(this);
mHotseat.addOnAttachStateChangeListener(this);
- mIsCacheEmpty = mPredictionModel.getPredictionComponentKeys().isEmpty();
if (mHotseat.isAttachedToWindow()) {
onViewAttachedToWindow(mHotseat);
}
@@ -260,6 +241,7 @@
* Unregisters callbacks and frees resources
*/
public void destroy() {
+ mIsDestroyed = true;
mAllAppsStore.removeUpdateListener(this);
mLauncher.getDeviceProfile().inv.removeOnChangeListener(this);
mHotseat.removeOnAttachStateChangeListener(this);
@@ -292,100 +274,54 @@
}
if (mAppPredictor != null) {
mAppPredictor.destroy();
+ mAppPredictor = null;
}
- mAppPredictor = apm.createAppPredictionSession(
- new AppPredictionContext.Builder(mLauncher)
- .setUiSurface(PREDICTION_CLIENT)
- .setPredictedTargetCount(mHotSeatItemsCount)
- .setExtras(getAppPredictionContextExtra())
- .build());
WeakReference<HotseatPredictionController> controllerRef = new WeakReference<>(this);
- mAppPredictor.registerPredictionUpdates(mLauncher.getApplicationContext().getMainExecutor(),
- list -> {
- if (controllerRef.get() != null) {
- controllerRef.get().setPredictedApps(list);
- }
- });
+
+ mPredictionModel.createBundle(bundle -> {
+ if (mIsDestroyed) return;
+ mAppPredictor = apm.createAppPredictionSession(
+ new AppPredictionContext.Builder(mLauncher)
+ .setUiSurface(PREDICTION_CLIENT)
+ .setPredictedTargetCount(mHotSeatItemsCount)
+ .setExtras(bundle)
+ .build());
+ mAppPredictor.registerPredictionUpdates(
+ mLauncher.getApplicationContext().getMainExecutor(),
+ list -> {
+ if (controllerRef.get() != null) {
+ controllerRef.get().setPredictedApps(list);
+ }
+ });
+ mAppPredictor.requestPredictionUpdate();
+ });
setPauseUIUpdate(false);
if (!isEduSeen()) {
mHotseatEduController = new HotseatEduController(mLauncher, this::createPredictor);
}
- mAppPredictor.requestPredictionUpdate();
}
/**
* Create WorkspaceItemInfo objects and binds PredictedAppIcon views for cached predicted items.
*/
- public void showCachedItems(List<AppInfo> apps, IntArray ranks) {
+ public void showCachedItems(List<AppInfo> apps, IntArray ranks) {
+ mIsCacheEmpty = apps.isEmpty();
int count = Math.min(ranks.size(), apps.size());
List<WorkspaceItemInfo> items = new ArrayList<>(count);
+ mComponentKeyMappers.clear();
for (int i = 0; i < count; i++) {
WorkspaceItemInfo item = new WorkspaceItemInfo(apps.get(i));
+ ComponentKey componentKey = new ComponentKey(item.getTargetComponent(), item.user);
preparePredictionInfo(item, ranks.get(i));
items.add(item);
- }
- mComponentKeyMappers.clear();
- for (ComponentKey key : mPredictionModel.getPredictionComponentKeys()) {
- mComponentKeyMappers.add(new ComponentKeyMapper(key, mDynamicItemCache));
+
+ mComponentKeyMappers.add(new ComponentKeyMapper(componentKey, mDynamicItemCache));
}
updateDependencies();
bindItems(items, false, null);
}
- private Bundle getAppPredictionContextExtra() {
- Bundle bundle = new Bundle();
-
- //TODO: remove this way of reporting items
- bundle.putParcelableArrayList(BUNDLE_KEY_HOTSEAT,
- getPinnedAppTargetsInViewGroup((mHotseat.getShortcutsAndWidgets())));
- bundle.putParcelableArrayList(BUNDLE_KEY_WORKSPACE, getPinnedAppTargetsInViewGroup(
- mLauncher.getWorkspace().getScreenWithId(
- Workspace.FIRST_SCREEN_ID).getShortcutsAndWidgets()));
-
- ArrayList<AppTargetEvent> pinEvents = new ArrayList<>();
- getPinEventsForViewGroup(pinEvents, mHotseat.getShortcutsAndWidgets(),
- APP_LOCATION_HOTSEAT);
- getPinEventsForViewGroup(pinEvents, mLauncher.getWorkspace().getScreenWithId(
- Workspace.FIRST_SCREEN_ID).getShortcutsAndWidgets(), APP_LOCATION_WORKSPACE);
- bundle.putParcelableArrayList(BUNDLE_KEY_PIN_EVENTS, pinEvents);
-
- return bundle;
- }
-
- private ArrayList<AppTargetEvent> getPinEventsForViewGroup(ArrayList<AppTargetEvent> pinEvents,
- ViewGroup views, String root) {
- for (int i = 0; i < views.getChildCount(); i++) {
- View child = views.getChildAt(i);
- final AppTargetEvent event;
- if (child.getTag() instanceof ItemInfo && getAppTargetFromInfo(
- (ItemInfo) child.getTag()) != null) {
- ItemInfo info = (ItemInfo) child.getTag();
- event = wrapAppTargetWithLocation(getAppTargetFromInfo(info),
- AppTargetEvent.ACTION_PIN, info);
- } else {
- CellLayout.LayoutParams params = (CellLayout.LayoutParams) views.getLayoutParams();
- event = wrapAppTargetWithLocation(getBlockAppTarget(), AppTargetEvent.ACTION_PIN,
- root, 0, params.cellX, params.cellY, params.cellHSpan, params.cellVSpan);
- }
- pinEvents.add(event);
- }
- return pinEvents;
- }
-
-
- private ArrayList<AppTarget> getPinnedAppTargetsInViewGroup(ViewGroup viewGroup) {
- ArrayList<AppTarget> pinnedApps = new ArrayList<>();
- for (int i = 0; i < viewGroup.getChildCount(); i++) {
- View child = viewGroup.getChildAt(i);
- if (isPinnedIcon(child)) {
- WorkspaceItemInfo itemInfo = (WorkspaceItemInfo) child.getTag();
- pinnedApps.add(getAppTargetFromItemInfo(itemInfo));
- }
- }
- return pinnedApps;
- }
-
private void setPredictedApps(List<AppTarget> appTargets) {
mComponentKeyMappers.clear();
StringBuilder predictionLog = new StringBuilder("predictedApps: [\n");
@@ -443,8 +379,11 @@
workspaceItemInfo.cellX, workspaceItemInfo.cellY);
ObjectAnimator.ofFloat(icon, SCALE_PROPERTY, 1, 0.8f, 1).start();
icon.pin(workspaceItemInfo);
- AppTarget appTarget = getAppTargetFromItemInfo(workspaceItemInfo);
- notifyItemAction(appTarget, APP_LOCATION_HOTSEAT, AppTargetEvent.ACTION_PIN);
+ AppTarget appTarget = mPredictionModel.getAppTargetFromInfo(workspaceItemInfo);
+ if (appTarget != null) {
+ notifyItemAction(mPredictionModel.wrapAppTargetWithLocation(appTarget,
+ AppTargetEvent.ACTION_PIN, workspaceItemInfo));
+ }
mRequiresCacheUpdate = true;
}
@@ -524,10 +463,9 @@
mIconRemoveAnimators.start();
}
- private void notifyItemAction(AppTarget target, String location, int action) {
+ private void notifyItemAction(AppTargetEvent event) {
if (mAppPredictor != null) {
- mAppPredictor.notifyAppTargetEvent(new AppTargetEvent.Builder(target,
- action).setLaunchLocation(location).build());
+ mAppPredictor.notifyAppTargetEvent(event);
}
}
@@ -545,36 +483,35 @@
/**
* Unpins pinned app when it's converted into a folder
*/
- public void folderCreatedFromWorkspaceItem(ItemInfo info, FolderInfo folderInfo) {
- if (info.itemType != LauncherSettings.Favorites.ITEM_TYPE_APPLICATION) {
- return;
+ public void folderCreatedFromWorkspaceItem(ItemInfo itemInfo, FolderInfo folderInfo) {
+ AppTarget folderTarget = mPredictionModel.getAppTargetFromInfo(folderInfo);
+ AppTarget itemTarget = mPredictionModel.getAppTargetFromInfo(itemInfo);
+ if (folderTarget != null && HotseatPredictionModel.isTrackedForPrediction(folderInfo)) {
+ notifyItemAction(mPredictionModel.wrapAppTargetWithLocation(folderTarget,
+ AppTargetEvent.ACTION_PIN, folderInfo));
}
- AppTarget target = getAppTargetFromItemInfo(info);
- ViewGroup hotseatVG = mHotseat.getShortcutsAndWidgets();
- ViewGroup firstScreenVG = mLauncher.getWorkspace().getScreenWithId(
- Workspace.FIRST_SCREEN_ID).getShortcutsAndWidgets();
-
- if (isInHotseat(folderInfo) && !getPinnedAppTargetsInViewGroup(hotseatVG).contains(
- target)) {
- notifyItemAction(target, APP_LOCATION_HOTSEAT, APPTARGET_ACTION_UNPIN);
- } else if (isInFirstPage(folderInfo) && !getPinnedAppTargetsInViewGroup(
- firstScreenVG).contains(target)) {
- notifyItemAction(target, APP_LOCATION_WORKSPACE, APPTARGET_ACTION_UNPIN);
+ // using folder info with isTrackedForPrediction as itemInfo.container is already changed
+ // to folder by this point
+ if (itemTarget != null && HotseatPredictionModel.isTrackedForPrediction(folderInfo)) {
+ notifyItemAction(mPredictionModel.wrapAppTargetWithLocation(itemTarget,
+ AppTargetEvent.ACTION_UNPIN, folderInfo
+ ));
}
}
/**
* Pins workspace item created when all folder items are removed but one
*/
- public void folderConvertedToWorkspaceItem(ItemInfo info, FolderInfo folderInfo) {
- if (info.itemType != LauncherSettings.Favorites.ITEM_TYPE_APPLICATION) {
- return;
+ public void folderConvertedToWorkspaceItem(ItemInfo itemInfo, FolderInfo folderInfo) {
+ AppTarget folderTarget = mPredictionModel.getAppTargetFromInfo(folderInfo);
+ AppTarget itemTarget = mPredictionModel.getAppTargetFromInfo(itemInfo);
+ if (folderTarget != null && HotseatPredictionModel.isTrackedForPrediction(folderInfo)) {
+ notifyItemAction(mPredictionModel.wrapAppTargetWithLocation(folderTarget,
+ AppTargetEvent.ACTION_UNPIN, folderInfo));
}
- AppTarget target = getAppTargetFromItemInfo(info);
- if (isInHotseat(info)) {
- notifyItemAction(target, APP_LOCATION_HOTSEAT, AppTargetEvent.ACTION_PIN);
- } else if (isInFirstPage(info)) {
- notifyItemAction(target, APP_LOCATION_WORKSPACE, AppTargetEvent.ACTION_PIN);
+ if (itemTarget != null && HotseatPredictionModel.isTrackedForPrediction(itemInfo)) {
+ notifyItemAction(mPredictionModel.wrapAppTargetWithLocation(itemTarget,
+ AppTargetEvent.ACTION_PIN, itemInfo));
}
}
@@ -585,29 +522,18 @@
}
ItemInfo dragInfo = mDragObject.dragInfo;
- ViewGroup hotseatVG = mHotseat.getShortcutsAndWidgets();
- ViewGroup firstScreenVG = mLauncher.getWorkspace().getScreenWithId(
- Workspace.FIRST_SCREEN_ID).getShortcutsAndWidgets();
-
- if (dragInfo instanceof WorkspaceItemInfo
- && dragInfo.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION
- && dragInfo.getTargetComponent() != null) {
- AppTarget appTarget = getAppTargetFromItemInfo(dragInfo);
- if (!isInHotseat(dragInfo) && isInHotseat(mDragObject.originalDragInfo)) {
- if (!getPinnedAppTargetsInViewGroup(hotseatVG).contains(appTarget)) {
- notifyItemAction(appTarget, APP_LOCATION_HOTSEAT, APPTARGET_ACTION_UNPIN);
- }
+ if (mDragObject.isMoved()) {
+ AppTarget appTarget = mPredictionModel.getAppTargetFromInfo(dragInfo);
+ //always send pin event first to prevent AiAi from predicting an item moved within
+ // the same page
+ if (appTarget != null && HotseatPredictionModel.isTrackedForPrediction(dragInfo)) {
+ notifyItemAction(mPredictionModel.wrapAppTargetWithLocation(appTarget,
+ AppTargetEvent.ACTION_PIN, dragInfo));
}
- if (!isInFirstPage(dragInfo) && isInFirstPage(mDragObject.originalDragInfo)) {
- if (!getPinnedAppTargetsInViewGroup(firstScreenVG).contains(appTarget)) {
- notifyItemAction(appTarget, APP_LOCATION_WORKSPACE, APPTARGET_ACTION_UNPIN);
- }
- }
- if (isInHotseat(dragInfo) && !isInHotseat(mDragObject.originalDragInfo)) {
- notifyItemAction(appTarget, APP_LOCATION_HOTSEAT, AppTargetEvent.ACTION_PIN);
- }
- if (isInFirstPage(dragInfo) && !isInFirstPage(mDragObject.originalDragInfo)) {
- notifyItemAction(appTarget, APP_LOCATION_WORKSPACE, AppTargetEvent.ACTION_PIN);
+ if (appTarget != null && HotseatPredictionModel.isTrackedForPrediction(
+ mDragObject.originalDragInfo)) {
+ notifyItemAction(mPredictionModel.wrapAppTargetWithLocation(appTarget,
+ AppTargetEvent.ACTION_UNPIN, mDragObject.originalDragInfo));
}
}
mDragObject = null;
@@ -615,6 +541,7 @@
mRequiresCacheUpdate = true;
}
+
@Nullable
@Override
public SystemShortcut<QuickstepLauncher> getShortcut(QuickstepLauncher activity,
@@ -711,77 +638,4 @@
&& ((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_PREDICTION && (
- info.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION);
- }
-
- private static boolean isInHotseat(ItemInfo itemInfo) {
- return itemInfo.container == LauncherSettings.Favorites.CONTAINER_HOTSEAT;
- }
-
- private static boolean isInFirstPage(ItemInfo itemInfo) {
- return itemInfo.container == LauncherSettings.Favorites.CONTAINER_DESKTOP
- && itemInfo.screenId == Workspace.FIRST_SCREEN_ID;
- }
-
- private static AppTarget getAppTargetFromItemInfo(ItemInfo info) {
- if (info.getTargetComponent() == null) return null;
- ComponentName cn = info.getTargetComponent();
- return new AppTarget.Builder(new AppTargetId("app:" + cn.getPackageName()),
- cn.getPackageName(), info.user).setClassName(cn.getClassName()).build();
- }
-
- private AppTarget getAppTargetFromInfo(ItemInfo info) {
- if (info == null) return null;
- if (info.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET
- && info instanceof LauncherAppWidgetInfo
- && ((LauncherAppWidgetInfo) info).providerName != null) {
- ComponentName cn = ((LauncherAppWidgetInfo) info).providerName;
- return new AppTarget.Builder(new AppTargetId("widget:" + cn.getPackageName()),
- cn.getPackageName(), info.user).setClassName(cn.getClassName()).build();
- } else if (info.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION
- && info.getTargetComponent() != null) {
- ComponentName cn = info.getTargetComponent();
- return new AppTarget.Builder(new AppTargetId("app:" + cn.getPackageName()),
- cn.getPackageName(), info.user).setClassName(cn.getClassName()).build();
- } else if (info.itemType == LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT
- && info instanceof WorkspaceItemInfo) {
- ShortcutKey shortcutKey = ShortcutKey.fromItemInfo(info);
- //TODO: switch to using full shortcut info
- return new AppTarget.Builder(new AppTargetId("shortcut:" + shortcutKey.getId()),
- shortcutKey.componentName.getPackageName(), shortcutKey.user).build();
- } else if (info.itemType == LauncherSettings.Favorites.ITEM_TYPE_FOLDER) {
- return new AppTarget.Builder(new AppTargetId("folder:" + info.id),
- mLauncher.getPackageName(), info.user).build();
- }
- return null;
- }
-
- private AppTargetEvent wrapAppTargetWithLocation(AppTarget target, int action, ItemInfo info) {
- return wrapAppTargetWithLocation(target, action,
- info.container == LauncherSettings.Favorites.CONTAINER_HOTSEAT
- ? APP_LOCATION_HOTSEAT : APP_LOCATION_WORKSPACE, info.screenId, info.cellX,
- info.cellY, info.spanX, info.spanY);
- }
-
- private AppTargetEvent wrapAppTargetWithLocation(AppTarget target, int action, String root,
- int screenId, int x, int y, int spanX, int spanY) {
- return new AppTargetEvent.Builder(target, action).setLaunchLocation(
- String.format(Locale.ENGLISH, "%s/%d/[%d,%d]/[%d,%d]", root, screenId, x, y, spanX,
- spanY)).build();
- }
-
- /**
- * A helper method to generate an AppTarget that's used to communicate workspace layout
- */
- private AppTarget getBlockAppTarget() {
- return new AppTarget.Builder(new AppTargetId("block"),
- mLauncher.getPackageName(), Process.myUserHandle()).build();
- }
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatPredictionModel.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatPredictionModel.java
new file mode 100644
index 0000000..5a038d2
--- /dev/null
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatPredictionModel.java
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.hybridhotseat;
+
+import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
+
+import android.app.prediction.AppTarget;
+import android.app.prediction.AppTargetEvent;
+import android.app.prediction.AppTargetId;
+import android.content.ComponentName;
+import android.content.Context;
+import android.os.Bundle;
+
+import com.android.launcher3.LauncherAppState;
+import com.android.launcher3.LauncherSettings;
+import com.android.launcher3.Workspace;
+import com.android.launcher3.model.AllAppsList;
+import com.android.launcher3.model.BaseModelUpdateTask;
+import com.android.launcher3.model.BgDataModel;
+import com.android.launcher3.model.PredictionModel;
+import com.android.launcher3.model.data.ItemInfo;
+import com.android.launcher3.model.data.LauncherAppWidgetInfo;
+import com.android.launcher3.model.data.WorkspaceItemInfo;
+import com.android.launcher3.shortcuts.ShortcutKey;
+
+import java.util.ArrayList;
+import java.util.Locale;
+import java.util.function.Consumer;
+
+/**
+ * Model helper for app predictions in workspace
+ */
+public class HotseatPredictionModel extends PredictionModel {
+ private static final String APP_LOCATION_HOTSEAT = "hotseat";
+ private static final String APP_LOCATION_WORKSPACE = "workspace";
+
+ private static final String BUNDLE_KEY_PIN_EVENTS = "pin_events";
+ private static final String BUNDLE_KEY_CURRENT_ITEMS = "current_items";
+
+
+ public HotseatPredictionModel(Context context) { }
+
+ /**
+ * Creates and returns bundle using workspace items and cached items
+ */
+ public void createBundle(Consumer<Bundle> cb) {
+ LauncherAppState appState = LauncherAppState.getInstance(mContext);
+ appState.getModel().enqueueModelUpdateTask(new BaseModelUpdateTask() {
+ @Override
+ public void execute(LauncherAppState app, BgDataModel dataModel, AllAppsList apps) {
+ Bundle bundle = new Bundle();
+ ArrayList<AppTargetEvent> events = new ArrayList<>();
+ ArrayList<ItemInfo> workspaceItems = new ArrayList<>(dataModel.workspaceItems);
+ workspaceItems.addAll(dataModel.appWidgets);
+ for (ItemInfo item : workspaceItems) {
+ AppTarget target = getAppTargetFromInfo(item);
+ if (target != null && !isTrackedForPrediction(item)) continue;
+ events.add(wrapAppTargetWithLocation(target, AppTargetEvent.ACTION_PIN, item));
+ }
+ ArrayList<AppTarget> currentTargets = new ArrayList<>();
+ for (ItemInfo itemInfo : dataModel.cachedPredictedItems) {
+ AppTarget target = getAppTargetFromInfo(itemInfo);
+ if (target != null) currentTargets.add(target);
+ }
+ bundle.putParcelableArrayList(BUNDLE_KEY_PIN_EVENTS, events);
+ bundle.putParcelableArrayList(BUNDLE_KEY_CURRENT_ITEMS, currentTargets);
+ MAIN_EXECUTOR.execute(() -> cb.accept(bundle));
+ }
+ });
+ }
+
+ /**
+ * Creates and returns for {@link AppTarget} object given an {@link ItemInfo}. Returns null
+ * if item is not supported prediction
+ */
+ public AppTarget getAppTargetFromInfo(ItemInfo info) {
+ if (info == null) return null;
+ if (info.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET
+ && info instanceof LauncherAppWidgetInfo
+ && ((LauncherAppWidgetInfo) info).providerName != null) {
+ ComponentName cn = ((LauncherAppWidgetInfo) info).providerName;
+ return new AppTarget.Builder(new AppTargetId("widget:" + cn.getPackageName()),
+ cn.getPackageName(), info.user).setClassName(cn.getClassName()).build();
+ } else if (info.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION
+ && info.getTargetComponent() != null) {
+ ComponentName cn = info.getTargetComponent();
+ return new AppTarget.Builder(new AppTargetId("app:" + cn.getPackageName()),
+ cn.getPackageName(), info.user).setClassName(cn.getClassName()).build();
+ } else if (info.itemType == LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT
+ && info instanceof WorkspaceItemInfo) {
+ ShortcutKey shortcutKey = ShortcutKey.fromItemInfo(info);
+ //TODO: switch to using full shortcut info
+ return new AppTarget.Builder(new AppTargetId("shortcut:" + shortcutKey.getId()),
+ shortcutKey.componentName.getPackageName(), shortcutKey.user).build();
+ } else if (info.itemType == LauncherSettings.Favorites.ITEM_TYPE_FOLDER) {
+ return new AppTarget.Builder(new AppTargetId("folder:" + info.id),
+ mContext.getPackageName(), info.user).build();
+ }
+ return null;
+ }
+
+
+ /**
+ * Creates and returns {@link AppTargetEvent} from an {@link AppTarget}, action, and item
+ * location using {@link ItemInfo}
+ */
+ public AppTargetEvent wrapAppTargetWithLocation(AppTarget target, int action, ItemInfo info) {
+ String location = String.format(Locale.ENGLISH, "%s/%d/[%d,%d]/[%d,%d]",
+ info.container == LauncherSettings.Favorites.CONTAINER_HOTSEAT
+ ? APP_LOCATION_HOTSEAT : APP_LOCATION_WORKSPACE,
+ info.screenId, info.cellX, info.cellY, info.spanX, info.spanY);
+ return new AppTargetEvent.Builder(target, action).setLaunchLocation(location).build();
+ }
+
+ /**
+ * Helper method to determine if {@link ItemInfo} should be tracked and reported to predictors
+ */
+ public static boolean isTrackedForPrediction(ItemInfo info) {
+ return info.container == LauncherSettings.Favorites.CONTAINER_HOTSEAT || (
+ info.container == LauncherSettings.Favorites.CONTAINER_DESKTOP
+ && info.screenId == Workspace.FIRST_SCREEN_ID);
+ }
+}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java
index d841511..8bffc78 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java
@@ -540,8 +540,6 @@
boolean canStartSystemGesture = mDeviceState.canStartSystemGesture();
if (!mDeviceState.isUserUnlocked()) {
- Log.d(TAG, "User locked. Can start system gesture? " + canStartSystemGesture
- + " sysUiFlags: " + mDeviceState.getSystemUiStateFlags());
if (canStartSystemGesture) {
// This handles apps launched in direct boot mode (e.g. dialer) as well as apps
// launched while device is locked even after exiting direct boot mode (e.g. camera).
diff --git a/quickstep/src/com/android/quickstep/GestureState.java b/quickstep/src/com/android/quickstep/GestureState.java
index 8e14bbb..016ffea 100644
--- a/quickstep/src/com/android/quickstep/GestureState.java
+++ b/quickstep/src/com/android/quickstep/GestureState.java
@@ -322,7 +322,7 @@
pw.println(" gestureID=" + mGestureId);
pw.println(" runningTask=" + mRunningTask);
pw.println(" endTarget=" + mEndTarget);
- pw.println(" lastAppearedTaskTarget=" + mLastAppearedTaskTarget);
+ pw.println(" lastAppearedTaskTargetId=" + getLastAppearedTaskId());
pw.println(" lastStartedTaskId=" + mLastStartedTaskId);
pw.println(" isRecentsAnimationRunning=" + isRecentsAnimationRunning());
}
diff --git a/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java b/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java
index 8ac15e8..a892ddc 100644
--- a/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java
+++ b/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java
@@ -73,8 +73,6 @@
NavigationModeChangeListener,
DefaultDisplay.DisplayInfoChangeListener {
- private static final String TAG = "RecentsAnimationDeviceState";
-
private final Context mContext;
private final SysUINavigationMode mSysUiNavMode;
private final DefaultDisplay mDefaultDisplay;
@@ -97,7 +95,6 @@
@Override
public void onReceive(Context context, Intent intent) {
if (ACTION_USER_UNLOCKED.equals(intent.getAction())) {
- Log.d(TAG, "User Unlocked Broadcast Received");
mIsUserUnlocked = true;
notifyUserUnlocked();
}
diff --git a/res/values/config.xml b/res/values/config.xml
index 603dc91..4cbc597 100644
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -69,6 +69,7 @@
<string name="app_launch_tracker_class" translatable="false"></string>
<string name="test_information_handler_class" translatable="false"></string>
<string name="launcher_activity_logic_class" translatable="false"></string>
+ <string name="prediction_model_class" translatable="false"></string>
<!-- View ID to use for QSB widget -->
<item type="id" name="qsb_widget" />
diff --git a/src/com/android/launcher3/DropTarget.java b/src/com/android/launcher3/DropTarget.java
index 0b0983c..c1aed98 100644
--- a/src/com/android/launcher3/DropTarget.java
+++ b/src/com/android/launcher3/DropTarget.java
@@ -110,6 +110,18 @@
return res;
}
+
+
+ /**
+ * This is used to determine if an object is dropped at a different location than it was
+ * dragged from
+ */
+ public boolean isMoved() {
+ return dragInfo.cellX != originalDragInfo.cellX
+ || dragInfo.cellY != originalDragInfo.cellY
+ || dragInfo.screenId != originalDragInfo.screenId
+ || dragInfo.container != originalDragInfo.container;
+ }
}
/**
diff --git a/src/com/android/launcher3/LauncherAppState.java b/src/com/android/launcher3/LauncherAppState.java
index 14e604d..53e5274 100644
--- a/src/com/android/launcher3/LauncherAppState.java
+++ b/src/com/android/launcher3/LauncherAppState.java
@@ -129,7 +129,7 @@
mIconCache = new IconCache(mContext, mInvariantDeviceProfile, iconCacheFileName);
mWidgetCache = new WidgetPreviewLoader(mContext, mIconCache);
mModel = new LauncherModel(this, mIconCache, AppFilter.newInstance(mContext));
- mPredictionModel = new PredictionModel(mContext);
+ mPredictionModel = PredictionModel.newInstance(mContext);
}
protected void onNotificationSettingsChanged(boolean areNotificationDotsEnabled) {
diff --git a/src/com/android/launcher3/allapps/LauncherAllAppsContainerView.java b/src/com/android/launcher3/allapps/LauncherAllAppsContainerView.java
index 80b6a5a..a6bc6cf 100644
--- a/src/com/android/launcher3/allapps/LauncherAllAppsContainerView.java
+++ b/src/com/android/launcher3/allapps/LauncherAllAppsContainerView.java
@@ -60,6 +60,14 @@
}
@Override
+ public boolean onTouchEvent(MotionEvent ev) {
+ if (!mLauncher.isInState(LauncherState.ALL_APPS)) {
+ return false;
+ }
+ return super.onTouchEvent(ev);
+ }
+
+ @Override
public void setInsets(Rect insets) {
super.setInsets(insets);
mLauncher.getAllAppsController()
diff --git a/src/com/android/launcher3/logging/StatsLogManager.java b/src/com/android/launcher3/logging/StatsLogManager.java
index b240f0b..475305f 100644
--- a/src/com/android/launcher3/logging/StatsLogManager.java
+++ b/src/com/android/launcher3/logging/StatsLogManager.java
@@ -35,50 +35,50 @@
}
public enum LauncherEvent implements EventEnum {
- @LauncherUiEvent(doc = "App launched from workspace, hotseat or folder in launcher")
+ @UiEvent(doc = "App launched from workspace, hotseat or folder in launcher")
LAUNCHER_APP_LAUNCH_TAP(338),
- @LauncherUiEvent(doc = "Task launched from overview using TAP")
+ @UiEvent(doc = "Task launched from overview using TAP")
LAUNCHER_TASK_LAUNCH_TAP(339),
- @LauncherUiEvent(doc = "Task launched from overview using SWIPE DOWN")
+ @UiEvent(doc = "Task launched from overview using SWIPE DOWN")
LAUNCHER_TASK_LAUNCH_SWIPE_DOWN(340),
- @LauncherUiEvent(doc = "TASK dismissed from overview using SWIPE UP")
+ @UiEvent(doc = "TASK dismissed from overview using SWIPE UP")
LAUNCHER_TASK_DISMISS_SWIPE_UP(341),
- @LauncherUiEvent(doc = "User dragged a launcher item")
+ @UiEvent(doc = "User dragged a launcher item")
LAUNCHER_ITEM_DRAG_STARTED(383),
- @LauncherUiEvent(doc = "A dragged launcher item is successfully dropped")
+ @UiEvent(doc = "A dragged launcher item is successfully dropped")
LAUNCHER_ITEM_DROP_COMPLETED(385),
- @LauncherUiEvent(doc = "A dragged launcher item is successfully dropped on another item "
+ @UiEvent(doc = "A dragged launcher item is successfully dropped on another item "
+ "resulting in a new folder creation")
LAUNCHER_ITEM_DROP_FOLDER_CREATED(386),
- @LauncherUiEvent(doc = "User action resulted in or manually updated the folder label to "
+ @UiEvent(doc = "User action resulted in or manually updated the folder label to "
+ "new/same value.")
LAUNCHER_FOLDER_LABEL_UPDATED(460),
- @LauncherUiEvent(doc = "A dragged item is dropped on 'Remove' button in the target bar")
+ @UiEvent(doc = "A dragged item is dropped on 'Remove' button in the target bar")
LAUNCHER_ITEM_DROPPED_ON_REMOVE(465),
- @LauncherUiEvent(doc = "A dragged item is dropped on 'Cancel' button in the target bar")
+ @UiEvent(doc = "A dragged item is dropped on 'Cancel' button in the target bar")
LAUNCHER_ITEM_DROPPED_ON_CANCEL(466),
- @LauncherUiEvent(doc = "A predicted item is dragged and dropped on 'Don't suggest app'"
+ @UiEvent(doc = "A predicted item is dragged and dropped on 'Don't suggest app'"
+ " button in the target bar")
LAUNCHER_ITEM_DROPPED_ON_DONT_SUGGEST(467),
- @LauncherUiEvent(doc = "A dragged item is dropped on 'Uninstall' button in target bar")
+ @UiEvent(doc = "A dragged item is dropped on 'Uninstall' button in target bar")
LAUNCHER_ITEM_DROPPED_ON_UNINSTALL(468),
- @LauncherUiEvent(doc = "User completed uninstalling the package after dropping on "
+ @UiEvent(doc = "User completed uninstalling the package after dropping on "
+ "the icon onto 'Uninstall' button in the target bar")
LAUNCHER_ITEM_UNINSTALL_COMPLETED(469),
- @LauncherUiEvent(doc = "User cancelled uninstalling the package after dropping on "
+ @UiEvent(doc = "User cancelled uninstalling the package after dropping on "
+ "the icon onto 'Uninstall' button in the target bar")
LAUNCHER_ITEM_UNINSTALL_CANCELLED(470);
// ADD MORE
diff --git a/src/com/android/launcher3/logging/LauncherUiEvent.java b/src/com/android/launcher3/logging/UiEvent.java
similarity index 80%
rename from src/com/android/launcher3/logging/LauncherUiEvent.java
rename to src/com/android/launcher3/logging/UiEvent.java
index 4507ff7..20d6c72 100644
--- a/src/com/android/launcher3/logging/LauncherUiEvent.java
+++ b/src/com/android/launcher3/logging/UiEvent.java
@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+
package com.android.launcher3.logging;
import static java.lang.annotation.ElementType.FIELD;
@@ -23,8 +24,11 @@
@Retention(SOURCE)
@Target(FIELD)
-public @interface LauncherUiEvent {
- /** An explanation, suitable for Android analysts, of the UI event that this log represents. */
+// Copy of frameworks/base/core/java/com/android/internal/logging/UiEvent.java
+public @interface UiEvent {
+
+ /**
+ * An explanation, suitable for Android analysts, of the UI event that this log represents.
+ */
String doc();
}
-
diff --git a/src/com/android/launcher3/model/BaseLoaderResults.java b/src/com/android/launcher3/model/BaseLoaderResults.java
index 1465100..ab921ea 100644
--- a/src/com/android/launcher3/model/BaseLoaderResults.java
+++ b/src/com/android/launcher3/model/BaseLoaderResults.java
@@ -253,8 +253,8 @@
}
private void bindPredictedItems(IntArray ranks, final Executor executor) {
- executeCallbacksTask(
- c -> c.bindPredictedItems(mBgDataModel.cachedPredictedItems, ranks), executor);
+ ArrayList<AppInfo> items = new ArrayList<>(mBgDataModel.cachedPredictedItems);
+ executeCallbacksTask(c -> c.bindPredictedItems(items, ranks), executor);
}
protected void executeCallbacksTask(CallbackTask task, Executor executor) {
diff --git a/src/com/android/launcher3/model/LoaderTask.java b/src/com/android/launcher3/model/LoaderTask.java
index 9e6282e..d05d70b 100644
--- a/src/com/android/launcher3/model/LoaderTask.java
+++ b/src/com/android/launcher3/model/LoaderTask.java
@@ -45,6 +45,8 @@
import android.util.MutableInt;
import android.util.TimingLogger;
+import androidx.annotation.WorkerThread;
+
import com.android.launcher3.InstallShortcutReceiver;
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.LauncherModel;
@@ -850,12 +852,11 @@
}
}
- private List<AppInfo> loadCachedPredictions() {
+ @WorkerThread
+ private void loadCachedPredictions() {
synchronized (mBgDataModel) {
List<ComponentKey> componentKeys =
mApp.getPredictionModel().getPredictionComponentKeys();
- List<AppInfo> results = new ArrayList<>();
- if (componentKeys == null) return results;
List<LauncherActivityInfo> l;
mBgDataModel.cachedPredictedItems.clear();
for (ComponentKey key : componentKeys) {
@@ -866,7 +867,6 @@
mBgDataModel.cachedPredictedItems.add(info);
mIconCache.getTitleAndIcon(info, false);
}
- return results;
}
}
diff --git a/src/com/android/launcher3/model/PredictionModel.java b/src/com/android/launcher3/model/PredictionModel.java
index 6aa41eb..1429843 100644
--- a/src/com/android/launcher3/model/PredictionModel.java
+++ b/src/com/android/launcher3/model/PredictionModel.java
@@ -14,80 +14,111 @@
* limitations under the License.
*/
package com.android.launcher3.model;
+import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
+import android.content.ComponentName;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.UserHandle;
+import androidx.annotation.AnyThread;
+import androidx.annotation.WorkerThread;
+
+import com.android.launcher3.R;
import com.android.launcher3.Utilities;
-import com.android.launcher3.model.data.AppInfo;
+import com.android.launcher3.pm.UserCache;
import com.android.launcher3.util.ComponentKey;
+import com.android.launcher3.util.Preconditions;
+import com.android.launcher3.util.ResourceBasedOverride;
import java.util.ArrayList;
import java.util.List;
-import java.util.stream.Collectors;
/**
- * Model helper for app predictions in workspace
+ * Model Helper for app predictions
*/
-public class PredictionModel {
+public class PredictionModel implements ResourceBasedOverride {
+
private static final String CACHED_ITEMS_KEY = "predicted_item_keys";
private static final int MAX_CACHE_ITEMS = 5;
- private final Context mContext;
- private final SharedPreferences mDevicePrefs;
- private ArrayList<ComponentKey> mCachedComponentKeys;
+ protected Context mContext;
+ private SharedPreferences mDevicePrefs;
+ private UserCache mUserCache;
- public PredictionModel(Context context) {
- mContext = context;
- mDevicePrefs = Utilities.getDevicePrefs(mContext);
+
+ /**
+ * Retrieve instance of this object that can be overridden in runtime based on the build
+ * variant of the application.
+ */
+ public static PredictionModel newInstance(Context context) {
+ PredictionModel model = Overrides.getObject(PredictionModel.class, context,
+ R.string.prediction_model_class);
+ model.init(context);
+ return model;
}
+ protected void init(Context context) {
+ mContext = context;
+ mDevicePrefs = Utilities.getDevicePrefs(mContext);
+ mUserCache = UserCache.INSTANCE.get(mContext);
+
+ }
/**
* Formats and stores a list of component key in device preferences.
*/
+ @AnyThread
public void cachePredictionComponentKeys(List<ComponentKey> componentKeys) {
- StringBuilder builder = new StringBuilder();
- int count = Math.min(componentKeys.size(), MAX_CACHE_ITEMS);
- for (int i = 0; i < count; i++) {
- builder.append(componentKeys.get(i));
- builder.append("\n");
- }
- mDevicePrefs.edit().putString(CACHED_ITEMS_KEY, builder.toString()).apply();
- mCachedComponentKeys = null;
+ MODEL_EXECUTOR.execute(() -> {
+ StringBuilder builder = new StringBuilder();
+ int count = Math.min(componentKeys.size(), MAX_CACHE_ITEMS);
+ for (int i = 0; i < count; i++) {
+ builder.append(serializeComponentKeyToString(componentKeys.get(i)));
+ builder.append("\n");
+ }
+ mDevicePrefs.edit().putString(CACHED_ITEMS_KEY, builder.toString()).apply();
+ });
}
/**
* parses and returns ComponentKeys saved by
* {@link PredictionModel#cachePredictionComponentKeys(List)}
*/
+ @WorkerThread
public List<ComponentKey> getPredictionComponentKeys() {
- if (mCachedComponentKeys == null) {
- mCachedComponentKeys = new ArrayList<>();
-
- String cachedBlob = mDevicePrefs.getString(CACHED_ITEMS_KEY, "");
- for (String line : cachedBlob.split("\n")) {
- ComponentKey key = ComponentKey.fromString(line);
- if (key != null) {
- mCachedComponentKeys.add(key);
- }
+ Preconditions.assertWorkerThread();
+ ArrayList<ComponentKey> items = new ArrayList<>();
+ String cachedBlob = mDevicePrefs.getString(CACHED_ITEMS_KEY, "");
+ for (String line : cachedBlob.split("\n")) {
+ ComponentKey key = getComponentKeyFromSerializedString(line);
+ if (key != null) {
+ items.add(key);
}
+
}
- return mCachedComponentKeys;
+ return items;
}
- /**
- * Remove uninstalled applications from model
- */
- public void removePackage(String pkgName, UserHandle user, ArrayList<AppInfo> ids) {
- for (int i = ids.size() - 1; i >= 0; i--) {
- AppInfo info = ids.get(i);
- if (info.user.equals(user) && pkgName.equals(info.componentName.getPackageName())) {
- ids.remove(i);
- }
+ private String serializeComponentKeyToString(ComponentKey componentKey) {
+ long userSerialNumber = mUserCache.getSerialNumberForUser(componentKey.user);
+ return componentKey.componentName.flattenToString() + "#" + userSerialNumber;
+ }
+
+ private ComponentKey getComponentKeyFromSerializedString(String str) {
+ int sep = str.indexOf('#');
+ if (sep < 0 || (sep + 1) >= str.length()) {
+ return null;
}
- cachePredictionComponentKeys(getPredictionComponentKeys().stream()
- .filter(cn -> !(cn.user.equals(user) && cn.componentName.getPackageName().equals(
- pkgName))).collect(Collectors.toList()));
+ ComponentName componentName = ComponentName.unflattenFromString(str.substring(0, sep));
+ if (componentName == null) {
+ return null;
+ }
+ try {
+ long serialNumber = Long.parseLong(str.substring(sep + 1));
+ UserHandle userHandle = mUserCache.getUserForSerialNumber(serialNumber);
+ return userHandle != null ? new ComponentKey(componentName, userHandle) : null;
+ } catch (NumberFormatException ex) {
+ return null;
+ }
}
}
diff --git a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
index 14212be..4493279 100644
--- a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
+++ b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
@@ -436,9 +436,12 @@
sEventChecker.finishNoWait();
}
}
- // b/156287114
+
try {
- log("Input: " + mDevice.executeShellCommand("dumpsys input"));
+ Log.e("b/156287114", "Input:");
+ for (String line : mDevice.executeShellCommand("dumpsys input").split("\\n")) {
+ Log.d("b/156287114", line);
+ }
} catch (IOException e) {
e.printStackTrace();
}
@@ -1320,6 +1323,16 @@
if (mCheckEventsForSuccessfulGestures) {
final String message = sEventChecker.verify(WAIT_TIME_MS, true);
if (message != null) {
+ try {
+ Log.e("b/156287114", "Input:");
+ for (String line : mDevice.executeShellCommand("dumpsys input").split(
+ "\\n")) {
+ Log.d("b/156287114", line);
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+
checkForAnomaly();
Assert.fail(formatSystemHealthMessage(
"http://go/tapl : successful gesture produced " + message));