2021727f1e
- No longer bind All Apps to TaskbarRecentsController, and register RecentsModel.RecentTasksChangedListener instead - The source of truth for "running tasks" in Desktop mode is the DesktopTask#tasks list itself, instead of RecentsModel.RunningTasksListener (which is no longer used) - Added TaskInfo.TaskKey#isVisible to distinguish minimized running apps - Next CL will hook up the UI for Recent/Running tasks that are not part of the Hotseat. Flag: com.android.launcher3.enable_recents_in_taskbar Test: TaskbarRecentAppsControllerTest Fixes: 335398876 Bug: 315354060 Change-Id: I1313f97a791c5c0c1db7443a5d4f1d5bc761981f
264 lines
9.0 KiB
Java
264 lines
9.0 KiB
Java
/*
|
|
* 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 androidx.annotation.UiThread;
|
|
|
|
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.AppInfo;
|
|
import com.android.launcher3.model.data.ItemInfo;
|
|
import com.android.launcher3.model.data.WorkspaceItemInfo;
|
|
import com.android.launcher3.util.ComponentKey;
|
|
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 com.android.launcher3.util.PackageUserKey;
|
|
import com.android.launcher3.util.Preconditions;
|
|
|
|
import java.io.PrintWriter;
|
|
import java.util.ArrayList;
|
|
import java.util.Collections;
|
|
import java.util.HashMap;
|
|
import java.util.HashSet;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
import java.util.Set;
|
|
import java.util.function.Predicate;
|
|
|
|
/**
|
|
* 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;
|
|
|
|
// Initialized in init.
|
|
protected TaskbarControllers mControllers;
|
|
|
|
// Used to defer any UI updates during the SUW unstash animation.
|
|
private boolean mDeferUpdatesForSUW;
|
|
private Runnable mDeferredUpdates;
|
|
|
|
public TaskbarModelCallbacks(
|
|
TaskbarActivityContext context, TaskbarView container) {
|
|
mContext = context;
|
|
mContainer = container;
|
|
}
|
|
|
|
public void init(TaskbarControllers controllers) {
|
|
mControllers = controllers;
|
|
}
|
|
|
|
@Override
|
|
public void startBinding() {
|
|
mContext.setBindingItems(true);
|
|
mHotseatItems.clear();
|
|
mPredictedItems = Collections.emptyList();
|
|
}
|
|
|
|
@Override
|
|
public void finishBindingItems(IntSet pagesBoundFirst) {
|
|
mContext.setBindingItems(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(Predicate<ItemInfo> matcher) {
|
|
if (handleItemsRemoved(matcher)) {
|
|
commitItemsToUI();
|
|
}
|
|
}
|
|
|
|
private boolean handleItemsRemoved(Predicate<ItemInfo> matcher) {
|
|
boolean modified = false;
|
|
for (int i = mHotseatItems.size() - 1; i >= 0; i--) {
|
|
if (matcher.test(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();
|
|
} else if (item.containerId == Favorites.CONTAINER_PREDICTION) {
|
|
mControllers.taskbarAllAppsController.setPredictedApps(item.items);
|
|
}
|
|
}
|
|
|
|
private void commitItemsToUI() {
|
|
if (mContext.isBindingItems()) {
|
|
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++;
|
|
}
|
|
}
|
|
|
|
final TaskbarRecentAppsController recentAppsController =
|
|
mControllers.taskbarRecentAppsController;
|
|
hotseatItemInfos = recentAppsController.updateHotseatItemInfos(hotseatItemInfos);
|
|
Set<String> runningPackages = recentAppsController.getRunningAppPackages();
|
|
Set<String> minimizedPackages = recentAppsController.getMinimizedAppPackages();
|
|
|
|
if (mDeferUpdatesForSUW) {
|
|
ItemInfo[] finalHotseatItemInfos = hotseatItemInfos;
|
|
mDeferredUpdates = () ->
|
|
commitHotseatItemUpdates(finalHotseatItemInfos, runningPackages,
|
|
minimizedPackages);
|
|
} else {
|
|
commitHotseatItemUpdates(hotseatItemInfos, runningPackages, minimizedPackages);
|
|
}
|
|
}
|
|
|
|
private void commitHotseatItemUpdates(ItemInfo[] hotseatItemInfos, Set<String> runningPackages,
|
|
Set<String> minimizedPackages) {
|
|
mContainer.updateHotseatItems(hotseatItemInfos);
|
|
mControllers.taskbarViewController.updateIconViewsRunningStates(runningPackages,
|
|
minimizedPackages);
|
|
}
|
|
|
|
/**
|
|
* This is used to defer UI updates after SUW builds the unstash animation.
|
|
* @param defer if true, defers updates to the UI
|
|
* if false, posts updates (if any) to the UI
|
|
*/
|
|
public void setDeferUpdatesForSUW(boolean defer) {
|
|
mDeferUpdatesForSUW = defer;
|
|
|
|
if (!mDeferUpdatesForSUW) {
|
|
if (mDeferredUpdates != null) {
|
|
mContainer.post(mDeferredUpdates);
|
|
mDeferredUpdates = null;
|
|
}
|
|
}
|
|
}
|
|
|
|
/** Called when there's a change in running apps to update the UI. */
|
|
public void commitRunningAppsToUI() {
|
|
commitItemsToUI();
|
|
}
|
|
|
|
@Override
|
|
public void bindDeepShortcutMap(HashMap<ComponentKey, Integer> deepShortcutMapCopy) {
|
|
mControllers.taskbarPopupController.setDeepShortcutMap(deepShortcutMapCopy);
|
|
}
|
|
|
|
@UiThread
|
|
@Override
|
|
public void bindAllApplications(AppInfo[] apps, int flags,
|
|
Map<PackageUserKey, Integer> packageUserKeytoUidMap) {
|
|
Preconditions.assertUIThread();
|
|
mControllers.taskbarAllAppsController.setApps(apps, flags, packageUserKeytoUidMap);
|
|
}
|
|
|
|
protected void dumpLogs(String prefix, PrintWriter pw) {
|
|
pw.println(prefix + "TaskbarModelCallbacks:");
|
|
|
|
pw.println(String.format("%s\thotseat items count=%s", prefix, mHotseatItems.size()));
|
|
if (mPredictedItems != null) {
|
|
pw.println(
|
|
String.format("%s\tpredicted items count=%s", prefix, mPredictedItems.size()));
|
|
}
|
|
pw.println(String.format("%s\tmDeferUpdatesForSUW=%b", prefix, mDeferUpdatesForSUW));
|
|
pw.println(String.format("%s\tupdates pending=%b", prefix, (mDeferredUpdates != null)));
|
|
}
|
|
}
|