Update taskbar to add extra hotseat items instead of recent apps

Removes recents-related code including the divider between it and
hotseat.

Test: manually on device

Fixes: 184366189
Bug: 184789479
Bug: 171917176
Change-Id: I7776c98659ded70f53a49befddcd23c8353c6440
This commit is contained in:
Tony Wickham 2021-04-07 15:24:10 -07:00
parent b87f3cdc1c
commit be282e9bc8
8 changed files with 5 additions and 344 deletions

View File

@ -1,21 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- 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.
-->
<View
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="@dimen/taskbar_divider_thickness"
android:layout_height="@dimen/taskbar_divider_height"
android:background="@color/taskbar_divider" />

View File

@ -27,5 +27,4 @@
<!-- Taskbar -->
<color name="taskbar_background">#101010</color>
<color name="taskbar_divider">#C0C0C0</color>
</resources>

View File

@ -134,7 +134,5 @@
<dimen name="taskbar_icon_drag_icon_size">54dp</dimen>
<!-- Note that this applies to both sides of all icons, so visible space is double this. -->
<dimen name="taskbar_icon_spacing">8dp</dimen>
<dimen name="taskbar_divider_thickness">1dp</dimen>
<dimen name="taskbar_divider_height">32dp</dimen>
<dimen name="taskbar_folder_margin">16dp</dimen>
</resources>

View File

@ -108,6 +108,7 @@ public abstract class BaseQuickstepLauncher extends Launcher
SysUINavigationMode.INSTANCE.get(this).removeModeChangeListener(this);
if (mTaskbarController != null) {
mTaskbarController.cleanup();
mTaskbarController = null;
}
super.onDestroy();

View File

