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

Commit 870ec6a9 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Improve Hybird hotseat cache support" into ub-launcher3-rvc-dev

parents 0029fd77 385e9324
Loading
Loading
Loading
Loading
+32 −35
Original line number Diff line number Diff line
@@ -43,6 +43,7 @@ import com.android.launcher3.DropTarget;
import com.android.launcher3.Hotseat;
import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.LauncherSettings;
import com.android.launcher3.LauncherState;
import com.android.launcher3.R;
@@ -56,6 +57,7 @@ import com.android.launcher3.dragndrop.DragController;
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;
@@ -69,6 +71,7 @@ import com.android.launcher3.uioverrides.PredictedAppIcon;
import com.android.launcher3.uioverrides.QuickstepLauncher;
import com.android.launcher3.userevent.nano.LauncherLogProto;
import com.android.launcher3.util.ComponentKey;
import com.android.launcher3.util.IntArray;

import java.lang.ref.WeakReference;
import java.util.ArrayList;
@@ -93,8 +96,6 @@ 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";

@@ -115,11 +116,13 @@ public class HotseatPredictionController implements DragController.DragListener,

    private DynamicItemCache mDynamicItemCache;

    private final PredictionModel mPredictionModel;
    private AppPredictor mAppPredictor;
    private AllAppsStore mAllAppsStore;
    private AnimatorSet mIconRemoveAnimators;
    private boolean mUIUpdatePaused = false;
    private boolean mRequiresCacheUpdate = false;
    private boolean mRequiresCacheUpdate = true;
    private boolean mIsCacheEmpty;

    private HotseatEduController mHotseatEduController;

