• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 androidx.annotation.NonNull;
22 import androidx.annotation.UiThread;
23 
24 import com.android.launcher3.LauncherSettings.Favorites;
25 import com.android.launcher3.model.BgDataModel;
26 import com.android.launcher3.model.BgDataModel.FixedContainerItems;
27 import com.android.launcher3.model.data.AppInfo;
28 import com.android.launcher3.model.data.ItemInfo;
29 import com.android.launcher3.util.ComponentKey;
30 import com.android.launcher3.util.IntArray;
31 import com.android.launcher3.util.IntSet;
32 import com.android.launcher3.util.ItemInfoMatcher;
33 import com.android.launcher3.util.LauncherBindableItemsContainer;
34 import com.android.launcher3.util.PackageUserKey;
35 import com.android.launcher3.util.Preconditions;
36 import com.android.quickstep.util.GroupTask;
37 
38 import java.io.PrintWriter;
39 import java.util.ArrayList;
40 import java.util.Collections;
41 import java.util.HashMap;
42 import java.util.List;
43 import java.util.Map;
44 import java.util.Set;
45 import java.util.function.Predicate;
46 
47 /**
48  * Launcher model Callbacks for rendering taskbar.
49  */
50 public class TaskbarModelCallbacks implements
51         BgDataModel.Callbacks, LauncherBindableItemsContainer {
52 
53     private final SparseArray<ItemInfo> mHotseatItems = new SparseArray<>();
54     private List<ItemInfo> mPredictedItems = Collections.emptyList();
55 
56     private final TaskbarActivityContext mContext;
57     private final TaskbarView mContainer;
58 
59     // Initialized in init.
60     protected TaskbarControllers mControllers;
61 
62     // Used to defer any UI updates during the SUW unstash animation.
63     private boolean mDeferUpdatesForSUW;
64     private Runnable mDeferredUpdates;
65     private boolean mBindingItems = false;
66 
TaskbarModelCallbacks( TaskbarActivityContext context, TaskbarView container)67     public TaskbarModelCallbacks(
68             TaskbarActivityContext context, TaskbarView container) {
69         mContext = context;
70         mContainer = container;
71     }
72 
init(TaskbarControllers controllers)73     public void init(TaskbarControllers controllers) {
74         mControllers = controllers;
75     }
76 
77     @Override
startBinding()78     public void startBinding() {
79         mBindingItems = true;
80         mHotseatItems.clear();
81         mPredictedItems = Collections.emptyList();
82     }
83 
84     @Override
finishBindingItems(IntSet pagesBoundFirst)85     public void finishBindingItems(IntSet pagesBoundFirst) {
86         mBindingItems = 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     @Override
bindItemsUpdated(Set<ItemInfo> updates)119     public void bindItemsUpdated(Set<ItemInfo> updates) {
120         updateContainerItems(updates, mContext);
121     }
122 
123     @Override
mapOverItems(@onNull ItemOperator op)124     public View mapOverItems(@NonNull ItemOperator op) {
125         final int itemCount = mContainer.getChildCount();
126         for (int itemIdx = 0; itemIdx < itemCount; itemIdx++) {
127             View item = mContainer.getChildAt(itemIdx);
128             if (item.getTag() instanceof ItemInfo itemInfo && op.evaluate(itemInfo, item)) {
129                 return item;
130             }
131         }
132         return null;
133     }
134 
135     @Override
bindWorkspaceComponentsRemoved(Predicate<ItemInfo> matcher)136     public void bindWorkspaceComponentsRemoved(Predicate<ItemInfo> matcher) {
137         if (handleItemsRemoved(matcher)) {
138             commitItemsToUI();
139         }
140     }
141 
handleItemsRemoved(Predicate<ItemInfo> matcher)142     private boolean handleItemsRemoved(Predicate<ItemInfo> matcher) {
143         boolean modified = false;
144         for (int i = mHotseatItems.size() - 1; i >= 0; i--) {
145             if (matcher.test(mHotseatItems.valueAt(i))) {
146                 modified = true;
147                 mHotseatItems.removeAt(i);
148             }
149         }
150         return modified;
151     }
152 
153     @Override
bindItemsModified(List<ItemInfo> items)154     public void bindItemsModified(List<ItemInfo> items) {
155         boolean removed = handleItemsRemoved(ItemInfoMatcher.ofItems(items));
156         boolean added = handleItemsAdded(items);
157         if (removed || added) {
158             commitItemsToUI();
159         }
160     }
161 
162     @Override
bindExtraContainerItems(FixedContainerItems item)163     public void bindExtraContainerItems(FixedContainerItems item) {
164         if (item.containerId == Favorites.CONTAINER_HOTSEAT_PREDICTION) {
165             mPredictedItems = item.items;
166             commitItemsToUI();
167         } else if (item.containerId == Favorites.CONTAINER_PREDICTION) {
168             mControllers.taskbarAllAppsController.setPredictedApps(item.items);
169         }
170     }
171 
commitItemsToUI()172     private void commitItemsToUI() {
173         if (mBindingItems) {
174             return;
175         }
176 
177         ItemInfo[] hotseatItemInfos =
178                 new ItemInfo[mContext.getDeviceProfile().numShownHotseatIcons];
179         int predictionSize = mPredictedItems.size();
180         int predictionNextIndex = 0;
181 
182         for (int i = 0; i < hotseatItemInfos.length; i++) {
183             hotseatItemInfos[i] = mHotseatItems.get(i);
184             if (hotseatItemInfos[i] == null && predictionNextIndex < predictionSize) {
185                 hotseatItemInfos[i] = mPredictedItems.get(predictionNextIndex);
186                 hotseatItemInfos[i].screenId = i;
187                 predictionNextIndex++;
188             }
189         }
190 
191         final TaskbarRecentAppsController recentAppsController =
192                 mControllers.taskbarRecentAppsController;
193         hotseatItemInfos = recentAppsController.updateHotseatItemInfos(hotseatItemInfos);
194 
195         if (mDeferUpdatesForSUW) {
196             ItemInfo[] finalHotseatItemInfos = hotseatItemInfos;
197             mDeferredUpdates = () ->
198                     commitHotseatItemUpdates(finalHotseatItemInfos,
199                             recentAppsController.getShownTasks());
200         } else {
201             commitHotseatItemUpdates(hotseatItemInfos, recentAppsController.getShownTasks());
202         }
203     }
204 
commitHotseatItemUpdates( ItemInfo[] hotseatItemInfos, List<GroupTask> recentTasks)205     private void commitHotseatItemUpdates(
206             ItemInfo[] hotseatItemInfos, List<GroupTask> recentTasks) {
207         mContainer.updateItems(hotseatItemInfos, recentTasks);
208         mControllers.taskbarViewController.updateIconViewsRunningStates();
209         mControllers.taskbarPopupController.setHotseatInfosList(mHotseatItems);
210     }
211 
212     /**
213      * This is used to defer UI updates after SUW builds the unstash animation.
214      * @param defer if true, defers updates to the UI
215      *              if false, posts updates (if any) to the UI
216      */
setDeferUpdatesForSUW(boolean defer)217     public void setDeferUpdatesForSUW(boolean defer) {
218         mDeferUpdatesForSUW = defer;
219 
220         if (!mDeferUpdatesForSUW) {
221             if (mDeferredUpdates != null) {
222                 mContainer.post(mDeferredUpdates);
223                 mDeferredUpdates = null;
224             }
225         }
226     }
227 
228     /** Called when there's a change in running apps to update the UI. */
commitRunningAppsToUI()229     public void commitRunningAppsToUI() {
230         commitItemsToUI();
231     }
232 
233     @Override
bindDeepShortcutMap(HashMap<ComponentKey, Integer> deepShortcutMapCopy)234     public void bindDeepShortcutMap(HashMap<ComponentKey, Integer> deepShortcutMapCopy) {
235         mControllers.taskbarPopupController.setDeepShortcutMap(deepShortcutMapCopy);
236     }
237 
238     @UiThread
239     @Override
bindAllApplications(AppInfo[] apps, int flags, Map<PackageUserKey, Integer> packageUserKeytoUidMap)240     public void bindAllApplications(AppInfo[] apps, int flags,
241             Map<PackageUserKey, Integer> packageUserKeytoUidMap) {
242         Preconditions.assertUIThread();
243         mControllers.taskbarAllAppsController.setApps(apps, flags, packageUserKeytoUidMap);
244         mControllers.taskbarPopupController.setApps(apps);
245     }
246 
dumpLogs(String prefix, PrintWriter pw)247     protected void dumpLogs(String prefix, PrintWriter pw) {
248         pw.println(prefix + "TaskbarModelCallbacks:");
249 
250         pw.println(String.format("%s\thotseat items count=%s", prefix, mHotseatItems.size()));
251         if (mPredictedItems != null) {
252             pw.println(
253                     String.format("%s\tpredicted items count=%s", prefix, mPredictedItems.size()));
254         }
255         pw.println(String.format("%s\tmDeferUpdatesForSUW=%b", prefix, mDeferUpdatesForSUW));
256         pw.println(String.format("%s\tupdates pending=%b", prefix, (mDeferredUpdates != null)));
257     }
258 }
259