@ -25,7 +25,6 @@ import static com.android.systemui.shared.system.WindowManagerWrapper.ITYPE_EXTR
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.app.ActivityOptions;
import android.content.ComponentName;
import android.graphics.PixelFormat;
import android.graphics.Point;
import android.graphics.Rect;
@ -56,9 +55,6 @@ import com.android.systemui.shared.recents.model.Task;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.WindowManagerWrapper;
import java.util.ArrayList;
import java.util.List;
/**
* Interfaces with Launcher/WindowManager/SystemUI to determine what to show in TaskbarView.
*/
@ -76,17 +72,11 @@ public class TaskbarController {
private final TaskbarStateHandler mTaskbarStateHandler;
private final TaskbarAnimationController mTaskbarAnimationController;
private final TaskbarHotseatController mHotseatController;
private final TaskbarRecentsController mRecentsController;
private final TaskbarDragController mDragController;
// Initialized in init().
private WindowManager.LayoutParams mWindowLayoutParams;
// Contains all loaded Tasks, not yet deduped from Hotseat items.
private List<Task> mLatestLoadedRecentTasks;
// Contains all loaded Hotseat items.
private ItemInfo[] mLatestLoadedHotseatItems;
private @Nullable Animator mAnimator;
private boolean mIsAnimatingToLauncher;
@ -106,8 +96,6 @@ public class TaskbarController {
createTaskbarAnimationControllerCallbacks());
mHotseatController = new TaskbarHotseatController(mLauncher,
createTaskbarHotseatControllerCallbacks());
mRecentsController = new TaskbarRecentsController(mLauncher,
createTaskbarRecentsControllerCallbacks());
mDragController = new TaskbarDragController(mLauncher);
}
@ -220,24 +208,6 @@ public class TaskbarController {
@Override
public void updateHotseatItems(ItemInfo[] hotseatItemInfos) {
mTaskbarViewInApp.updateHotseatItems(hotseatItemInfos);
mLatestLoadedHotseatItems = hotseatItemInfos;
dedupeAndUpdateRecentItems();
}
};
}
private TaskbarRecentsControllerCallbacks createTaskbarRecentsControllerCallbacks() {
return new TaskbarRecentsControllerCallbacks() {
@Override
public void updateRecentItems(ArrayList<Task> recentTasks) {
mLatestLoadedRecentTasks = recentTasks;
dedupeAndUpdateRecentItems();
}
@Override
public void updateRecentTaskAtIndex(int taskIndex, Task task) {
mTaskbarViewInApp.updateRecentTaskAtIndex(taskIndex, task);
mTaskbarViewOnHome.updateRecentTaskAtIndex(taskIndex, task);
}
};
}
@ -246,16 +216,13 @@ public class TaskbarController {
* Initializes the Taskbar, including adding it to the screen.
*/
public void init() {
mTaskbarViewInApp.init(mHotseatController.getNumHotseatIcons(),
mRecentsController.getNumRecentIcons());
mTaskbarViewOnHome.init(mHotseatController.getNumHotseatIcons(),
mRecentsController.getNumRecentIcons());
mTaskbarViewInApp.init(mHotseatController.getNumHotseatIcons());
mTaskbarViewOnHome.init(mHotseatController.getNumHotseatIcons());
mTaskbarContainerView.init(mTaskbarViewInApp);
addToWindowManager();
mTaskbarStateHandler.setTaskbarCallbacks(createTaskbarStateHandlerCallbacks());
mTaskbarAnimationController.init();
mHotseatController.init();
mRecentsController.init();
setWhichTaskbarViewIsVisible(mLauncher.hasBeenResumed()
? mTaskbarViewOnHome
@ -292,7 +259,6 @@ public class TaskbarController {
mTaskbarStateHandler.setTaskbarCallbacks(null);
mTaskbarAnimationController.cleanup();
mHotseatController.cleanup();
mRecentsController.cleanup();
setWhichTaskbarViewIsVisible(null);
}
@ -425,53 +391,6 @@ public class TaskbarController {
return mTaskbarViewInApp.isDraggingItem() || mTaskbarViewOnHome.isDraggingItem();
}
private void dedupeAndUpdateRecentItems() {
if (mLatestLoadedRecentTasks == null || mLatestLoadedHotseatItems == null) {
return;
}
final int numRecentIcons = mRecentsController.getNumRecentIcons();
// From most recent to least recently opened.
List<Task> dedupedTasksInDescendingOrder = new ArrayList<>();
for (int i = mLatestLoadedRecentTasks.size() - 1; i >= 0; i--) {
Task task = mLatestLoadedRecentTasks.get(i);
boolean isTaskInHotseat = false;
for (ItemInfo hotseatItem : mLatestLoadedHotseatItems) {
if (hotseatItem == null) {
continue;
}
ComponentName hotseatActivity = hotseatItem.getTargetComponent();
if (hotseatActivity != null && task.key.sourceComponent.getPackageName()
.equals(hotseatActivity.getPackageName())) {
isTaskInHotseat = true;
break;
}
}
if (!isTaskInHotseat) {
dedupedTasksInDescendingOrder.add(task);
if (dedupedTasksInDescendingOrder.size() == numRecentIcons) {
break;
}
}
}
// TaskbarView expects an array of all the recent tasks to show, in the order to show them.
// So we create an array of the proper size, then fill it in such that the most recent items
// are at the end. If there aren't enough elements to fill the array, leave them null.
Task[] tasksArray = new Task[numRecentIcons];
for (int i = 0; i < tasksArray.length; i++) {
Task task = i >= dedupedTasksInDescendingOrder.size()
? null
: dedupedTasksInDescendingOrder.get(i);
tasksArray[tasksArray.length - 1 - i] = task;
}
mTaskbarViewInApp.updateRecentTasks(tasksArray);
mTaskbarViewOnHome.updateRecentTasks(tasksArray);
mRecentsController.loadIconsForTasks(tasksArray);
}
/**
* @return Whether the given View is in the same window as Taskbar.
*/
@ -573,12 +492,4 @@ public class TaskbarController {
protected interface TaskbarHotseatControllerCallbacks {
void updateHotseatItems(ItemInfo[] hotseatItemInfos);
}
/**
* Contains methods that TaskbarRecentsController can call to interface with TaskbarController.
*/
protected interface TaskbarRecentsControllerCallbacks {
void updateRecentItems(ArrayList<Task> recentTasks);
void updateRecentTaskAtIndex(int taskIndex, Task task);
}
}

View File

@ -1,120 +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 com.android.launcher3.BaseQuickstepLauncher;
import com.android.quickstep.RecentsModel;
import com.android.quickstep.util.CancellableTask;
import com.android.systemui.shared.recents.model.Task;
import com.android.systemui.shared.system.TaskStackChangeListener;
import com.android.systemui.shared.system.TaskStackChangeListeners;
import java.util.ArrayList;
/**
* Works with TaskbarController to update the TaskbarView's Recent items.
*/
public class TaskbarRecentsController {
private final int mNumRecentIcons = 2;
private final BaseQuickstepLauncher mLauncher;
private final TaskbarController.TaskbarRecentsControllerCallbacks mTaskbarCallbacks;
private final RecentsModel mRecentsModel;
private final TaskStackChangeListener mTaskStackChangeListener = new TaskStackChangeListener() {
@Override
public void onTaskStackChanged() {
reloadRecentTasksIfNeeded();
}
};
// TODO: add TaskbarVisualsChangedListener as well (for calendar/clock?)
// Used to keep track of the last requested task list id, so that we do not request to load the
// tasks again if we have already requested it and the task list has not changed
private int mTaskListChangeId = -1;
// The current background requests to load the task icons
private CancellableTask[] mIconLoadRequests = new CancellableTask[mNumRecentIcons];
private boolean mIsAlive;
public TaskbarRecentsController(BaseQuickstepLauncher launcher,
TaskbarController.TaskbarRecentsControllerCallbacks taskbarCallbacks) {
mLauncher = launcher;
mTaskbarCallbacks = taskbarCallbacks;
mRecentsModel = RecentsModel.INSTANCE.get(mLauncher);
}
protected void init() {
mIsAlive = true;
TaskStackChangeListeners.getInstance().registerTaskStackListener(mTaskStackChangeListener);
reloadRecentTasksIfNeeded();
}
protected void cleanup() {
mIsAlive = false;
TaskStackChangeListeners.getInstance().unregisterTaskStackListener(
mTaskStackChangeListener);
cancelAllPendingIconLoadTasks();
}
private void reloadRecentTasksIfNeeded() {
if (!mRecentsModel.isTaskListValid(mTaskListChangeId)) {
mTaskListChangeId = mRecentsModel.getTasks(this::onRecentTasksChanged);
}
}
private void cancelAllPendingIconLoadTasks() {
for (int i = 0; i < mIconLoadRequests.length; i++) {
if (mIconLoadRequests[i] != null) {
mIconLoadRequests[i].cancel();
}
mIconLoadRequests[i] = null;
}
}
private void onRecentTasksChanged(ArrayList<Task> tasks) {
if (mIsAlive) {
mTaskbarCallbacks.updateRecentItems(tasks);
}
}
/**
* For each Task, loads its icon from the cache in the background, then calls
* {@link TaskbarController.TaskbarRecentsControllerCallbacks#updateRecentTaskAtIndex}.
*/
protected void loadIconsForTasks(Task[] tasks) {
cancelAllPendingIconLoadTasks();
for (int i = 0; i < tasks.length; i++) {
Task task = tasks[i];
if (task == null) {
continue;
}
final int taskIndex = i;
mIconLoadRequests[i] = mRecentsModel.getIconCache().updateIconInBackground(
task, updatedTask -> onTaskIconLoaded(task, taskIndex));
}
}
private void onTaskIconLoaded(Task task, int taskIndex) {
mTaskbarCallbacks.updateRecentTaskAtIndex(taskIndex, task);
}
protected int getNumRecentIcons() {
return mNumRecentIcons;
}
}

View File

@ -25,7 +25,6 @@ import android.graphics.Canvas;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.DragEvent;
import android.view.MotionEvent;
@ -47,7 +46,6 @@ import com.android.launcher3.model.data.FolderInfo;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.model.data.WorkspaceItemInfo;
import com.android.launcher3.views.ActivityContext;
import com.android.systemui.shared.recents.model.Task;
/**
* Hosts the Taskbar content such as Hotseat and Recent Apps. Drawn on top of other apps.
@ -55,8 +53,6 @@ import com.android.systemui.shared.recents.model.Task;
public class TaskbarView extends LinearLayout implements FolderIcon.FolderIconParent, Insettable {
private final ColorDrawable mBackgroundDrawable;
private final int mDividerWidth;
private final int mDividerHeight;
private final int mIconTouchSize;
private final boolean mIsRtl;
private final int mTouchSlop;
@ -74,9 +70,6 @@ public class TaskbarView extends LinearLayout implements FolderIcon.FolderIconPa
private LayoutTransition mLayoutTransition;
private int mHotseatStartIndex;
private int mHotseatEndIndex;
private View mHotseatRecentsDivider;
private int mRecentsStartIndex;
private int mRecentsEndIndex;
// Delegate touches to the closest view if within mIconTouchSize.
private boolean mDelegateTargeted;
@ -105,8 +98,6 @@ public class TaskbarView extends LinearLayout implements FolderIcon.FolderIconPa
Resources resources = getResources();
mBackgroundDrawable = (ColorDrawable) getBackground();
mDividerWidth = resources.getDimensionPixelSize(R.dimen.taskbar_divider_thickness);
mDividerHeight = resources.getDimensionPixelSize(R.dimen.taskbar_divider_height);
mIconTouchSize = resources.getDimensionPixelSize(R.dimen.taskbar_icon_touch_size);
mIsRtl = Utilities.isRtl(resources);
mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
@ -119,18 +110,11 @@ public class TaskbarView extends LinearLayout implements FolderIcon.FolderIconPa
mItemMarginLeftRight = Math.round(mItemMarginLeftRight * mNonIconScale);
}
protected void init(int numHotseatIcons, int numRecentIcons) {
protected void init(int numHotseatIcons) {
mHotseatStartIndex = 0;
mHotseatEndIndex = mHotseatStartIndex + numHotseatIcons - 1;
updateHotseatItems(new ItemInfo[numHotseatIcons]);
int dividerIndex = mHotseatEndIndex + 1;
mHotseatRecentsDivider = addDivider(dividerIndex);
mRecentsStartIndex = dividerIndex + 1;
mRecentsEndIndex = mRecentsStartIndex + numRecentIcons - 1;
updateRecentTasks(new Task[numRecentIcons]);
mLayoutTransition = new LayoutTransition();
addUpdateListenerForAllLayoutTransitions(() -> {
if (getLayoutTransition() == mLayoutTransition) {
@ -165,7 +149,6 @@ public class TaskbarView extends LinearLayout implements FolderIcon.FolderIconPa
endAllLayoutTransitionAnimators();
setLayoutTransition(null);
removeAllViews();
mHotseatRecentsDivider = null;
}
private void endAllLayoutTransitionAnimators() {
@ -248,8 +231,6 @@ public class TaskbarView extends LinearLayout implements FolderIcon.FolderIconPa
}
updateHotseatItemVisibility(hotseatView);
}
updateHotseatRecentsDividerVisibility();
}
protected void updateHotseatItemsVisibility() {
@ -273,95 +254,6 @@ public class TaskbarView extends LinearLayout implements FolderIcon.FolderIconPa
}
}
private View addDivider(int dividerIndex) {
View divider = inflate(R.layout.taskbar_divider);
LayoutParams lp = new LayoutParams(mDividerWidth, mDividerHeight);
lp.setMargins(mItemMarginLeftRight, 0, mItemMarginLeftRight, 0);
divider.setScaleX(mNonIconScale);
divider.setScaleY(mNonIconScale);
addView(divider, dividerIndex, lp);
return divider;
}
/**
* Inflates/binds the Recents items to show in the Taskbar given their Tasks.
*/
protected void updateRecentTasks(Task[] tasks) {
for (int i = 0; i < tasks.length; i++) {
Task task = tasks[i];
int recentsIndex = mRecentsStartIndex + i;
View recentsView = getChildAt(recentsIndex);
// Inflate empty icon Views.
if (recentsView == null) {
BubbleTextView btv = (BubbleTextView) inflate(R.layout.taskbar_app_icon);
LayoutParams lp = new LayoutParams(btv.getIconSize(), btv.getIconSize());
lp.setMargins(mItemMarginLeftRight, 0, mItemMarginLeftRight, 0);
recentsView = btv;
addView(recentsView, recentsIndex, lp);
}
// Apply the Task, or hide the view if there is none for a given index.
if (recentsView instanceof BubbleTextView && task != null) {
applyTaskToBubbleTextView((BubbleTextView) recentsView, task);
recentsView.setVisibility(VISIBLE);
recentsView.setOnClickListener(mControllerCallbacks.getItemOnClickListener());
recentsView.setOnLongClickListener(
mControllerCallbacks.getItemOnLongClickListener());
} else {
recentsView.setVisibility(GONE);
recentsView.setOnClickListener(null);
recentsView.setOnLongClickListener(null);
}
}
updateHotseatRecentsDividerVisibility();
}
private void applyTaskToBubbleTextView(BubbleTextView btv, Task task) {
if (task.icon != null) {
Drawable icon = task.icon.getConstantState().newDrawable().mutate();
btv.applyIconAndLabel(icon, task.titleDescription);
}
btv.setTag(task);
}
protected void updateRecentTaskAtIndex(int taskIndex, Task task) {
View taskView = getChildAt(mRecentsStartIndex + taskIndex);
if (taskView instanceof BubbleTextView) {
applyTaskToBubbleTextView((BubbleTextView) taskView, task);
}
}
/**
* Make the divider VISIBLE between the Hotseat and Recents if there is at least one icon in
* each, otherwise make it GONE.
*/
private void updateHotseatRecentsDividerVisibility() {
if (mHotseatRecentsDivider == null) {
return;
}
boolean hasAtLeastOneHotseatItem = false;
for (int i = mHotseatStartIndex; i <= mHotseatEndIndex; i++) {
if (getChildAt(i).getVisibility() != GONE) {
hasAtLeastOneHotseatItem = true;
break;
}
}
boolean hasAtLeastOneRecentItem = false;
for (int i = mRecentsStartIndex; i <= mRecentsEndIndex; i++) {
if (getChildAt(i).getVisibility() != GONE) {
hasAtLeastOneRecentItem = true;
break;
}
}
mHotseatRecentsDivider.setVisibility(hasAtLeastOneHotseatItem && hasAtLeastOneRecentItem
? VISIBLE : GONE);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
boolean handled = delegateTouchIfNecessary(event);

View File

@ -149,6 +149,7 @@ public class SettingsChangeLogger implements
SharedPreferences prefs = getPrefs(mContext);
StatsLogManager.LauncherEvent gridSizeChangedEvent = null;
// TODO(b/184981523): This doesn't work for 2-panel grid, which has 6 hotseat icons
switch (prefs.getInt(KEY_MIGRATION_SRC_HOTSEAT_COUNT, -1)) {
case 5:
gridSizeChangedEvent = LAUNCHER_GRID_SIZE_5;