501ac7242d
This CL adds app icons for launched/running apps to the Launcher taskbar hotseat. When the activity is closed, the app icon is removed. The apps that are added to the taskbar on boot are never removed. Recall: http://recall/clips/ad6d3cfc-7358-4b37-846e-de843ad3000d Bug: 183906774 Test: Launch an app and verify the app icon is added on the taskbar. Close the app and verify the icon is removed from the taskbar. Test: Switch navigation modes on the emulator and ensure that running app icons are added to the taskbar after it is reinitialized. Test: atest NexusLauncherTests:com.android.quickstep.RecentTasksListTest RecentTasksControllerTest Change-Id: Ieaaf001530b5778871fb7a8d18cdcaa1ccbf0e31
246 lines
8.1 KiB
Java
246 lines
8.1 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 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.quickstep.RecentsModel;
|
|
|
|
import java.io.PrintWriter;
|
|
import java.util.ArrayList;
|
|
import java.util.Collections;
|
|
import java.util.HashMap;
|
|
import java.util.HashSet;
|
|
import java.util.List;
|
|
|
|
/**
|
|
* Launcher model Callbacks for rendering taskbar.
|
|
*/
|
|
public class TaskbarModelCallbacks implements
|
|
BgDataModel.Callbacks, LauncherBindableItemsContainer, RecentsModel.RunningTasksListener {
|
|
|
|
private final SparseArray<ItemInfo> mHotseatItems = new SparseArray<>();
|
|
private List<ItemInfo> mPredictedItems = Collections.emptyList();
|
|
|
|
private final TaskbarActivityContext mContext;
|
|
private final TaskbarView mContainer;
|
|
|
|
// Initialized in init.
|
|
private TaskbarControllers mControllers;
|
|
|
|
public TaskbarModelCallbacks(
|
|
TaskbarActivityContext context, TaskbarView container) {
|
|
mContext = context;
|
|
mContainer = container;
|
|
}
|
|
|
|
public void init(TaskbarControllers controllers) {
|
|
mControllers = controllers;
|
|
if (mControllers.taskbarRecentAppsController.isEnabled()) {
|
|
RecentsModel.INSTANCE.get(mContext).registerRunningTasksListener(this);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Unregisters listeners in this class.
|
|
*/
|
|
public void unregisterListeners() {
|
|
RecentsModel.INSTANCE.get(mContext).unregisterRunningTasksListener();
|
|
}
|
|
|
|
@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(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();
|
|
} 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;
|
|
|
|
boolean isHotseatEmpty = true;
|
|
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++;
|
|
}
|
|
if (hotseatItemInfos[i] != null) {
|
|
isHotseatEmpty = false;
|
|
}
|
|
}
|
|
hotseatItemInfos = mControllers.taskbarRecentAppsController
|
|
.updateHotseatItemInfos(hotseatItemInfos);
|
|
mContainer.updateHotseatItems(hotseatItemInfos);
|
|
|
|
final boolean finalIsHotseatEmpty = isHotseatEmpty;
|
|
mControllers.runAfterInit(() -> {
|
|
mControllers.taskbarStashController.updateStateForFlag(
|
|
TaskbarStashController.FLAG_STASHED_IN_APP_EMPTY, finalIsHotseatEmpty);
|
|
mControllers.taskbarStashController.applyState();
|
|
});
|
|
}
|
|
|
|
@Override
|
|
public void onRunningTasksChanged() {
|
|
updateRunningApps();
|
|
}
|
|
|
|
/** Called when there's a change in running apps to update the UI. */
|
|
public void commitRunningAppsToUI() {
|
|
commitItemsToUI();
|
|
}
|
|
|
|
/** Call TaskbarRecentAppsController to update running apps with mHotseatItems. */
|
|
public void updateRunningApps() {
|
|
mControllers.taskbarRecentAppsController.updateRunningApps(mHotseatItems);
|
|
}
|
|
|
|
@Override
|
|
public void bindDeepShortcutMap(HashMap<ComponentKey, Integer> deepShortcutMapCopy) {
|
|
mControllers.taskbarPopupController.setDeepShortcutMap(deepShortcutMapCopy);
|
|
}
|
|
|
|
@Override
|
|
public void bindAllApplications(AppInfo[] apps, int flags) {
|
|
mControllers.taskbarAllAppsController.setApps(apps, flags);
|
|
mControllers.taskbarRecentAppsController.setApps(apps);
|
|
}
|
|
|
|
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()));
|
|
}
|
|
}
|
|
}
|