Merge "Implement hotseat prediction client" into ub-launcher3-master
This commit is contained in:
committed by
Android (Google) Code Review
commit
8e24097014
+144
-57
@@ -15,7 +15,15 @@
|
||||
*/
|
||||
package com.android.launcher3;
|
||||
|
||||
import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.app.prediction.AppPredictionContext;
|
||||
import android.app.prediction.AppPredictionManager;
|
||||
import android.app.prediction.AppPredictor;
|
||||
import android.app.prediction.AppTarget;
|
||||
import android.content.ComponentName;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
@@ -25,14 +33,16 @@ import androidx.annotation.Nullable;
|
||||
import com.android.launcher3.allapps.AllAppsStore;
|
||||
import com.android.launcher3.anim.AnimationSuccessListener;
|
||||
import com.android.launcher3.appprediction.ComponentKeyMapper;
|
||||
import com.android.launcher3.appprediction.PredictionUiStateManager;
|
||||
import com.android.launcher3.config.FeatureFlags;
|
||||
import com.android.launcher3.appprediction.DynamicItemCache;
|
||||
import com.android.launcher3.dragndrop.DragController;
|
||||
import com.android.launcher3.dragndrop.DragOptions;
|
||||
import com.android.launcher3.icons.IconCache;
|
||||
import com.android.launcher3.popup.PopupContainerWithArrow;
|
||||
import com.android.launcher3.popup.SystemShortcut;
|
||||
import com.android.launcher3.shortcuts.ShortcutKey;
|
||||
import com.android.launcher3.touch.ItemLongClickListener;
|
||||
import com.android.launcher3.uioverrides.QuickstepLauncher;
|
||||
import com.android.launcher3.util.ComponentKey;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
@@ -43,73 +53,86 @@ import java.util.List;
|
||||
* pinning of predicted apps and manages replacement of predicted apps with user drag.
|
||||
*/
|
||||
public class HotseatPredictionController implements DragController.DragListener,
|
||||
View.OnAttachStateChangeListener, SystemShortcut.Factory<QuickstepLauncher> {
|
||||
View.OnAttachStateChangeListener, SystemShortcut.Factory<QuickstepLauncher>,
|
||||
InvariantDeviceProfile.OnIDPChangeListener, AllAppsStore.OnUpdateListener,
|
||||
IconCache.ItemInfoUpdateReceiver {
|
||||
|
||||
private static final String TAG = "PredictiveHotseat";
|
||||
private static final boolean DEBUG = false;
|
||||
|
||||
private static final String PREDICTION_CLIENT = "hotseat";
|
||||
|
||||
private boolean mDragStarted = false;
|
||||
private PredictionUiStateManager mPredictionUiStateManager;
|
||||
private ArrayList<WorkspaceItemInfo> mPredictedApps = new ArrayList<>();
|
||||
private int mHotSeatItemsCount;
|
||||
|
||||
private Launcher mLauncher;
|
||||
private Hotseat mHotseat;
|
||||
|
||||
private List<ComponentKeyMapper> mComponentKeyMappers = new ArrayList<>();
|
||||
|
||||
private DynamicItemCache mDynamicItemCache;
|
||||
|
||||
private AppPredictor mAppPredictor;
|
||||
private AllAppsStore mAllAppsStore;
|
||||
|
||||
public HotseatPredictionController(Launcher launcher) {
|
||||
mLauncher = launcher;
|
||||
mPredictionUiStateManager = PredictionUiStateManager.INSTANCE.get(mLauncher);
|
||||
if (FeatureFlags.ENABLE_HYBRID_HOTSEAT.get()) {
|
||||
mLauncher.getHotseat().addOnAttachStateChangeListener(this);
|
||||
}
|
||||
mHotseat = launcher.getHotseat();
|
||||
mAllAppsStore = mLauncher.getAppsView().getAppsStore();
|
||||
mAllAppsStore.addUpdateListener(this);
|
||||
mDynamicItemCache = new DynamicItemCache(mLauncher, () -> fillGapsWithPrediction(false));
|
||||
mHotSeatItemsCount = mLauncher.getDeviceProfile().inv.numHotseatIcons;
|
||||
launcher.getDeviceProfile().inv.addOnChangeListener(this);
|
||||
mHotseat.addOnAttachStateChangeListener(this);
|
||||
createPredictor();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewAttachedToWindow(View view) {
|
||||
mPredictionUiStateManager.setHotseatPredictionController(this);
|
||||
mLauncher.getDragController().addDragListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewDetachedFromWindow(View view) {
|
||||
mPredictionUiStateManager.setHotseatPredictionController(null);
|
||||
mLauncher.getDragController().removeDragListener(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* sets the list of predicted items. gets called from PredictionUiStateManager
|
||||
*/
|
||||
public void setPredictedApps(List<ComponentKeyMapper> apps) {
|
||||
mPredictedApps.clear();
|
||||
mPredictedApps.addAll(mapToWorkspaceItemInfo(apps));
|
||||
fillGapsWithPrediction(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fills gaps in the hotseat with predictions
|
||||
*/
|
||||
public void fillGapsWithPrediction(boolean animate) {
|
||||
if (!FeatureFlags.ENABLE_HYBRID_HOTSEAT.get() || mDragStarted) {
|
||||
if (mDragStarted) {
|
||||
return;
|
||||
}
|
||||
removePredictedApps(false);
|
||||
List<WorkspaceItemInfo> predictedApps = mapToWorkspaceItemInfo(mComponentKeyMappers);
|
||||
int predictionIndex = 0;
|
||||
ArrayList<ItemInfo> itemInfos = new ArrayList<>();
|
||||
int cellCount = mLauncher.getWallpaperDeviceProfile().inv.numHotseatIcons;
|
||||
for (int rank = 0; rank < cellCount; rank++) {
|
||||
if (mPredictedApps.size() == predictionIndex) {
|
||||
break;
|
||||
}
|
||||
View child = mLauncher.getHotseat().getChildAt(
|
||||
mLauncher.getHotseat().getCellXFromOrder(rank),
|
||||
mLauncher.getHotseat().getCellYFromOrder(rank));
|
||||
if (child != null) {
|
||||
// we already have an item there. skip cell
|
||||
ArrayList<ItemInfo> newItemsToAdd = new ArrayList<>();
|
||||
for (int rank = 0; rank < mHotSeatItemsCount; rank++) {
|
||||
View child = mHotseat.getChildAt(
|
||||
mHotseat.getCellXFromOrder(rank),
|
||||
mHotseat.getCellYFromOrder(rank));
|
||||
|
||||
if (child != null && !isPredictedIcon(child)) {
|
||||
continue;
|
||||
}
|
||||
WorkspaceItemInfo predictedItem = mPredictedApps.get(predictionIndex++);
|
||||
if (predictedApps.size() <= predictionIndex) {
|
||||
// Remove predicted apps from the past
|
||||
if (isPredictedIcon(child)) {
|
||||
mHotseat.removeView(child);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
WorkspaceItemInfo predictedItem = predictedApps.get(predictionIndex++);
|
||||
if (isPredictedIcon(child)) {
|
||||
BubbleTextView icon = (BubbleTextView) child;
|
||||
icon.applyFromWorkspaceItem(predictedItem);
|
||||
} else {
|
||||
newItemsToAdd.add(predictedItem);
|
||||
}
|
||||
preparePredictionInfo(predictedItem, rank);
|
||||
itemInfos.add(predictedItem);
|
||||
}
|
||||
mLauncher.bindItems(itemInfos, animate);
|
||||
mLauncher.bindItems(newItemsToAdd, animate);
|
||||
for (BubbleTextView icon : getPredictedIcons()) {
|
||||
icon.verifyHighRes();
|
||||
icon.setOnLongClickListener((v) -> {
|
||||
@@ -119,29 +142,73 @@ public class HotseatPredictionController implements DragController.DragListener,
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregisters callbacks and frees resources
|
||||
*/
|
||||
public void destroy() {
|
||||
mAllAppsStore.removeUpdateListener(this);
|
||||
mLauncher.getDeviceProfile().inv.removeOnChangeListener(this);
|
||||
mHotseat.removeOnAttachStateChangeListener(this);
|
||||
if (mAppPredictor != null) {
|
||||
mAppPredictor.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
private void createPredictor() {
|
||||
AppPredictionManager apm = mLauncher.getSystemService(AppPredictionManager.class);
|
||||
if (apm == null) {
|
||||
return;
|
||||
}
|
||||
if (mAppPredictor != null) {
|
||||
mAppPredictor.destroy();
|
||||
}
|
||||
mAppPredictor = apm.createAppPredictionSession(
|
||||
new AppPredictionContext.Builder(mLauncher)
|
||||
.setUiSurface(PREDICTION_CLIENT)
|
||||
.setPredictedTargetCount(mHotSeatItemsCount)
|
||||
.build());
|
||||
mAppPredictor.registerPredictionUpdates(mLauncher.getMainExecutor(),
|
||||
this::setPredictedApps);
|
||||
mAppPredictor.requestPredictionUpdate();
|
||||
}
|
||||
|
||||
private void setPredictedApps(List<AppTarget> appTargets) {
|
||||
mComponentKeyMappers.clear();
|
||||
for (AppTarget appTarget : appTargets) {
|
||||
ComponentKey key;
|
||||
if (appTarget.getShortcutInfo() != null) {
|
||||
key = ShortcutKey.fromInfo(appTarget.getShortcutInfo());
|
||||
} else {
|
||||
key = new ComponentKey(new ComponentName(appTarget.getPackageName(),
|
||||
appTarget.getClassName()), appTarget.getUser());
|
||||
}
|
||||
mComponentKeyMappers.add(new ComponentKeyMapper(key, mDynamicItemCache));
|
||||
}
|
||||
updateDependencies();
|
||||
fillGapsWithPrediction(false);
|
||||
}
|
||||
|
||||
private void updateDependencies() {
|
||||
mDynamicItemCache.updateDependencies(mComponentKeyMappers, mAllAppsStore, this,
|
||||
mHotSeatItemsCount);
|
||||
}
|
||||
|
||||
private void pinPrediction(ItemInfo info) {
|
||||
BubbleTextView icon = (BubbleTextView) mLauncher.getHotseat().getChildAt(
|
||||
mLauncher.getHotseat().getCellXFromOrder(info.rank),
|
||||
mLauncher.getHotseat().getCellYFromOrder(info.rank));
|
||||
BubbleTextView icon = (BubbleTextView) mHotseat.getChildAt(
|
||||
mHotseat.getCellXFromOrder(info.rank),
|
||||
mHotseat.getCellYFromOrder(info.rank));
|
||||
if (icon == null) {
|
||||
return;
|
||||
}
|
||||
WorkspaceItemInfo workspaceItemInfo = new WorkspaceItemInfo((WorkspaceItemInfo) info);
|
||||
workspaceItemInfo.container = LauncherSettings.Favorites.CONTAINER_HOTSEAT;
|
||||
mLauncher.getModelWriter().addItemToDatabase(workspaceItemInfo,
|
||||
workspaceItemInfo.container, workspaceItemInfo.screenId,
|
||||
LauncherSettings.Favorites.CONTAINER_HOTSEAT, workspaceItemInfo.screenId,
|
||||
workspaceItemInfo.cellX, workspaceItemInfo.cellY);
|
||||
icon.animate().scaleY(0.8f).scaleX(0.8f).setListener(new AnimationSuccessListener() {
|
||||
@Override
|
||||
public void onAnimationSuccess(Animator animator) {
|
||||
icon.animate().scaleY(1).scaleX(1);
|
||||
}
|
||||
});
|
||||
ObjectAnimator.ofFloat(icon, SCALE_PROPERTY, 1, 0.8f, 1).start();
|
||||
icon.applyFromWorkspaceItem(workspaceItemInfo);
|
||||
icon.setOnLongClickListener(ItemLongClickListener.INSTANCE_WORKSPACE);
|
||||
}
|
||||
|
||||
|
||||
private List<WorkspaceItemInfo> mapToWorkspaceItemInfo(
|
||||
List<ComponentKeyMapper> components) {
|
||||
AllAppsStore allAppsStore = mLauncher.getAppsView().getAppsStore();
|
||||
@@ -163,7 +230,7 @@ public class HotseatPredictionController implements DragController.DragListener,
|
||||
}
|
||||
}
|
||||
// Stop at the number of hotseat items
|
||||
if (predictedApps.size() == mLauncher.getDeviceProfile().inv.numHotseatIcons) {
|
||||
if (predictedApps.size() == mHotSeatItemsCount) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -172,12 +239,10 @@ public class HotseatPredictionController implements DragController.DragListener,
|
||||
|
||||
private List<BubbleTextView> getPredictedIcons() {
|
||||
List<BubbleTextView> icons = new ArrayList<>();
|
||||
ViewGroup vg = mLauncher.getHotseat().getShortcutsAndWidgets();
|
||||
ViewGroup vg = mHotseat.getShortcutsAndWidgets();
|
||||
for (int i = 0; i < vg.getChildCount(); i++) {
|
||||
View child = vg.getChildAt(i);
|
||||
if (child instanceof BubbleTextView && child.getTag() instanceof WorkspaceItemInfo
|
||||
&& ((WorkspaceItemInfo) child.getTag()).container
|
||||
== LauncherSettings.Favorites.CONTAINER_HOTSEAT_PREDICTION) {
|
||||
if (isPredictedIcon(child)) {
|
||||
icons.add((BubbleTextView) child);
|
||||
}
|
||||
}
|
||||
@@ -191,13 +256,13 @@ public class HotseatPredictionController implements DragController.DragListener,
|
||||
@Override
|
||||
public void onAnimationSuccess(Animator animator) {
|
||||
if (icon.getParent() != null) {
|
||||
((ViewGroup) icon.getParent()).removeView(icon);
|
||||
mHotseat.removeView(icon);
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
if (icon.getParent() != null) {
|
||||
((ViewGroup) icon.getParent()).removeView(icon);
|
||||
mHotseat.removeView(icon);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -222,7 +287,6 @@ public class HotseatPredictionController implements DragController.DragListener,
|
||||
@Override
|
||||
public SystemShortcut<QuickstepLauncher> getShortcut(QuickstepLauncher activity,
|
||||
ItemInfo itemInfo) {
|
||||
if (!FeatureFlags.ENABLE_HYBRID_HOTSEAT.get()) return null;
|
||||
if (itemInfo.container != LauncherSettings.Favorites.CONTAINER_HOTSEAT_PREDICTION) {
|
||||
return null;
|
||||
}
|
||||
@@ -233,10 +297,27 @@ public class HotseatPredictionController implements DragController.DragListener,
|
||||
itemInfo.container = LauncherSettings.Favorites.CONTAINER_HOTSEAT_PREDICTION;
|
||||
itemInfo.rank = rank;
|
||||
itemInfo.cellX = rank;
|
||||
itemInfo.cellY = LauncherAppState.getIDP(mLauncher).numHotseatIcons - rank - 1;
|
||||
itemInfo.cellY = mHotSeatItemsCount - rank - 1;
|
||||
itemInfo.screenId = rank;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onIdpChanged(int changeFlags, InvariantDeviceProfile profile) {
|
||||
this.mHotSeatItemsCount = profile.numHotseatIcons;
|
||||
createPredictor();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAppsUpdated() {
|
||||
updateDependencies();
|
||||
fillGapsWithPrediction(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reapplyItemInfo(ItemInfoWithIcon info) {
|
||||
|
||||
}
|
||||
|
||||
private class PinPrediction extends SystemShortcut<QuickstepLauncher> {
|
||||
|
||||
private PinPrediction(QuickstepLauncher target, ItemInfo itemInfo) {
|
||||
@@ -250,4 +331,10 @@ public class HotseatPredictionController implements DragController.DragListener,
|
||||
pinPrediction(mItemInfo);
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isPredictedIcon(View view) {
|
||||
return view instanceof BubbleTextView && view.getTag() instanceof WorkspaceItemInfo
|
||||
&& ((WorkspaceItemInfo) view.getTag()).container
|
||||
== LauncherSettings.Favorites.CONTAINER_HOTSEAT_PREDICTION;
|
||||
}
|
||||
}
|
||||
|
||||
+36
@@ -18,6 +18,7 @@ package com.android.launcher3.appprediction;
|
||||
import static android.content.pm.PackageManager.MATCH_INSTANT;
|
||||
|
||||
import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
|
||||
import static com.android.quickstep.InstantAppResolverImpl.COMPONENT_CLASS_MARKER;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
@@ -37,8 +38,10 @@ import androidx.annotation.Nullable;
|
||||
import androidx.annotation.UiThread;
|
||||
import androidx.annotation.WorkerThread;
|
||||
|
||||
import com.android.launcher3.AppInfo;
|
||||
import com.android.launcher3.LauncherAppState;
|
||||
import com.android.launcher3.WorkspaceItemInfo;
|
||||
import com.android.launcher3.allapps.AllAppsStore;
|
||||
import com.android.launcher3.icons.IconCache;
|
||||
import com.android.launcher3.icons.LauncherIcons;
|
||||
import com.android.launcher3.shortcuts.DeepShortcutManager;
|
||||
@@ -72,6 +75,7 @@ public class DynamicItemCache {
|
||||
private final Handler mUiHandler;
|
||||
private final InstantAppResolver mInstantAppResolver;
|
||||
private final Runnable mOnUpdateCallback;
|
||||
private final IconCache mIconCache;
|
||||
|
||||
private final Map<ShortcutKey, WorkspaceItemInfo> mShortcuts;
|
||||
private final Map<String, InstantAppItemInfo> mInstantApps;
|
||||
@@ -82,6 +86,7 @@ public class DynamicItemCache {
|
||||
mUiHandler = new Handler(Looper.getMainLooper(), this::handleUiMessage);
|
||||
mInstantAppResolver = InstantAppResolver.newInstance(context);
|
||||
mOnUpdateCallback = onUpdateCallback;
|
||||
mIconCache = LauncherAppState.getInstance(mContext).getIconCache();
|
||||
|
||||
mShortcuts = new HashMap<>();
|
||||
mInstantApps = new HashMap<>();
|
||||
@@ -240,4 +245,35 @@ public class DynamicItemCache {
|
||||
public WorkspaceItemInfo getShortcutInfo(ShortcutKey key) {
|
||||
return mShortcuts.get(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* requests and caches icons for app targets
|
||||
*/
|
||||
public void updateDependencies(List<ComponentKeyMapper> componentKeyMappers,
|
||||
AllAppsStore appsStore, IconCache.ItemInfoUpdateReceiver callback, int itemCount) {
|
||||
List<String> instantAppsToLoad = new ArrayList<>();
|
||||
List<ShortcutKey> shortcutsToLoad = new ArrayList<>();
|
||||
int total = componentKeyMappers.size();
|
||||
for (int i = 0, count = 0; i < total && count < itemCount; i++) {
|
||||
ComponentKeyMapper mapper = componentKeyMappers.get(i);
|
||||
// Update instant apps
|
||||
if (COMPONENT_CLASS_MARKER.equals(mapper.getComponentClass())) {
|
||||
instantAppsToLoad.add(mapper.getPackage());
|
||||
count++;
|
||||
} else if (mapper.getComponentKey() instanceof ShortcutKey) {
|
||||
shortcutsToLoad.add((ShortcutKey) mapper.getComponentKey());
|
||||
count++;
|
||||
} else {
|
||||
// Reload high res icon
|
||||
AppInfo info = (AppInfo) mapper.getApp(appsStore);
|
||||
if (info != null) {
|
||||
if (info.usingLowResIcon()) {
|
||||
mIconCache.updateIconInBackground(callback, info);
|
||||
}
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
cacheItems(shortcutsToLoad, instantAppsToLoad);
|
||||
}
|
||||
}
|
||||
|
||||
+3
-41
@@ -1,4 +1,4 @@
|
||||
/**
|
||||
/*
|
||||
* Copyright (C) 2019 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@@ -18,15 +18,12 @@ package com.android.launcher3.appprediction;
|
||||
|
||||
import static com.android.launcher3.LauncherState.BACKGROUND_APP;
|
||||
import static com.android.launcher3.LauncherState.OVERVIEW;
|
||||
import static com.android.quickstep.InstantAppResolverImpl.COMPONENT_CLASS_MARKER;
|
||||
|
||||
import android.app.prediction.AppPredictor;
|
||||
import android.app.prediction.AppTarget;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
|
||||
import com.android.launcher3.AppInfo;
|
||||
import com.android.launcher3.HotseatPredictionController;
|
||||
import com.android.launcher3.InvariantDeviceProfile;
|
||||
import com.android.launcher3.InvariantDeviceProfile.OnIDPChangeListener;
|
||||
import com.android.launcher3.ItemInfoWithIcon;
|
||||
@@ -37,7 +34,6 @@ import com.android.launcher3.LauncherStateManager.StateListener;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.allapps.AllAppsContainerView;
|
||||
import com.android.launcher3.allapps.AllAppsStore.OnUpdateListener;
|
||||
import com.android.launcher3.icons.IconCache;
|
||||
import com.android.launcher3.icons.IconCache.ItemInfoUpdateReceiver;
|
||||
import com.android.launcher3.shortcuts.ShortcutKey;
|
||||
import com.android.launcher3.util.ComponentKey;
|
||||
@@ -90,8 +86,6 @@ public class PredictionUiStateManager implements StateListener, ItemInfoUpdateRe
|
||||
|
||||
private AllAppsContainerView mAppsView;
|
||||
|
||||
private HotseatPredictionController mHotseatPredictionController;
|
||||
|
||||
private PredictionState mPendingState;
|
||||
private PredictionState mCurrentState;
|
||||
|
||||
@@ -153,10 +147,6 @@ public class PredictionUiStateManager implements StateListener, ItemInfoUpdateRe
|
||||
updateDependencies(mCurrentState);
|
||||
}
|
||||
|
||||
public void setHotseatPredictionController(HotseatPredictionController controller) {
|
||||
mHotseatPredictionController = controller;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reapplyItemInfo(ItemInfoWithIcon info) { }
|
||||
|
||||
@@ -193,9 +183,6 @@ public class PredictionUiStateManager implements StateListener, ItemInfoUpdateRe
|
||||
mAppsView.getFloatingHeaderView().findFixedRowByType(PredictionRowView.class)
|
||||
.setPredictedApps(mCurrentState.apps);
|
||||
}
|
||||
if (mHotseatPredictionController != null) {
|
||||
mHotseatPredictionController.setPredictedApps(mCurrentState.apps);
|
||||
}
|
||||
}
|
||||
|
||||
private void updatePredictionStateAfterCallback() {
|
||||
@@ -260,33 +247,8 @@ public class PredictionUiStateManager implements StateListener, ItemInfoUpdateRe
|
||||
if (!state.isEnabled || mAppsView == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
IconCache iconCache = LauncherAppState.getInstance(mContext).getIconCache();
|
||||
List<String> instantAppsToLoad = new ArrayList<>();
|
||||
List<ShortcutKey> shortcutsToLoad = new ArrayList<>();
|
||||
int total = state.apps.size();
|
||||
for (int i = 0, count = 0; i < total && count < mMaxIconsPerRow; i++) {
|
||||
ComponentKeyMapper mapper = state.apps.get(i);
|
||||
// Update instant apps
|
||||
if (COMPONENT_CLASS_MARKER.equals(mapper.getComponentClass())) {
|
||||
instantAppsToLoad.add(mapper.getPackage());
|
||||
count++;
|
||||
} else if (mapper.getComponentKey() instanceof ShortcutKey) {
|
||||
shortcutsToLoad.add((ShortcutKey) mapper.getComponentKey());
|
||||
count++;
|
||||
} else {
|
||||
// Reload high res icon
|
||||
AppInfo info = (AppInfo) mapper.getApp(mAppsView.getAppsStore());
|
||||
if (info != null) {
|
||||
if (info.usingLowResIcon()) {
|
||||
// TODO: Update icon cache to support null callbacks.
|
||||
iconCache.updateIconInBackground(this, info);
|
||||
}
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
mDynamicItemCache.cacheItems(shortcutsToLoad, instantAppsToLoad);
|
||||
mDynamicItemCache.updateDependencies(state.apps, mAppsView.getAppsStore(), this,
|
||||
mMaxIconsPerRow);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+22
-5
@@ -1,4 +1,4 @@
|
||||
/**
|
||||
/*
|
||||
* Copyright (C) 2019 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@@ -31,6 +31,7 @@ import com.android.launcher3.HotseatPredictionController;
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.LauncherState;
|
||||
import com.android.launcher3.anim.AnimatorPlaybackController;
|
||||
import com.android.launcher3.config.FeatureFlags;
|
||||
import com.android.launcher3.graphics.RotationMode;
|
||||
import com.android.launcher3.popup.SystemShortcut;
|
||||
import com.android.launcher3.uioverrides.touchcontrollers.FlingAndHoldTouchController;
|
||||
@@ -137,7 +138,9 @@ public class QuickstepLauncher extends BaseQuickstepLauncher {
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
mHotseatPredictionController = new HotseatPredictionController(this);
|
||||
if (FeatureFlags.ENABLE_HYBRID_HOTSEAT.get()) {
|
||||
mHotseatPredictionController = new HotseatPredictionController(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -165,8 +168,12 @@ public class QuickstepLauncher extends BaseQuickstepLauncher {
|
||||
|
||||
@Override
|
||||
public Stream<SystemShortcut.Factory> getSupportedShortcuts() {
|
||||
return Stream.concat(super.getSupportedShortcuts(),
|
||||
Stream.of(mHotseatPredictionController));
|
||||
if (mHotseatPredictionController != null) {
|
||||
return Stream.concat(super.getSupportedShortcuts(),
|
||||
Stream.of(mHotseatPredictionController));
|
||||
} else {
|
||||
return super.getSupportedShortcuts();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -187,7 +194,17 @@ public class QuickstepLauncher extends BaseQuickstepLauncher {
|
||||
@Override
|
||||
public void finishBindingItems(int pageBoundFirst) {
|
||||
super.finishBindingItems(pageBoundFirst);
|
||||
mHotseatPredictionController.fillGapsWithPrediction(false);
|
||||
if (mHotseatPredictionController != null) {
|
||||
mHotseatPredictionController.fillGapsWithPrediction(false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
if (mHotseatPredictionController != null) {
|
||||
mHotseatPredictionController.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -496,7 +496,8 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
|
||||
// Text should be visible everywhere but the hotseat.
|
||||
Object tag = getParent() instanceof FolderIcon ? ((View) getParent()).getTag() : getTag();
|
||||
ItemInfo info = tag instanceof ItemInfo ? (ItemInfo) tag : null;
|
||||
return info == null || info.container != LauncherSettings.Favorites.CONTAINER_HOTSEAT;
|
||||
return info == null || (info.container != LauncherSettings.Favorites.CONTAINER_HOTSEAT
|
||||
&& info.container != LauncherSettings.Favorites.CONTAINER_HOTSEAT_PREDICTION);
|
||||
}
|
||||
|
||||
public void setTextVisibility(boolean visible) {
|
||||
|
||||
Reference in New Issue
Block a user