@@ -138,15 +141,16 @@ public class HotseatPredictionController implements DragController.DragListener,
        mLauncher = launcher;
        mHotseat = launcher.getHotseat();
        mAllAppsStore = mLauncher.getAppsView().getAppsStore();
        mPredictionModel = LauncherAppState.INSTANCE.get(launcher).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);
        }
        showCachedItems();
    }

    /**
@@ -185,6 +189,11 @@ public class HotseatPredictionController implements DragController.DragListener,
            return;
        }
        List<WorkspaceItemInfo> predictedApps = mapToWorkspaceItemInfo(mComponentKeyMappers);
        if (mComponentKeyMappers.isEmpty() != predictedApps.isEmpty()) {
            // Safely ignore update as AppsList is not ready yet. This will called again once
            // apps are ready (HotseatPredictionController#onAppsUpdated)
            return;
        }
        int predictionIndex = 0;
        ArrayList<WorkspaceItemInfo> newItems = new ArrayList<>();
        // make sure predicted icon removal and filling predictions don't step on each other
@@ -305,14 +314,23 @@ public class HotseatPredictionController implements DragController.DragListener,
        mAppPredictor.requestPredictionUpdate();
    }

    private void showCachedItems() {
        ArrayList<ComponentKey> componentKeys = getCachedComponentKeys();
    /**
     * Create WorkspaceItemInfo objects and binds PredictedAppIcon views for cached predicted items.
     */
    public void showCachedItems(List<AppInfo> apps, IntArray ranks) {
        int count = Math.min(ranks.size(), apps.size());
        List<WorkspaceItemInfo> items = new ArrayList<>(count);
        for (int i = 0; i < count; i++) {
            WorkspaceItemInfo item = new WorkspaceItemInfo(apps.get(i));
            preparePredictionInfo(item, ranks.get(i));
            items.add(item);
        }
        mComponentKeyMappers.clear();
        for (ComponentKey key : componentKeys) {
        for (ComponentKey key : mPredictionModel.getPredictionComponentKeys()) {
            mComponentKeyMappers.add(new ComponentKeyMapper(key, mDynamicItemCache));
        }
        updateDependencies();
        fillGapsWithPrediction();
        bindItems(items, false, null);
    }

    private Bundle getAppPredictionContextExtra() {
@@ -394,37 +412,16 @@ public class HotseatPredictionController implements DragController.DragListener,
        if (!isEduSeen() && mHotseatEduController != null) {
            mHotseatEduController.setPredictedApps(mapToWorkspaceItemInfo(mComponentKeyMappers));
        }
        // should invalidate cache if AiAi sends empty list of AppTargets
        if (appTargets.isEmpty()) {
            mRequiresCacheUpdate = true;
        }
        cachePredictionComponentKeys(componentKeys);
        cachePredictionComponentKeysIfNecessary(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();
    private void cachePredictionComponentKeysIfNecessary(ArrayList<ComponentKey> componentKeys) {
        if (!mRequiresCacheUpdate && componentKeys.isEmpty() == mIsCacheEmpty) return;
        mPredictionModel.cachePredictionComponentKeys(componentKeys);
        mIsCacheEmpty = componentKeys.isEmpty();
        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() {
        mDynamicItemCache.updateDependencies(mComponentKeyMappers, mAllAppsStore, this,
                mHotSeatItemsCount);
+11 −0
Original line number Diff line number Diff line
@@ -44,6 +44,7 @@ import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.folder.Folder;
import com.android.launcher3.hybridhotseat.HotseatPredictionController;
import com.android.launcher3.model.data.AppInfo;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.model.data.WorkspaceItemInfo;
import com.android.launcher3.popup.SystemShortcut;
@@ -58,6 +59,7 @@ import com.android.launcher3.uioverrides.touchcontrollers.QuickSwitchTouchContro
import com.android.launcher3.uioverrides.touchcontrollers.StatusBarTouchController;
import com.android.launcher3.uioverrides.touchcontrollers.TaskViewTouchController;
import com.android.launcher3.uioverrides.touchcontrollers.TransposedQuickSwitchTouchController;
import com.android.launcher3.util.IntArray;
import com.android.launcher3.util.TouchController;
import com.android.launcher3.util.UiThreadHelper;
import com.android.launcher3.util.UiThreadHelper.AsyncCommand;
@@ -70,6 +72,7 @@ import com.android.quickstep.views.TaskView;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;

public class QuickstepLauncher extends BaseQuickstepLauncher {
@@ -177,6 +180,14 @@ public class QuickstepLauncher extends BaseQuickstepLauncher {
        }
    }

    @Override
    public void bindPredictedItems(List<AppInfo> appInfos, IntArray ranks) {
        super.bindPredictedItems(appInfos, ranks);
        if (mHotseatPredictionController != null) {
            mHotseatPredictionController.showCachedItems(appInfos, ranks);
        }
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
+3 −0
Original line number Diff line number Diff line
@@ -2225,6 +2225,9 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns,
        workspace.requestLayout();
    }

    @Override
    public void bindPredictedItems(List<AppInfo> appInfos, IntArray ranks) { }

    /**
     * Add the views for a widget to the workspace.
     */
+7 −0
Original line number Diff line number Diff line
@@ -33,6 +33,7 @@ import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.icons.IconCache;
import com.android.launcher3.icons.IconProvider;
import com.android.launcher3.icons.LauncherIcons;
import com.android.launcher3.model.PredictionModel;
import com.android.launcher3.notification.NotificationListener;
import com.android.launcher3.pm.InstallSessionHelper;
import com.android.launcher3.pm.InstallSessionTracker;
@@ -57,6 +58,7 @@ public class LauncherAppState {
    private final IconCache mIconCache;
    private final WidgetPreviewLoader mWidgetCache;
    private final InvariantDeviceProfile mInvariantDeviceProfile;
    private final PredictionModel mPredictionModel;

    private SecureSettingsObserver mNotificationDotsObserver;
    private InstallSessionTracker mInstallSessionTracker;
@@ -127,6 +129,7 @@ public class LauncherAppState {
        mIconCache = new IconCache(mContext, mInvariantDeviceProfile, iconCacheFileName);
        mWidgetCache = new WidgetPreviewLoader(mContext, mIconCache);
        mModel = new LauncherModel(this, mIconCache, AppFilter.newInstance(mContext));
        mPredictionModel = new PredictionModel(mContext);
    }

    protected void onNotificationSettingsChanged(boolean areNotificationDotsEnabled) {
@@ -182,6 +185,10 @@ public class LauncherAppState {
        return mModel;
    }

    public PredictionModel getPredictionModel() {
        return mPredictionModel;
    }

    public WidgetPreviewLoader getWidgetCache() {
        return mWidgetCache;
    }
+10 −0
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package com.android.launcher3.model;

import static com.android.launcher3.model.ModelUtils.filterCurrentWorkspaceItems;
import static com.android.launcher3.model.ModelUtils.getMissingHotseatRanks;
import static com.android.launcher3.model.ModelUtils.sortWorkspaceItemsSpatially;

import android.util.Log;
@@ -196,6 +197,10 @@ public abstract class BaseLoaderResults {
            // Load items on the current page.
            bindWorkspaceItems(currentWorkspaceItems, mainExecutor);
            bindAppWidgets(currentAppWidgets, mainExecutor);

            // Locate available spots for prediction using currentWorkspaceItems
            IntArray gaps = getMissingHotseatRanks(currentWorkspaceItems, idp.numHotseatIcons);
            bindPredictedItems(gaps, mainExecutor);
            // In case of validFirstPage, only bind the first screen, and defer binding the
            // remaining screens after first onDraw (and an optional the fade animation whichever
            // happens later).
@@ -247,6 +252,11 @@ public abstract class BaseLoaderResults {
            }
        }

        private void bindPredictedItems(IntArray ranks, final Executor executor) {
            executeCallbacksTask(
                    c -> c.bindPredictedItems(mBgDataModel.cachedPredictedItems, ranks), executor);
        }

        protected void executeCallbacksTask(CallbackTask task, Executor executor) {
            executor.execute(() -> {
                if (mMyBindingId != mBgDataModel.lastBindId) {
Loading