Merge "Improve Hybird hotseat cache support" into ub-launcher3-rvc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
870ec6a974
+32
-35
@@ -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() {
|
||||
@@ -390,41 +408,20 @@ public class HotseatPredictionController implements DragController.DragListener,
|
||||
predictionLog.append("]");
|
||||
if (Utilities.IS_DEBUG_DEVICE) FileLog.d(TAG, predictionLog.toString());
|
||||
updateDependencies();
|
||||
fillGapsWithPrediction();
|
||||
fillGapsWithPrediction();
|
||||
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
@@ -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();
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -92,6 +92,11 @@ public class BgDataModel {
|
||||
*/
|
||||
public final Map<ShortcutKey, MutableInt> pinnedShortcutCounts = new HashMap<>();
|
||||
|
||||
/**
|
||||
* List of all cached predicted items visible on home screen
|
||||
*/
|
||||
public final ArrayList<AppInfo> cachedPredictedItems = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* True if the launcher has permission to access deep shortcuts.
|
||||
*/
|
||||
@@ -366,5 +371,10 @@ public class BgDataModel {
|
||||
void bindDeepShortcutMap(HashMap<ComponentKey, Integer> deepShortcutMap);
|
||||
|
||||
void bindAllApplications(AppInfo[] apps);
|
||||
|
||||
/**
|
||||
* Binds predicted appInfos at at available prediction slots.
|
||||
*/
|
||||
void bindPredictedItems(List<AppInfo> appInfos, IntArray ranks);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -179,6 +179,7 @@ public class LoaderTask implements Runnable {
|
||||
try (LauncherModel.LoaderTransaction transaction = mApp.getModel().beginLoader(this)) {
|
||||
List<ShortcutInfo> allShortcuts = new ArrayList<>();
|
||||
loadWorkspace(allShortcuts);
|
||||
loadCachedPredictions();
|
||||
logger.addSplit("loadWorkspace");
|
||||
|
||||
verifyNotStopped();
|
||||
@@ -849,6 +850,23 @@ public class LoaderTask implements Runnable {
|
||||
}
|
||||
}
|
||||
|
||||
private List<AppInfo> loadCachedPredictions() {
|
||||
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) {
|
||||
l = mLauncherApps.getActivityList(key.componentName.getPackageName(), key.user);
|
||||
if (l.size() == 0) continue;
|
||||
boolean quietMode = mUserManager.isQuietModeEnabled(key.user);
|
||||
AppInfo info = new AppInfo(l.get(0), key.user, quietMode);
|
||||
mBgDataModel.cachedPredictedItems.add(info);
|
||||
mIconCache.getTitleAndIcon(info, false);
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
private List<LauncherActivityInfo> loadAllApps() {
|
||||
final List<UserHandle> profiles = mUserCache.getUserProfiles();
|
||||
List<LauncherActivityInfo> allActivityList = new ArrayList<>();
|
||||
@@ -880,6 +898,14 @@ public class LoaderTask implements Runnable {
|
||||
PackageInstallInfo.fromInstallingState(info));
|
||||
}
|
||||
}
|
||||
for (AppInfo item : mBgDataModel.cachedPredictedItems) {
|
||||
List<LauncherActivityInfo> l = mLauncherApps.getActivityList(
|
||||
item.componentName.getPackageName(), item.user);
|
||||
for (LauncherActivityInfo info : l) {
|
||||
boolean quietMode = mUserManager.isQuietModeEnabled(item.user);
|
||||
mBgAllAppsList.add(new AppInfo(info, item.user, quietMode), info);
|
||||
}
|
||||
}
|
||||
|
||||
mBgAllAppsList.getAndResetChangeFlag();
|
||||
return allActivityList;
|
||||
|
||||
@@ -19,11 +19,14 @@ import com.android.launcher3.InvariantDeviceProfile;
|
||||
import com.android.launcher3.LauncherSettings;
|
||||
import com.android.launcher3.config.FeatureFlags;
|
||||
import com.android.launcher3.model.data.ItemInfo;
|
||||
import com.android.launcher3.util.IntArray;
|
||||
import com.android.launcher3.util.IntSet;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
/**
|
||||
* Utils class for {@link com.android.launcher3.LauncherModel}.
|
||||
@@ -109,4 +112,17 @@ public class ModelUtils {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterates though current workspace items and returns available hotseat ranks for prediction.
|
||||
*/
|
||||
public static IntArray getMissingHotseatRanks(List<ItemInfo> items, int len) {
|
||||
IntSet seen = new IntSet();
|
||||
items.stream().filter(
|
||||
info -> info.container == LauncherSettings.Favorites.CONTAINER_HOTSEAT)
|
||||
.forEach(i -> seen.add(i.screenId));
|
||||
IntArray result = new IntArray(len);
|
||||
IntStream.range(0, len).filter(i -> !seen.contains(i)).forEach(result::add);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* 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.model;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.UserHandle;
|
||||
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.model.data.AppInfo;
|
||||
import com.android.launcher3.util.ComponentKey;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Model helper for app predictions in workspace
|
||||
*/
|
||||
public class PredictionModel {
|
||||
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;
|
||||
|
||||
public PredictionModel(Context context) {
|
||||
mContext = context;
|
||||
mDevicePrefs = Utilities.getDevicePrefs(mContext);
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats and stores a list of component key in device preferences.
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* parses and returns ComponentKeys saved by
|
||||
* {@link PredictionModel#cachePredictionComponentKeys(List)}
|
||||
*/
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
return mCachedComponentKeys;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
cachePredictionComponentKeys(getPredictionComponentKeys().stream()
|
||||
.filter(cn -> !(cn.user.equals(user) && cn.componentName.getPackageName().equals(
|
||||
pkgName))).collect(Collectors.toList()));
|
||||
}
|
||||
}
|
||||
@@ -195,6 +195,9 @@ public class SecondaryDisplayLauncher extends BaseDraggingActivity
|
||||
@Override
|
||||
public void bindItems(List<ItemInfo> shortcuts, boolean forceAnimateIcons) { }
|
||||
|
||||
@Override
|
||||
public void bindPredictedItems(List<AppInfo> appInfos, IntArray ranks) { }
|
||||
|
||||
@Override
|
||||
public void bindScreens(IntArray orderedScreenIds) { }
|
||||
|
||||
|
||||
Reference in New Issue
Block a user