1 /* 2 * Copyright (C) 2021 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package com.android.launcher3.taskbar; 17 18 import android.util.SparseArray; 19 import android.view.View; 20 21 import com.android.launcher3.LauncherSettings.Favorites; 22 import com.android.launcher3.model.BgDataModel; 23 import com.android.launcher3.model.BgDataModel.FixedContainerItems; 24 import com.android.launcher3.model.data.AppInfo; 25 import com.android.launcher3.model.data.ItemInfo; 26 import com.android.launcher3.model.data.WorkspaceItemInfo; 27 import com.android.launcher3.util.ComponentKey; 28 import com.android.launcher3.util.IntArray; 29 import com.android.launcher3.util.IntSet; 30 import com.android.launcher3.util.ItemInfoMatcher; 31 import com.android.launcher3.util.LauncherBindableItemsContainer; 32 import com.android.quickstep.RecentsModel; 33 34 import java.io.PrintWriter; 35 import java.util.ArrayList; 36 import java.util.Collections; 37 import java.util.HashMap; 38 import java.util.HashSet; 39 import java.util.List; 40 import java.util.function.Predicate; 41 42 /** 43 * Launcher model Callbacks for rendering taskbar. 44 */ 45 public class TaskbarModelCallbacks implements 46 BgDataModel.Callbacks, LauncherBindableItemsContainer, RecentsModel.RunningTasksListener { 47 48 private final SparseArray<ItemInfo> mHotseatItems = new SparseArray<>(); 49 private List<ItemInfo> mPredictedItems = Collections.emptyList(); 50 51 private final TaskbarActivityContext mContext; 52 private final TaskbarView mContainer; 53 54 // Initialized in init. 55 private TaskbarControllers mControllers; 56 TaskbarModelCallbacks( TaskbarActivityContext context, TaskbarView container)57 public TaskbarModelCallbacks( 58 TaskbarActivityContext context, TaskbarView container) { 59 mContext = context; 60 mContainer = container; 61 } 62 init(TaskbarControllers controllers)63 public void init(TaskbarControllers controllers) { 64 mControllers = controllers; 65 if (mControllers.taskbarRecentAppsController.isEnabled()) { 66 RecentsModel.INSTANCE.get(mContext).registerRunningTasksListener(this); 67 } 68 } 69 70 /** 71 * Unregisters listeners in this class. 72 */ unregisterListeners()73 public void unregisterListeners() { 74 RecentsModel.INSTANCE.get(mContext).unregisterRunningTasksListener(); 75 } 76 77 @Override startBinding()78 public void startBinding() { 79 mContext.setBindingItems(true); 80 mHotseatItems.clear(); 81 mPredictedItems = Collections.emptyList(); 82 } 83 84 @Override finishBindingItems(IntSet pagesBoundFirst)85 public void finishBindingItems(IntSet pagesBoundFirst) { 86 mContext.setBindingItems(false); 87 commitItemsToUI(); 88 } 89 90 @Override bindAppsAdded(IntArray newScreens, ArrayList<ItemInfo> addNotAnimated, ArrayList<ItemInfo> addAnimated)91 public void bindAppsAdded(IntArray newScreens, ArrayList<ItemInfo> addNotAnimated, 92 ArrayList<ItemInfo> addAnimated) { 93 boolean add1 = handleItemsAdded(addNotAnimated); 94 boolean add2 = handleItemsAdded(addAnimated); 95 if (add1 || add2) { 96 commitItemsToUI(); 97 } 98 } 99 100 @Override bindItems(List<ItemInfo> shortcuts, boolean forceAnimateIcons)101 public void bindItems(List<ItemInfo> shortcuts, boolean forceAnimateIcons) { 102 if (handleItemsAdded(shortcuts)) { 103 commitItemsToUI(); 104 } 105 } 106 handleItemsAdded(List<ItemInfo> items)107 private boolean handleItemsAdded(List<ItemInfo> items) { 108 boolean modified = false; 109 for (ItemInfo item : items) { 110 if (item.container == Favorites.CONTAINER_HOTSEAT) { 111 mHotseatItems.put(item.screenId, item); 112 modified = true; 113 } 114 } 115 return modified; 116 } 117 118 119 @Override bindWorkspaceItemsChanged(List<WorkspaceItemInfo> updated)120 public void bindWorkspaceItemsChanged(List<WorkspaceItemInfo> updated) { 121 updateWorkspaceItems(updated, mContext); 122 } 123 124 @Override bindRestoreItemsChange(HashSet<ItemInfo> updates)125 public void bindRestoreItemsChange(HashSet<ItemInfo> updates) { 126 updateRestoreItems(updates, mContext); 127 } 128 129 @Override mapOverItems(ItemOperator op)130 public void mapOverItems(ItemOperator op) { 131 final int itemCount = mContainer.getChildCount(); 132 for (int itemIdx = 0; itemIdx < itemCount; itemIdx++) { 133 View item = mContainer.getChildAt(itemIdx); 134 if (op.evaluate((ItemInfo) item.getTag(), item)) { 135 return; 136 } 137 } 138 } 139 140 @Override bindWorkspaceComponentsRemoved(Predicate<ItemInfo> matcher)141 public void bindWorkspaceComponentsRemoved(Predicate<ItemInfo> matcher) { 142 if (handleItemsRemoved(matcher)) { 143 commitItemsToUI(); 144 } 145 } 146 handleItemsRemoved(Predicate<ItemInfo> matcher)147 private boolean handleItemsRemoved(Predicate<ItemInfo> matcher) { 148 boolean modified = false; 149 for (int i = mHotseatItems.size() - 1; i >= 0; i--) { 150 if (matcher.test(mHotseatItems.valueAt(i))) { 151 modified = true; 152 mHotseatItems.removeAt(i); 153 } 154 } 155 return modified; 156 } 157 158 @Override bindItemsModified(List<ItemInfo> items)159 public void bindItemsModified(List<ItemInfo> items) { 160 boolean removed = handleItemsRemoved(ItemInfoMatcher.ofItems(items)); 161 boolean added = handleItemsAdded(items); 162 if (removed || added) { 163 commitItemsToUI(); 164 } 165 } 166 167 @Override bindExtraContainerItems(FixedContainerItems item)168 public void bindExtraContainerItems(FixedContainerItems item) { 169 if (item.containerId == Favorites.CONTAINER_HOTSEAT_PREDICTION) { 170 mPredictedItems = item.items; 171 commitItemsToUI(); 172 } else if (item.containerId == Favorites.CONTAINER_PREDICTION) { 173 mControllers.taskbarAllAppsController.setPredictedApps(item.items); 174 } 175 } 176 commitItemsToUI()177 private void commitItemsToUI() { 178 if (mContext.isBindingItems()) { 179 return; 180 } 181 182 ItemInfo[] hotseatItemInfos = 183 new ItemInfo[mContext.getDeviceProfile().numShownHotseatIcons]; 184 int predictionSize = mPredictedItems.size(); 185 int predictionNextIndex = 0; 186 187 for (int i = 0; i < hotseatItemInfos.length; i++) { 188 hotseatItemInfos[i] = mHotseatItems.get(i); 189 if (hotseatItemInfos[i] == null && predictionNextIndex < predictionSize) { 190 hotseatItemInfos[i] = mPredictedItems.get(predictionNextIndex); 191 hotseatItemInfos[i].screenId = i; 192 predictionNextIndex++; 193 } 194 } 195 hotseatItemInfos = mControllers.taskbarRecentAppsController 196 .updateHotseatItemInfos(hotseatItemInfos); 197 mContainer.updateHotseatItems(hotseatItemInfos); 198 mControllers.taskbarViewController.updateIconsBackground(); 199 } 200 201 @Override onRunningTasksChanged()202 public void onRunningTasksChanged() { 203 updateRunningApps(); 204 } 205 206 /** Called when there's a change in running apps to update the UI. */ commitRunningAppsToUI()207 public void commitRunningAppsToUI() { 208 commitItemsToUI(); 209 } 210 211 /** Call TaskbarRecentAppsController to update running apps with mHotseatItems. */ updateRunningApps()212 public void updateRunningApps() { 213 mControllers.taskbarRecentAppsController.updateRunningApps(mHotseatItems); 214 } 215 216 @Override bindDeepShortcutMap(HashMap<ComponentKey, Integer> deepShortcutMapCopy)217 public void bindDeepShortcutMap(HashMap<ComponentKey, Integer> deepShortcutMapCopy) { 218 mControllers.taskbarPopupController.setDeepShortcutMap(deepShortcutMapCopy); 219 } 220 221 @Override bindAllApplications(AppInfo[] apps, int flags)222 public void bindAllApplications(AppInfo[] apps, int flags) { 223 mControllers.taskbarAllAppsController.setApps(apps, flags); 224 mControllers.taskbarRecentAppsController.setApps(apps); 225 } 226 dumpLogs(String prefix, PrintWriter pw)227 protected void dumpLogs(String prefix, PrintWriter pw) { 228 pw.println(prefix + "TaskbarModelCallbacks:"); 229 230 pw.println(String.format("%s\thotseat items count=%s", prefix, mHotseatItems.size())); 231 if (mPredictedItems != null) { 232 pw.println( 233 String.format("%s\tpredicted items count=%s", prefix, mPredictedItems.size())); 234 } 235 } 236 } 237