Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 87a4d89e authored by Samuel Fufa's avatar Samuel Fufa
Browse files

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
parent 8f40d00a
Loading
Loading
Loading
Loading
+2 −4
Original line number Diff line number Diff line
@@ -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;
    }
}
+3 −2
Original line number Diff line number Diff line
@@ -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<ShortcutKey, WorkspaceItemInfo> mShortcuts;
    private final Map<ComponentKey, WorkspaceItemInfo> mShortcuts;
    private final Map<String, InstantAppItemInfo> 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);
    }

+47 −0
Original line number Diff line number Diff line
@@ -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<ComponentKey> 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<AppTarget> appTargets) {
        mComponentKeyMappers.clear();
        StringBuilder predictionLog = new StringBuilder("predictedApps: [\n");
        ArrayList<ComponentKey> 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<ComponentKey> 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<ComponentKey> getCachedComponentKeys() {
        String cachedBlob = mLauncher.getDevicePrefs().getString(PREDICTED_ITEMS_CACHE_KEY, "");
        ArrayList<ComponentKey> 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<WorkspaceItemInfo> mapToWorkspaceItemInfo(
@@ -533,6 +579,7 @@ public class HotseatPredictionController implements DragController.DragListener,
        }
        mDragObject = null;
        fillGapsWithPrediction(true, this::removeOutlineDrawings);
        mRequiresCacheUpdate = true;
    }

    @Nullable