From 87a4d89e8055333705f8a54081213bd344a7ac89 Mon Sep 17 00:00:00 2001 From: Samuel Fufa Date: Mon, 13 Apr 2020 23:37:49 -0700 Subject: [PATCH] Cache hotseat predictions Saves a list of ComponentKeys to allow launcher to show predictions while AiAi is booting up. Cache is invalidated on new predictor creation, on user changing home screen set up, or after receiving an empty list of predictions from AiAi. Bug: 152582306 Test: Manual Change-Id: I2047aa3bcbf8bc1ef9b7b6a7925ef14a3433a3b4 --- .../appprediction/ComponentKeyMapper.java | 6 +-- .../appprediction/DynamicItemCache.java | 5 +- .../HotseatPredictionController.java | 47 +++++++++++++++++++ 3 files changed, 52 insertions(+), 6 deletions(-) diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/ComponentKeyMapper.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/ComponentKeyMapper.java index fdb8e4c571..d200868899 100644 --- a/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/ComponentKeyMapper.java +++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/ComponentKeyMapper.java @@ -21,7 +21,6 @@ import static com.android.quickstep.InstantAppResolverImpl.COMPONENT_CLASS_MARKE import com.android.launcher3.allapps.AllAppsStore; import com.android.launcher3.model.data.AppInfo; import com.android.launcher3.model.data.ItemInfoWithIcon; -import com.android.launcher3.shortcuts.ShortcutKey; import com.android.launcher3.util.ComponentKey; public class ComponentKeyMapper { @@ -57,9 +56,8 @@ public class ComponentKeyMapper { return item; } else if (getComponentClass().equals(COMPONENT_CLASS_MARKER)) { return mCache.getInstantApp(componentKey.componentName.getPackageName()); - } else if (componentKey instanceof ShortcutKey) { - return mCache.getShortcutInfo((ShortcutKey) componentKey); + } else { + return mCache.getShortcutInfo(componentKey); } - return null; } } diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/DynamicItemCache.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/DynamicItemCache.java index 6c4bfe8a21..ab96b1340a 100644 --- a/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/DynamicItemCache.java +++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/DynamicItemCache.java @@ -45,6 +45,7 @@ import com.android.launcher3.model.data.AppInfo; import com.android.launcher3.model.data.WorkspaceItemInfo; import com.android.launcher3.shortcuts.ShortcutKey; import com.android.launcher3.shortcuts.ShortcutRequest; +import com.android.launcher3.util.ComponentKey; import com.android.launcher3.util.InstantAppResolver; import java.util.ArrayList; @@ -76,7 +77,7 @@ public class DynamicItemCache { private final Runnable mOnUpdateCallback; private final IconCache mIconCache; - private final Map mShortcuts; + private final Map mShortcuts; private final Map mInstantApps; public DynamicItemCache(Context context, Runnable onUpdateCallback) { @@ -230,7 +231,7 @@ public class DynamicItemCache { } @MainThread - public WorkspaceItemInfo getShortcutInfo(ShortcutKey key) { + public WorkspaceItemInfo getShortcutInfo(ComponentKey key) { return mShortcuts.get(key); } 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 7c002875fa..e7398ab528 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 @@ -97,6 +97,8 @@ public class HotseatPredictionController implements DragController.DragListener, //TODO: replace this with AppTargetEvent.ACTION_UNPIN (b/144119543) private static final int APPTARGET_ACTION_UNPIN = 4; + private static final String PREDICTED_ITEMS_CACHE_KEY = "predicted_item_keys"; + private static final String APP_LOCATION_HOTSEAT = "hotseat"; private static final String APP_LOCATION_WORKSPACE = "workspace"; @@ -119,6 +121,7 @@ public class HotseatPredictionController implements DragController.DragListener, private AllAppsStore mAllAppsStore; private AnimatorSet mIconRemoveAnimators; private boolean mUIUpdatePaused = false; + private boolean mRequiresCacheUpdate = false; private HotseatEduController mHotseatEduController; @@ -145,6 +148,7 @@ public class HotseatPredictionController implements DragController.DragListener, if (mHotseat.isAttachedToWindow()) { onViewAttachedToWindow(mHotseat); } + showCachedItems(); } /** @@ -294,6 +298,16 @@ public class HotseatPredictionController implements DragController.DragListener, mAppPredictor.requestPredictionUpdate(); } + private void showCachedItems() { + ArrayList componentKeys = getCachedComponentKeys(); + mComponentKeyMappers.clear(); + for (ComponentKey key : componentKeys) { + mComponentKeyMappers.add(new ComponentKeyMapper(key, mDynamicItemCache)); + } + updateDependencies(); + fillGapsWithPrediction(); + } + private Bundle getAppPredictionContextExtra() { Bundle bundle = new Bundle(); bundle.putParcelableArrayList(BUNDLE_KEY_HOTSEAT, @@ -320,6 +334,7 @@ public class HotseatPredictionController implements DragController.DragListener, private void setPredictedApps(List appTargets) { mComponentKeyMappers.clear(); StringBuilder predictionLog = new StringBuilder("predictedApps: [\n"); + ArrayList componentKeys = new ArrayList<>(); for (AppTarget appTarget : appTargets) { ComponentKey key; if (appTarget.getShortcutInfo() != null) { @@ -328,6 +343,7 @@ public class HotseatPredictionController implements DragController.DragListener, key = new ComponentKey(new ComponentName(appTarget.getPackageName(), appTarget.getClassName()), appTarget.getUser()); } + componentKeys.add(key); predictionLog.append(key.toString()); predictionLog.append(",rank:"); predictionLog.append(appTarget.getRank()); @@ -342,6 +358,35 @@ public class HotseatPredictionController implements DragController.DragListener, } else if (mHotseatEduController != null) { mHotseatEduController.setPredictedApps(mapToWorkspaceItemInfo(mComponentKeyMappers)); } + // should invalidate cache if AiAi sends empty list of AppTargets + if (appTargets.isEmpty()) { + mRequiresCacheUpdate = true; + } + cachePredictionComponentKeys(componentKeys); + } + + private void cachePredictionComponentKeys(ArrayList componentKeys) { + if (!mRequiresCacheUpdate) return; + StringBuilder builder = new StringBuilder(); + for (ComponentKey componentKey : componentKeys) { + builder.append(componentKey); + builder.append("\n"); + } + mLauncher.getDevicePrefs().edit().putString(PREDICTED_ITEMS_CACHE_KEY, + builder.toString()).apply(); + mRequiresCacheUpdate = false; + } + + private ArrayList getCachedComponentKeys() { + String cachedBlob = mLauncher.getDevicePrefs().getString(PREDICTED_ITEMS_CACHE_KEY, ""); + ArrayList results = new ArrayList<>(); + for (String line : cachedBlob.split("\n")) { + ComponentKey key = ComponentKey.fromString(line); + if (key != null) { + results.add(key); + } + } + return results; } private void updateDependencies() { @@ -367,6 +412,7 @@ public class HotseatPredictionController implements DragController.DragListener, icon.pin(workspaceItemInfo); AppTarget appTarget = getAppTargetFromItemInfo(workspaceItemInfo); notifyItemAction(appTarget, APP_LOCATION_HOTSEAT, AppTargetEvent.ACTION_PIN); + mRequiresCacheUpdate = true; } private List mapToWorkspaceItemInfo( @@ -533,6 +579,7 @@ public class HotseatPredictionController implements DragController.DragListener, } mDragObject = null; fillGapsWithPrediction(true, this::removeOutlineDrawings); + mRequiresCacheUpdate = true; } @Nullable