Binding Taskbar directly from Launcher model am: 711c596c86

Original change: https://googleplex-android-review.googlesource.com/c/platform/packages/apps/Launcher3/+/15082875

Change-Id: I3c0247dc339993ecb9d6c740a064231a06857c22
This commit is contained in:
Sunny Goyal
2021-07-15 22:25:28 +00:00
committed by Automerger Merge Worker
26 changed files with 427 additions and 242 deletions

View File

@@ -262,10 +262,6 @@ public class HotseatPredictionController implements DragController.DragListener,
} else {
removeOutlineDrawings();
}
if (mLauncher.getTaskbarUIController() != null) {
mLauncher.getTaskbarUIController().onHotseatUpdated();
}
}
private void removeOutlineDrawings() {

View File

@@ -48,7 +48,6 @@ public class LauncherTaskbarUIController extends TaskbarUIController {
private final BaseQuickstepLauncher mLauncher;
private final TaskbarStateHandler mTaskbarStateHandler;
private final TaskbarHotseatController mHotseatController;
private final TaskbarActivityContext mContext;
private final TaskbarDragLayer mTaskbarDragLayer;
@@ -77,8 +76,6 @@ public class LauncherTaskbarUIController extends TaskbarUIController {
mLauncher = launcher;
mTaskbarStateHandler = mLauncher.getTaskbarStateHandler();
mHotseatController = new TaskbarHotseatController(
mLauncher, mTaskbarView::updateHotseatItems);
}
@Override
@@ -91,7 +88,6 @@ public class LauncherTaskbarUIController extends TaskbarUIController {
MultiValueAlpha taskbarIconAlpha = mControllers.taskbarViewController.getTaskbarIconAlpha();
mIconAlphaForHome = taskbarIconAlpha.getProperty(ALPHA_INDEX_HOME);
mHotseatController.init();
mLauncher.setTaskbarUIController(this);
mKeyguardController = taskbarControllers.taskbarKeyguardController;
@@ -106,7 +102,6 @@ public class LauncherTaskbarUIController extends TaskbarUIController {
mIconAlignmentForResumedState.finishAnimation();
mIconAlignmentForGestureState.finishAnimation();
mHotseatController.cleanup();
mLauncher.getHotseat().setIconsAlpha(1f);
mLauncher.setTaskbarUIController(null);
}
@@ -243,13 +238,6 @@ public class LauncherTaskbarUIController extends TaskbarUIController {
return mControllers.taskbarStashController.onLongPressToUnstashTaskbar();
}
/**
* Should be called when one or more items in the Hotseat have changed.
*/
public void onHotseatUpdated() {
mHotseatController.onHotseatUpdated();
}
/**
* @param ev MotionEvent in screen coordinates.
* @return Whether any Taskbar item could handle the given MotionEvent if given the chance.

View File

@@ -85,5 +85,6 @@ public class TaskbarControllers {
rotationButtonController.onDestroy();
taskbarDragLayerController.onDestroy();
taskbarKeyguardController.onDestroy();
taskbarViewController.onDestroy();
}
}

View File

@@ -1,91 +0,0 @@
/*
* Copyright (C) 2021 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.taskbar;
import android.view.View;
import com.android.launcher3.BaseQuickstepLauncher;
import com.android.launcher3.CellLayout;
import com.android.launcher3.DropTarget;
import com.android.launcher3.Hotseat;
import com.android.launcher3.ShortcutAndWidgetContainer;
import com.android.launcher3.dragndrop.DragController;
import com.android.launcher3.dragndrop.DragOptions;
import com.android.launcher3.model.data.ItemInfo;
import java.util.function.Consumer;
/**
* Works with TaskbarController to update the TaskbarView's Hotseat items.
*/
public class TaskbarHotseatController {
private final BaseQuickstepLauncher mLauncher;
private final Hotseat mHotseat;
private final Consumer<ItemInfo[]> mTaskbarCallbacks;
private final int mNumHotseatIcons;
private final DragController.DragListener mDragListener = new DragController.DragListener() {
@Override
public void onDragStart(DropTarget.DragObject dragObject, DragOptions options) { }
@Override
public void onDragEnd() {
onHotseatUpdated();
}
};
public TaskbarHotseatController(
BaseQuickstepLauncher launcher, Consumer<ItemInfo[]> taskbarCallbacks) {
mLauncher = launcher;
mHotseat = mLauncher.getHotseat();
mTaskbarCallbacks = taskbarCallbacks;
mNumHotseatIcons = mLauncher.getDeviceProfile().numShownHotseatIcons;
}
protected void init() {
mLauncher.getDragController().addDragListener(mDragListener);
onHotseatUpdated();
}
protected void cleanup() {
mLauncher.getDragController().removeDragListener(mDragListener);
}
/**
* Called when any Hotseat item changes, and reports the new list of items to TaskbarController.
*/
protected void onHotseatUpdated() {
ShortcutAndWidgetContainer shortcutsAndWidgets = mHotseat.getShortcutsAndWidgets();
ItemInfo[] hotseatItemInfos = new ItemInfo[mNumHotseatIcons];
for (int i = 0; i < shortcutsAndWidgets.getChildCount(); i++) {
View child = shortcutsAndWidgets.getChildAt(i);
Object tag = shortcutsAndWidgets.getChildAt(i).getTag();
if (tag instanceof ItemInfo) {
ItemInfo itemInfo = (ItemInfo) tag;
CellLayout.LayoutParams lp = (CellLayout.LayoutParams) child.getLayoutParams();
// Since the hotseat might be laid out vertically or horizontally, use whichever
// index is higher.
int index = Math.max(lp.cellX, lp.cellY);
if (0 <= index && index < hotseatItemInfos.length) {
hotseatItemInfos[index] = itemInfo;
}
}
}
mTaskbarCallbacks.accept(hotseatItemInfos);
}
}

View File

@@ -0,0 +1,174 @@
/*
* Copyright (C) 2021 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.taskbar;
import android.util.SparseArray;
import android.view.View;
import com.android.launcher3.LauncherSettings.Favorites;
import com.android.launcher3.model.BgDataModel;
import com.android.launcher3.model.BgDataModel.FixedContainerItems;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.model.data.WorkspaceItemInfo;
import com.android.launcher3.util.IntArray;
import com.android.launcher3.util.IntSet;
import com.android.launcher3.util.ItemInfoMatcher;
import com.android.launcher3.util.LauncherBindableItemsContainer;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
/**
* Launcher model Callbacks for rendering taskbar.
*/
public class TaskbarModelCallbacks implements
BgDataModel.Callbacks, LauncherBindableItemsContainer {
private final SparseArray<ItemInfo> mHotseatItems = new SparseArray<>();
private List<ItemInfo> mPredictedItems = Collections.emptyList();
private final TaskbarActivityContext mContext;
private final TaskbarView mContainer;
private boolean mBindInProgress = false;
public TaskbarModelCallbacks(
TaskbarActivityContext context, TaskbarView container) {
mContext = context;
mContainer = container;
}
@Override
public void startBinding() {
mBindInProgress = true;
mHotseatItems.clear();
mPredictedItems = Collections.emptyList();
}
@Override
public void finishBindingItems(IntSet pagesBoundFirst) {
mBindInProgress = false;
commitItemsToUI();
}
@Override
public void bindAppsAdded(IntArray newScreens, ArrayList<ItemInfo> addNotAnimated,
ArrayList<ItemInfo> addAnimated) {
boolean add1 = handleItemsAdded(addNotAnimated);
boolean add2 = handleItemsAdded(addAnimated);
if (add1 || add2) {
commitItemsToUI();
}
}
@Override
public void bindItems(List<ItemInfo> shortcuts, boolean forceAnimateIcons) {
if (handleItemsAdded(shortcuts)) {
commitItemsToUI();
}
}
private boolean handleItemsAdded(List<ItemInfo> items) {
boolean modified = false;
for (ItemInfo item : items) {
if (item.container == Favorites.CONTAINER_HOTSEAT) {
mHotseatItems.put(item.screenId, item);
modified = true;
}
}
return modified;
}
@Override
public void bindWorkspaceItemsChanged(List<WorkspaceItemInfo> updated) {
updateWorkspaceItems(updated, mContext);
}
@Override
public void bindRestoreItemsChange(HashSet<ItemInfo> updates) {
updateRestoreItems(updates, mContext);
}
@Override
public void mapOverItems(ItemOperator op) {
final int itemCount = mContainer.getChildCount();
for (int itemIdx = 0; itemIdx < itemCount; itemIdx++) {
View item = mContainer.getChildAt(itemIdx);
if (op.evaluate((ItemInfo) item.getTag(), item)) {
return;
}
}
}
@Override
public void bindWorkspaceComponentsRemoved(ItemInfoMatcher matcher) {
if (handleItemsRemoved(matcher)) {
commitItemsToUI();
}
}
private boolean handleItemsRemoved(ItemInfoMatcher matcher) {
boolean modified = false;
for (int i = mHotseatItems.size() - 1; i >= 0; i--) {
if (matcher.matchesInfo(mHotseatItems.valueAt(i))) {
modified = true;
mHotseatItems.removeAt(i);
}
}
return modified;
}
@Override
public void bindItemsModified(List<ItemInfo> items) {
boolean removed = handleItemsRemoved(ItemInfoMatcher.ofItems(items));
boolean added = handleItemsAdded(items);
if (removed || added) {
commitItemsToUI();
}
}
@Override
public void bindExtraContainerItems(FixedContainerItems item) {
if (item.containerId == Favorites.CONTAINER_HOTSEAT_PREDICTION) {
mPredictedItems = item.items;
commitItemsToUI();
}
}
private void commitItemsToUI() {
if (mBindInProgress) {
return;
}
ItemInfo[] hotseatItemInfos =
new ItemInfo[mContext.getDeviceProfile().numShownHotseatIcons];
int predictionSize = mPredictedItems.size();
int predictionNextIndex = 0;
for (int i = 0; i < hotseatItemInfos.length; i++) {
hotseatItemInfos[i] = mHotseatItems.get(i);
if (hotseatItemInfos[i] == null && predictionNextIndex < predictionSize) {
hotseatItemInfos[i] = mPredictedItems.get(predictionNextIndex);
hotseatItemInfos[i].screenId = i;
predictionNextIndex++;
}
}
mContainer.updateHotseatItems(hotseatItemInfos);
}
}

View File

@@ -24,6 +24,7 @@ import android.graphics.Rect;
import android.view.View;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.anim.PendingAnimation;
import com.android.launcher3.model.data.ItemInfo;
@@ -50,6 +51,8 @@ public class TaskbarViewController {
private final AnimatedFloat mTaskbarIconTranslationYForStash = new AnimatedFloat(
this::updateTranslationY);
private final TaskbarModelCallbacks mModelCallbacks;
// Initialized in init.
private TaskbarControllers mControllers;
@@ -63,6 +66,7 @@ public class TaskbarViewController {
mTaskbarView = taskbarView;
mTaskbarIconAlpha = new MultiValueAlpha(mTaskbarView, 4);
mTaskbarIconAlpha.setUpdateVisibility(true);
mModelCallbacks = new TaskbarModelCallbacks(activity, mTaskbarView);
}
public void init(TaskbarControllers controllers) {
@@ -71,6 +75,11 @@ public class TaskbarViewController {
mTaskbarView.getLayoutParams().height = mActivity.getDeviceProfile().taskbarSize;
mTaskbarIconScaleForStash.updateValue(1f);
LauncherAppState.getInstance(mActivity).getModel().addCallbacksAndLoad(mModelCallbacks);
}
public void onDestroy() {
LauncherAppState.getInstance(mActivity).getModel().removeCallbacks(mModelCallbacks);
}
public boolean areIconsVisible() {

View File

@@ -17,7 +17,6 @@ package com.android.launcher3.uioverrides;
import static android.view.accessibility.AccessibilityEvent.TYPE_VIEW_FOCUSED;
import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_HOTSEAT;
import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_APPLICATION;
import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT;
import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT;
@@ -55,7 +54,6 @@ import com.android.launcher3.logging.InstanceId;
import com.android.launcher3.logging.StatsLogManager.StatsLogger;
import com.android.launcher3.model.BgDataModel.FixedContainerItems;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.model.data.WorkspaceItemInfo;
import com.android.launcher3.popup.SystemShortcut;
import com.android.launcher3.statemanager.StateManager.AtomicAnimationFactory;
import com.android.launcher3.uioverrides.states.QuickstepAtomicAnimationFactory;
@@ -84,7 +82,6 @@ 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.Objects;
import java.util.stream.Stream;
@@ -230,15 +227,6 @@ public class QuickstepLauncher extends BaseQuickstepLauncher {
}
}
@Override
public void bindWorkspaceItemsChanged(List<WorkspaceItemInfo> updated) {
super.bindWorkspaceItemsChanged(updated);
if (getTaskbarUIController() != null && updated.stream()
.filter(w -> w.container == CONTAINER_HOTSEAT).findFirst().isPresent()) {
getTaskbarUIController().onHotseatUpdated();
}
}
@Override
public void onDestroy() {
super.onDestroy();

View File

@@ -2147,7 +2147,7 @@ public class CellLayout extends ViewGroup {
mShakeAnimators.clear();
}
private void commitTempPlacement() {
private void commitTempPlacement(View dragView) {
mTmpOccupied.copyTo(mOccupied);
int screenId = Launcher.cast(mActivity).getWorkspace().getIdForScreen(this);
@@ -2165,7 +2165,7 @@ public class CellLayout extends ViewGroup {
ItemInfo info = (ItemInfo) child.getTag();
// We do a null check here because the item info can be null in the case of the
// AllApps button in the hotseat.
if (info != null) {
if (info != null && child != dragView) {
final boolean requiresDbUpdate = (info.cellX != lp.tmpCellX
|| info.cellY != lp.tmpCellY || info.spanX != lp.cellHSpan
|| info.spanY != lp.cellVSpan);
@@ -2327,7 +2327,7 @@ public class CellLayout extends ViewGroup {
animateItemsToSolution(swapSolution, dragView, commit);
if (commit) {
commitTempPlacement();
commitTempPlacement(null);
completeAndClearReorderPreviewAnimations();
setItemPlacementDirty(false);
} else {
@@ -2421,7 +2421,8 @@ public class CellLayout extends ViewGroup {
if (!DESTRUCTIVE_REORDER &&
(mode == MODE_ON_DROP || mode == MODE_ON_DROP_EXTERNAL)) {
commitTempPlacement();
// Since the temp solution didn't update dragView, don't commit it either
commitTempPlacement(dragView);
completeAndClearReorderPreviewAnimations();
setItemPlacementDirty(false);
} else {
@@ -2877,7 +2878,7 @@ public class CellLayout extends ViewGroup {
directionVector, null, false, configuration).isSolution) {
if (commitConfig) {
copySolutionToTempState(configuration, null);
commitTempPlacement();
commitTempPlacement(null);
// undo marking cells occupied since there is actually nothing being placed yet.
mOccupied.markCells(0, mCountY - 1, mCountX, 1, false);
}

View File

@@ -48,7 +48,6 @@ import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCH
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_WIDGET_RECONFIGURED;
import static com.android.launcher3.model.ItemInstallQueue.FLAG_ACTIVITY_PAUSED;
import static com.android.launcher3.model.ItemInstallQueue.FLAG_DRAG_AND_DROP;
import static com.android.launcher3.model.ItemInstallQueue.FLAG_LOADER_RUNNING;
import static com.android.launcher3.popup.SystemShortcut.APP_INFO;
import static com.android.launcher3.popup.SystemShortcut.INSTALL;
import static com.android.launcher3.popup.SystemShortcut.WIDGETS;
@@ -596,7 +595,7 @@ public class Launcher extends StatefulActivity<LauncherState> implements Launche
}
onDeviceProfileInitiated();
mModelWriter = mModel.getWriter(getDeviceProfile().isVerticalBarLayout(), true);
mModelWriter = mModel.getWriter(getDeviceProfile().isVerticalBarLayout(), true, this);
}
public RotationHelper getRotationHelper() {
@@ -2598,9 +2597,6 @@ public class Launcher extends StatefulActivity<LauncherState> implements Launche
mPendingActivityResult = null;
}
ItemInstallQueue.INSTANCE.get(this)
.resumeModelPush(FLAG_LOADER_RUNNING);
int currentPage = pagesBoundFirst != null && !pagesBoundFirst.isEmpty()
? pagesBoundFirst.getArray().get(0) : PagedView.INVALID_PAGE;
// When undoing the removal of the last item on a page, return to that page.
@@ -2677,7 +2673,7 @@ public class Launcher extends StatefulActivity<LauncherState> implements Launche
@Override
public void bindWorkspaceItemsChanged(List<WorkspaceItemInfo> updated) {
if (!updated.isEmpty()) {
mWorkspace.updateShortcuts(updated);
mWorkspace.updateWorkspaceItems(updated, this);
PopupContainerWithArrow.dismissInvalidPopup(this);
}
}
@@ -2689,7 +2685,7 @@ public class Launcher extends StatefulActivity<LauncherState> implements Launche
*/
@Override
public void bindRestoreItemsChange(HashSet<ItemInfo> updates) {
mWorkspace.updateRestoreItems(updates);
mWorkspace.updateRestoreItems(updates, this);
}
/**

View File

@@ -144,9 +144,10 @@ public class LauncherModel extends LauncherApps.Callback implements InstallSessi
enqueueModelUpdateTask(new AddWorkspaceItemsTask(itemList));
}
public ModelWriter getWriter(boolean hasVerticalHotseat, boolean verifyChanges) {
public ModelWriter getWriter(boolean hasVerticalHotseat, boolean verifyChanges,
@Nullable Callbacks owner) {
return new ModelWriter(mApp.getContext(), this, mBgDataModel,
hasVerticalHotseat, verifyChanges);
hasVerticalHotseat, verifyChanges, owner);
}
@Override
@@ -329,7 +330,7 @@ public class LauncherModel extends LauncherApps.Callback implements InstallSessi
public boolean addCallbacksAndLoad(Callbacks callbacks) {
synchronized (mLock) {
addCallbacks(callbacks);
return startLoader();
return startLoader(new Callbacks[] { callbacks });
}
}
@@ -349,26 +350,32 @@ public class LauncherModel extends LauncherApps.Callback implements InstallSessi
* @return true if the page could be bound synchronously.
*/
public boolean startLoader() {
return startLoader(new Callbacks[0]);
}
private boolean startLoader(Callbacks[] newCallbacks) {
// Enable queue before starting loader. It will get disabled in Launcher#finishBindingItems
ItemInstallQueue.INSTANCE.get(mApp.getContext())
.pauseModelPush(ItemInstallQueue.FLAG_LOADER_RUNNING);
synchronized (mLock) {
// Don't bother to start the thread if we know it's not going to do anything
final Callbacks[] callbacksList = getCallbacks();
// If there is already one running, tell it to stop.
boolean wasRunning = stopLoader();
boolean bindDirectly = mModelLoaded && !mIsLoaderTaskRunning;
boolean bindAllCallbacks = wasRunning || !bindDirectly || newCallbacks.length == 0;
final Callbacks[] callbacksList = bindAllCallbacks ? getCallbacks() : newCallbacks;
if (callbacksList.length > 0) {
// Clear any pending bind-runnables from the synchronized load process.
for (Callbacks cb : callbacksList) {
MAIN_EXECUTOR.execute(cb::clearPendingBinds);
}
// If there is already one running, tell it to stop.
stopLoader();
LoaderResults loaderResults = new LoaderResults(
mApp, mBgDataModel, mBgAllAppsList, callbacksList);
if (mModelLoaded && !mIsLoaderTaskRunning) {
if (bindDirectly) {
// Divide the set of loaded items into those that we are binding synchronously,
// and everything else that is to be bound normally (asynchronously).
loaderResults.bindWorkspace();
loaderResults.bindWorkspace(bindAllCallbacks);
// For now, continue posting the binding of AllApps as there are other
// issues that arise from that.
loaderResults.bindAllApps();
@@ -387,7 +394,7 @@ public class LauncherModel extends LauncherApps.Callback implements InstallSessi
* If there is already a loader task running, tell it to stop.
* @return true if an existing loader was stopped.
*/
public boolean stopLoader() {
private boolean stopLoader() {
synchronized (mLock) {
LoaderTask oldTask = mLoaderTask;
mLoaderTask = null;

View File

@@ -83,7 +83,6 @@ import com.android.launcher3.folder.Folder;
import com.android.launcher3.folder.FolderIcon;
import com.android.launcher3.folder.PreviewBackground;
import com.android.launcher3.graphics.DragPreviewProvider;
import com.android.launcher3.graphics.PreloadIconDrawable;
import com.android.launcher3.icons.BitmapRenderer;
import com.android.launcher3.icons.FastBitmapDrawable;
import com.android.launcher3.logger.LauncherAtom;
@@ -105,6 +104,7 @@ import com.android.launcher3.util.Executors;
import com.android.launcher3.util.IntArray;
import com.android.launcher3.util.IntSparseArrayMap;
import com.android.launcher3.util.ItemInfoMatcher;
import com.android.launcher3.util.LauncherBindableItemsContainer;
import com.android.launcher3.util.OverlayEdgeEffect;
import com.android.launcher3.util.PackageUserKey;
import com.android.launcher3.util.RunnableList;
@@ -123,7 +123,6 @@ import com.android.systemui.plugins.shared.LauncherOverlayManager.LauncherOverla
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Collectors;
@@ -136,7 +135,7 @@ import java.util.stream.Collectors;
public class Workspace extends PagedView<WorkspacePageIndicator>
implements DropTarget, DragSource, View.OnTouchListener,
DragController.DragListener, Insettable, StateHandler<LauncherState>,
WorkspaceLayoutManager {
WorkspaceLayoutManager, LauncherBindableItemsContainer {
/** The value that {@link #mTransitionProgress} must be greater than for
* {@link #transitionStateShouldAllowDrop()} to return true. */
@@ -3009,9 +3008,9 @@ public class Workspace extends PagedView<WorkspacePageIndicator>
* @param user The user of the app to match.
*/
public View getFirstMatchForAppClose(int preferredItemId, String packageName, UserHandle user) {
final Workspace.ItemOperator preferredItem = (ItemInfo info, View view) ->
final ItemOperator preferredItem = (ItemInfo info, View view) ->
info != null && info.id == preferredItemId;
final Workspace.ItemOperator preferredItemInFolder = (info, view) -> {
final ItemOperator preferredItemInFolder = (info, view) -> {
if (info instanceof FolderInfo) {
FolderInfo folderInfo = (FolderInfo) info;
for (WorkspaceItemInfo shortcutInfo : folderInfo.contents) {
@@ -3022,14 +3021,14 @@ public class Workspace extends PagedView<WorkspacePageIndicator>
}
return false;
};
final Workspace.ItemOperator packageAndUserAndApp = (ItemInfo info, View view) ->
final ItemOperator packageAndUserAndApp = (ItemInfo info, View view) ->
info != null
&& info.itemType == ITEM_TYPE_APPLICATION
&& info.user.equals(user)
&& info.getTargetComponent() != null
&& TextUtils.equals(info.getTargetComponent().getPackageName(),
packageName);
final Workspace.ItemOperator packageAndUserAndAppInFolder = (info, view) -> {
final ItemOperator packageAndUserAndAppInFolder = (info, view) -> {
if (info instanceof FolderInfo) {
FolderInfo folderInfo = (FolderInfo) info;
for (WorkspaceItemInfo shortcutInfo : folderInfo.contents) {
@@ -3148,22 +3147,7 @@ public class Workspace extends PagedView<WorkspacePageIndicator>
stripEmptyScreens();
}
public interface ItemOperator {
/**
* Process the next itemInfo, possibly with side-effect on the next item.
*
* @param info info for the shortcut
* @param view view for the shortcut
* @return true if done, false to continue the map
*/
boolean evaluate(ItemInfo info, View view);
}
/**
* Map the operator over the shortcuts and widgets, return the first-non-null value.
*
* @param op the operator to map over the shortcuts
*/
@Override
public void mapOverItems(ItemOperator op) {
for (CellLayout layout : getWorkspaceAndHotseatCellLayouts()) {
if (mapOverCellLayout(layout, op) != null) {
@@ -3189,31 +3173,6 @@ public class Workspace extends PagedView<WorkspacePageIndicator>
return null;
}
void updateShortcuts(List<WorkspaceItemInfo> shortcuts) {
final HashSet<WorkspaceItemInfo> updates = new HashSet<>(shortcuts);
ItemOperator op = (info, v) -> {
if (v instanceof BubbleTextView && updates.contains(info)) {
WorkspaceItemInfo si = (WorkspaceItemInfo) info;
BubbleTextView shortcut = (BubbleTextView) v;
Drawable oldIcon = shortcut.getIcon();
boolean oldPromiseState = (oldIcon instanceof PreloadIconDrawable)
&& ((PreloadIconDrawable) oldIcon).hasNotCompleted();
shortcut.applyFromWorkspaceItem(si, si.isPromise() != oldPromiseState);
} else if (info instanceof FolderInfo && v instanceof FolderIcon) {
((FolderIcon) v).updatePreviewItems(updates::contains);
}
// Iterate all items
return false;
};
mapOverItems(op);
Folder openFolder = Folder.getOpen(mLauncher);
if (openFolder != null) {
openFolder.iterateOverItems(op);
}
}
public void updateNotificationDots(Predicate<PackageUserKey> updatedDots) {
final PackageUserKey packageUserKey = new PackageUserKey(null, null);
Predicate<ItemInfo> matcher = info -> !packageUserKey.updateFromItemInfo(info)
@@ -3253,28 +3212,6 @@ public class Workspace extends PagedView<WorkspacePageIndicator>
removeItemsByMatcher(matcher);
}
public void updateRestoreItems(final HashSet<ItemInfo> updates) {
ItemOperator op = (info, v) -> {
if (info instanceof WorkspaceItemInfo && v instanceof BubbleTextView
&& updates.contains(info)) {
((BubbleTextView) v).applyLoadingState(false /* promiseStateChanged */);
} else if (v instanceof PendingAppWidgetHostView
&& info instanceof LauncherAppWidgetInfo
&& updates.contains(info)) {
((PendingAppWidgetHostView) v).applyState();
} else if (v instanceof FolderIcon && info instanceof FolderInfo) {
((FolderIcon) v).updatePreviewItems(updates::contains);
}
// process all the shortcuts
return false;
};
mapOverItems(op);
Folder folder = Folder.getOpen(mLauncher);
if (folder != null) {
folder.iterateOverItems(op);
}
}
public void widgetsRestored(final ArrayList<LauncherAppWidgetInfo> changedInfo) {
if (!changedInfo.isEmpty()) {
DeferredWidgetRefresh widgetRefresh = new DeferredWidgetRefresh(changedInfo,

View File

@@ -75,7 +75,6 @@ import com.android.launcher3.PagedView;
import com.android.launcher3.R;
import com.android.launcher3.ShortcutAndWidgetContainer;
import com.android.launcher3.Utilities;
import com.android.launcher3.Workspace.ItemOperator;
import com.android.launcher3.accessibility.AccessibleDragListenerAdapter;
import com.android.launcher3.accessibility.FolderAccessibilityHelper;
import com.android.launcher3.anim.KeyboardInsetAnimationCallback;
@@ -94,6 +93,7 @@ import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.model.data.WorkspaceItemInfo;
import com.android.launcher3.pageindicators.PageIndicatorDots;
import com.android.launcher3.util.Executors;
import com.android.launcher3.util.LauncherBindableItemsContainer.ItemOperator;
import com.android.launcher3.util.Thunk;
import com.android.launcher3.views.ActivityContext;
import com.android.launcher3.views.BaseDragLayer;
@@ -1196,8 +1196,7 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo
}
void replaceFolderWithFinalItem() {
mLauncherDelegate.replaceFolderWithFinalItem(this);
mDestroyed = true;
mDestroyed = mLauncherDelegate.replaceFolderWithFinalItem(this);
}
public boolean isDestroyed() {

View File

@@ -679,6 +679,7 @@ public class FolderIcon extends FrameLayout implements FolderListener, IconLabel
@Override
public void onAdd(WorkspaceItemInfo item, int rank) {
updatePreviewItems(false);
boolean wasDotted = mDotInfo.hasDot();
mDotInfo.addDotInfo(mActivity.getDotInfoForItem(item));
boolean isDotted = mDotInfo.hasDot();
@@ -690,6 +691,7 @@ public class FolderIcon extends FrameLayout implements FolderListener, IconLabel
@Override
public void onRemove(List<WorkspaceItemInfo> items) {
updatePreviewItems(false);
boolean wasDotted = mDotInfo.hasDot();
items.stream().map(mActivity::getDotInfoForItem).forEach(mDotInfo::subtractDotInfo);
boolean isDotted = mDotInfo.hasDot();

View File

@@ -41,12 +41,12 @@ import com.android.launcher3.PagedView;
import com.android.launcher3.R;
import com.android.launcher3.ShortcutAndWidgetContainer;
import com.android.launcher3.Utilities;
import com.android.launcher3.Workspace.ItemOperator;
import com.android.launcher3.keyboard.ViewGroupFocusHelper;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.model.data.WorkspaceItemInfo;
import com.android.launcher3.pageindicators.PageIndicatorDots;
import com.android.launcher3.touch.ItemClickHandler;
import com.android.launcher3.util.LauncherBindableItemsContainer.ItemOperator;
import com.android.launcher3.util.Thunk;
import com.android.launcher3.util.ViewCache;
import com.android.launcher3.views.ActivityContext;

View File

@@ -93,7 +93,7 @@ public class LauncherDelegate {
}
}
void replaceFolderWithFinalItem(Folder folder) {
boolean replaceFolderWithFinalItem(Folder folder) {
// Add the last remaining child to the workspace in place of the folder
Runnable onCompleteRunnable = new Runnable() {
@Override
@@ -147,6 +147,7 @@ public class LauncherDelegate {
} else {
onCompleteRunnable.run();
}
return true;
}
@@ -191,7 +192,7 @@ public class LauncherDelegate {
ModelWriter getModelWriter() {
if (mWriter == null) {
mWriter = LauncherAppState.getInstance((Context) mContext).getModel()
.getWriter(false, false);
.getWriter(false, false, null);
}
return mWriter;
}
@@ -205,7 +206,9 @@ public class LauncherDelegate {
}
@Override
void replaceFolderWithFinalItem(Folder folder) { }
boolean replaceFolderWithFinalItem(Folder folder) {
return false;
}
@Override
boolean interceptOutsideTouch(MotionEvent ev, BaseDragLayer dl, Folder folder) {

View File

@@ -16,6 +16,7 @@
package com.android.launcher3.model;
import static com.android.launcher3.model.ItemInstallQueue.FLAG_LOADER_RUNNING;
import static com.android.launcher3.model.ModelUtils.filterCurrentWorkspaceItems;
import static com.android.launcher3.model.ModelUtils.sortWorkspaceItemsSpatially;
import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
@@ -73,7 +74,7 @@ public abstract class BaseLoaderResults {
/**
* Binds all loaded data to actual views on the main thread.
*/
public void bindWorkspace() {
public void bindWorkspace(boolean incrementBindId) {
// Save a copy of all the bg-thread collections
ArrayList<ItemInfo> workspaceItems = new ArrayList<>();
ArrayList<LauncherAppWidgetInfo> appWidgets = new ArrayList<>();
@@ -85,7 +86,9 @@ public abstract class BaseLoaderResults {
appWidgets.addAll(mBgDataModel.appWidgets);
orderedScreenIds.addAll(mBgDataModel.collectWorkspaceScreens());
mBgDataModel.extraItems.forEach(extraItems::add);
mBgDataModel.lastBindId++;
if (incrementBindId) {
mBgDataModel.lastBindId++;
}
mMyBindingId = mBgDataModel.lastBindId;
}
@@ -217,7 +220,11 @@ public abstract class BaseLoaderResults {
bindAppWidgets(otherAppWidgets, pendingExecutor);
executeCallbacksTask(c -> c.finishBindingItems(currentScreenIndices), pendingExecutor);
pendingExecutor.execute(
() -> MODEL_EXECUTOR.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT));
() -> {
MODEL_EXECUTOR.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
ItemInstallQueue.INSTANCE.get(mApp.getContext())
.resumeModelPush(FLAG_LOADER_RUNNING);
});
executeCallbacksTask(
c -> {

View File

@@ -90,7 +90,7 @@ public abstract class BaseModelUpdateTask implements ModelUpdateTask {
public ModelWriter getModelWriter() {
// Updates from model task, do not deal with icon position in hotseat. Also no need to
// verify changes as the ModelTasks always push the changes to callbacks
return mModel.getWriter(false /* hasVerticalHotseat */, false /* verifyChanges */);
return mModel.getWriter(false /* hasVerticalHotseat */, false /* verifyChanges */, null);
}
public void bindUpdatedWorkspaceItems(List<WorkspaceItemInfo> allUpdates) {

View File

@@ -476,6 +476,11 @@ public class BgDataModel {
default void bindAppsAdded(IntArray newScreens,
ArrayList<ItemInfo> addNotAnimated, ArrayList<ItemInfo> addAnimated) { }
/**
* Called when some persistent property of an item is modified
*/
default void bindItemsModified(List<ItemInfo> items) { }
/**
* Binds updated incremental download progress
*/

View File

@@ -210,7 +210,7 @@ public class LoaderTask implements Runnable {
}
verifyNotStopped();
mResults.bindWorkspace();
mResults.bindWorkspace(true /* incrementBindId */);
logASplit(logger, "bindWorkspace");
mModelDelegate.workspaceLoadComplete();

View File

@@ -23,12 +23,13 @@ import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.net.Uri;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import androidx.annotation.Nullable;
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.LauncherModel;
import com.android.launcher3.LauncherModel.CallbackTask;
import com.android.launcher3.LauncherProvider;
import com.android.launcher3.LauncherSettings;
import com.android.launcher3.LauncherSettings.Favorites;
@@ -36,19 +37,22 @@ import com.android.launcher3.LauncherSettings.Settings;
import com.android.launcher3.Utilities;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.logging.FileLog;
import com.android.launcher3.model.BgDataModel.Callbacks;
import com.android.launcher3.model.data.FolderInfo;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.model.data.LauncherAppWidgetInfo;
import com.android.launcher3.model.data.WorkspaceItemInfo;
import com.android.launcher3.util.ContentWriter;
import com.android.launcher3.util.Executors;
import com.android.launcher3.util.ItemInfoMatcher;
import com.android.launcher3.util.LooperExecutor;
import com.android.launcher3.widget.LauncherAppWidgetHost;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.Executor;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;
@@ -63,7 +67,10 @@ public class ModelWriter {
private final Context mContext;
private final LauncherModel mModel;
private final BgDataModel mBgDataModel;
private final Handler mUiHandler;
private final LooperExecutor mUiExecutor;
@Nullable
private final Callbacks mOwner;
private final boolean mHasVerticalHotseat;
private final boolean mVerifyChanges;
@@ -73,13 +80,15 @@ public class ModelWriter {
private boolean mPreparingToUndo;
public ModelWriter(Context context, LauncherModel model, BgDataModel dataModel,
boolean hasVerticalHotseat, boolean verifyChanges) {
boolean hasVerticalHotseat, boolean verifyChanges,
@Nullable Callbacks owner) {
mContext = context;
mModel = model;
mBgDataModel = dataModel;
mHasVerticalHotseat = hasVerticalHotseat;
mVerifyChanges = verifyChanges;
mUiHandler = new Handler(Looper.getMainLooper());
mOwner = owner;
mUiExecutor = Executors.MAIN_EXECUTOR;
}
private void updateItemInfoProps(
@@ -162,6 +171,8 @@ public class ModelWriter {
public void moveItemInDatabase(final ItemInfo item,
int container, int screenId, int cellX, int cellY) {
updateItemInfoProps(item, container, screenId, cellX, cellY);
notifyItemModified(item);
enqueueDeleteRunnable(new UpdateItemRunnable(item, () ->
new ContentWriter(mContext)
.put(Favorites.CONTAINER, item.container)
@@ -178,6 +189,7 @@ public class ModelWriter {
public void moveItemsInDatabase(final ArrayList<ItemInfo> items, int container, int screen) {
ArrayList<ContentValues> contentValues = new ArrayList<>();
int count = items.size();
notifyOtherCallbacks(c -> c.bindItemsModified(items));
for (int i = 0; i < count; i++) {
ItemInfo item = items.get(i);
@@ -203,8 +215,9 @@ public class ModelWriter {
updateItemInfoProps(item, container, screenId, cellX, cellY);
item.spanX = spanX;
item.spanY = spanY;
notifyItemModified(item);
((Executor) MODEL_EXECUTOR).execute(new UpdateItemRunnable(item, () ->
MODEL_EXECUTOR.execute(new UpdateItemRunnable(item, () ->
new ContentWriter(mContext)
.put(Favorites.CONTAINER, item.container)
.put(Favorites.CELLX, item.cellX)
@@ -219,13 +232,18 @@ public class ModelWriter {
* Update an item to the database in a specified container.
*/
public void updateItemInDatabase(ItemInfo item) {
((Executor) MODEL_EXECUTOR).execute(new UpdateItemRunnable(item, () -> {
notifyItemModified(item);
MODEL_EXECUTOR.execute(new UpdateItemRunnable(item, () -> {
ContentWriter writer = new ContentWriter(mContext);
item.onAddToDatabase(writer);
return writer;
}));
}
private void notifyItemModified(ItemInfo item) {
notifyOtherCallbacks(c -> c.bindItemsModified(Collections.singletonList(item)));
}
/**
* Add an item to the database in a specified container. Sets the container, screen, cellX and
* cellY fields of the item. Also assigns an ID to the item.
@@ -236,10 +254,11 @@ public class ModelWriter {
final ContentResolver cr = mContext.getContentResolver();
item.id = Settings.call(cr, Settings.METHOD_NEW_ITEM_ID).getInt(Settings.EXTRA_VALUE);
notifyOtherCallbacks(c -> c.bindItems(Collections.singletonList(item), false));
ModelVerifier verifier = new ModelVerifier();
final StackTraceElement[] stackTrace = new Throwable().getStackTrace();
((Executor) MODEL_EXECUTOR).execute(() -> {
MODEL_EXECUTOR.execute(() -> {
// Write the item on background thread, as some properties might have been updated in
// the background.
final ContentWriter writer = new ContentWriter(mContext);
@@ -281,6 +300,7 @@ public class ModelWriter {
(item) -> item.getTargetComponent() == null ? ""
: item.getTargetComponent().getPackageName()).collect(
Collectors.joining(",")), new Exception());
notifyDelete(items);
enqueueDeleteRunnable(() -> {
for (ItemInfo item : items) {
final Uri uri = Favorites.getContentUri(item.id);
@@ -297,6 +317,7 @@ public class ModelWriter {
*/
public void deleteFolderAndContentsFromDatabase(final FolderInfo info) {
ModelVerifier verifier = new ModelVerifier();
notifyDelete(Collections.singleton(info));
enqueueDeleteRunnable(() -> {
ContentResolver cr = mContext.getContentResolver();
@@ -315,6 +336,7 @@ public class ModelWriter {
* Deletes the widget info and the widget id.
*/
public void deleteWidgetInfo(final LauncherAppWidgetInfo info, LauncherAppWidgetHost host) {
notifyDelete(Collections.singleton(info));
if (host != null && !info.isCustomWidget() && info.isWidgetIdAllocated()) {
// Deleting an app widget ID is a void call but writes to disk before returning
// to the caller...
@@ -323,6 +345,10 @@ public class ModelWriter {
deleteItemFromDatabase(info);
}
private void notifyDelete(Collection<? extends ItemInfo> items) {
notifyOtherCallbacks(c -> c.bindWorkspaceComponentsRemoved(ItemInfoMatcher.ofItems(items)));
}
/**
* Delete operations tracked using {@link #enqueueDeleteRunnable} will only be called
* if {@link #commitDelete} is called. Note that one of {@link #commitDelete()} or
@@ -348,14 +374,14 @@ public class ModelWriter {
if (mPreparingToUndo) {
mDeleteRunnables.add(r);
} else {
((Executor) MODEL_EXECUTOR).execute(r);
MODEL_EXECUTOR.execute(r);
}
}
public void commitDelete() {
mPreparingToUndo = false;
for (Runnable runnable : mDeleteRunnables) {
((Executor) MODEL_EXECUTOR).execute(runnable);
MODEL_EXECUTOR.execute(runnable);
}
mDeleteRunnables.clear();
}
@@ -371,6 +397,20 @@ public class ModelWriter {
mModel.forceReload();
}
private void notifyOtherCallbacks(CallbackTask task) {
if (mOwner == null) {
// If the call is happening from a model, it will take care of updating the callbacks
return;
}
mUiExecutor.execute(() -> {
for (Callbacks c : mModel.getCallbacks()) {
if (c != mOwner) {
task.execute(c);
}
}
});
}
private class UpdateItemRunnable extends UpdateItemBaseRunnable {
private final ItemInfo mItem;
private final Supplier<ContentWriter> mWriter;
@@ -491,7 +531,7 @@ public class ModelWriter {
int executeId = mBgDataModel.lastBindId;
mUiHandler.post(() -> {
mUiExecutor.post(() -> {
int currentId = mBgDataModel.lastBindId;
if (currentId > executeId) {
// Model was already bound after job was executed.

View File

@@ -23,6 +23,7 @@ import com.android.launcher3.LauncherSettings.Favorites;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.shortcuts.ShortcutKey;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
@@ -89,4 +90,13 @@ public interface ItemInfoMatcher {
static ItemInfoMatcher ofItemIds(IntSet ids) {
return (info, cn) -> ids.contains(info.id);
}
/**
* Returns a matcher for items with provided items
*/
static ItemInfoMatcher ofItems(Collection<? extends ItemInfo> items) {
IntSet ids = new IntSet();
items.forEach(item -> ids.add(item.id));
return ofItemIds(ids);
}
}

View File

@@ -0,0 +1,113 @@
/*
* Copyright (C) 2021 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.util;
import android.graphics.drawable.Drawable;
import android.view.View;
import com.android.launcher3.BubbleTextView;
import com.android.launcher3.folder.Folder;
import com.android.launcher3.folder.FolderIcon;
import com.android.launcher3.graphics.PreloadIconDrawable;
import com.android.launcher3.model.data.FolderInfo;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.model.data.LauncherAppWidgetInfo;
import com.android.launcher3.model.data.WorkspaceItemInfo;
import com.android.launcher3.views.ActivityContext;
import com.android.launcher3.widget.PendingAppWidgetHostView;
import java.util.HashSet;
import java.util.List;
/**
* Interface representing a container which can bind Launcher items with some utility methods
*/
public interface LauncherBindableItemsContainer {
/**
* Called to update workspace items as a result of
* {@link com.android.launcher3.model.BgDataModel.Callbacks#bindWorkspaceItemsChanged(List)}
*/
default void updateWorkspaceItems(List<WorkspaceItemInfo> shortcuts, ActivityContext context) {
final HashSet<WorkspaceItemInfo> updates = new HashSet<>(shortcuts);
ItemOperator op = (info, v) -> {
if (v instanceof BubbleTextView && updates.contains(info)) {
WorkspaceItemInfo si = (WorkspaceItemInfo) info;
BubbleTextView shortcut = (BubbleTextView) v;
Drawable oldIcon = shortcut.getIcon();
boolean oldPromiseState = (oldIcon instanceof PreloadIconDrawable)
&& ((PreloadIconDrawable) oldIcon).hasNotCompleted();
shortcut.applyFromWorkspaceItem(si, si.isPromise() != oldPromiseState);
} else if (info instanceof FolderInfo && v instanceof FolderIcon) {
((FolderIcon) v).updatePreviewItems(updates::contains);
}
// Iterate all items
return false;
};
mapOverItems(op);
Folder openFolder = Folder.getOpen(context);
if (openFolder != null) {
openFolder.iterateOverItems(op);
}
}
/**
* Called to update restored items as a result of
* {@link com.android.launcher3.model.BgDataModel.Callbacks#bindRestoreItemsChange(HashSet)}}
*/
default void updateRestoreItems(final HashSet<ItemInfo> updates, ActivityContext context) {
ItemOperator op = (info, v) -> {
if (info instanceof WorkspaceItemInfo && v instanceof BubbleTextView
&& updates.contains(info)) {
((BubbleTextView) v).applyLoadingState(false /* promiseStateChanged */);
} else if (v instanceof PendingAppWidgetHostView
&& info instanceof LauncherAppWidgetInfo
&& updates.contains(info)) {
((PendingAppWidgetHostView) v).applyState();
} else if (v instanceof FolderIcon && info instanceof FolderInfo) {
((FolderIcon) v).updatePreviewItems(updates::contains);
}
// process all the shortcuts
return false;
};
mapOverItems(op);
Folder folder = Folder.getOpen(context);
if (folder != null) {
folder.iterateOverItems(op);
}
}
/**
* Map the operator over the shortcuts and widgets.
*
* @param op the operator to map over the shortcuts
*/
void mapOverItems(ItemOperator op);
interface ItemOperator {
/**
* Process the next itemInfo, possibly with side-effect on the next item.
*
* @param info info for the shortcut
* @param view view for the shortcut
* @return true if done, false to continue the map
*/
boolean evaluate(ItemInfo info, View view);
}
}

View File

@@ -25,8 +25,8 @@ import androidx.test.runner.AndroidJUnit4;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherState;
import com.android.launcher3.Workspace;
import com.android.launcher3.ui.AbstractLauncherUiTest;
import com.android.launcher3.util.LauncherBindableItemsContainer.ItemOperator;
import org.junit.After;
import org.junit.Test;
@@ -75,7 +75,7 @@ public class PromiseIconUiTest extends AbstractLauncherUiTest {
@Test
public void testPromiseIcon_addedFromEligibleSession() throws Throwable {
final String appLabel = "Test Promise App " + UUID.randomUUID().toString();
final Workspace.ItemOperator findPromiseApp = (info, view) ->
final ItemOperator findPromiseApp = (info, view) ->
info != null && TextUtils.equals(info.title, appLabel);
// Create and add test session
@@ -97,7 +97,7 @@ public class PromiseIconUiTest extends AbstractLauncherUiTest {
@Test
public void testPromiseIcon_notAddedFromIneligibleSession() throws Throwable {
final String appLabel = "Test Promise App " + UUID.randomUUID().toString();
final Workspace.ItemOperator findPromiseApp = (info, view) ->
final ItemOperator findPromiseApp = (info, view) ->
info != null && TextUtils.equals(info.title, appLabel);
// Create and add test session without icon or label

View File

@@ -28,13 +28,13 @@ import android.view.View;
import androidx.test.filters.LargeTest;
import androidx.test.runner.AndroidJUnit4;
import com.android.launcher3.Workspace;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.model.data.LauncherAppWidgetInfo;
import com.android.launcher3.tapl.Widgets;
import com.android.launcher3.testcomponent.WidgetConfigActivity;
import com.android.launcher3.ui.AbstractLauncherUiTest;
import com.android.launcher3.ui.TestViewHelpers;
import com.android.launcher3.util.LauncherBindableItemsContainer.ItemOperator;
import com.android.launcher3.util.Wait;
import com.android.launcher3.util.Wait.Condition;
import com.android.launcher3.util.rule.ShellCommandRule;
@@ -121,7 +121,7 @@ public class AddConfigWidgetTest extends AbstractLauncherUiTest {
/**
* Condition for searching widget id
*/
private class WidgetSearchCondition implements Condition, Workspace.ItemOperator {
private class WidgetSearchCondition implements Condition, ItemOperator {
@Override
public boolean isTrue() throws Throwable {

View File

@@ -30,7 +30,6 @@ import androidx.test.filters.LargeTest;
import androidx.test.runner.AndroidJUnit4;
import com.android.launcher3.LauncherSettings.Favorites;
import com.android.launcher3.Workspace.ItemOperator;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.model.data.LauncherAppWidgetInfo;
import com.android.launcher3.model.data.WorkspaceItemInfo;
@@ -40,6 +39,7 @@ import com.android.launcher3.testcomponent.AppWidgetNoConfig;
import com.android.launcher3.testcomponent.AppWidgetWithConfig;
import com.android.launcher3.testcomponent.RequestPinItemActivity;
import com.android.launcher3.ui.AbstractLauncherUiTest;
import com.android.launcher3.util.LauncherBindableItemsContainer.ItemOperator;
import com.android.launcher3.util.Wait;
import com.android.launcher3.util.Wait.Condition;
import com.android.launcher3.util.rule.ScreenRecordRule.ScreenRecord;

View File

@@ -18,7 +18,7 @@ package com.android.launcher3.util.rule;
import android.app.Activity;
import com.android.launcher3.Launcher;
import com.android.launcher3.Workspace.ItemOperator;
import com.android.launcher3.util.LauncherBindableItemsContainer.ItemOperator;
import org.junit.runner.Description;
import org.junit.runners.model.Statement;