Add running apps icons to taskbar for desktop environment.

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: I2c839b6f35310d2d0fa98cc8d4a432eb1163861d
This commit is contained in:
Merissa Tan
2022-01-25 19:48:58 -08:00
parent 39853cc200
commit 2a607adc18
5 changed files with 99 additions and 17 deletions

View File

@@ -435,6 +435,7 @@ public class ShellTaskOrganizer extends TaskOrganizer implements
} }
notifyLocusVisibilityIfNeeded(info.getTaskInfo()); notifyLocusVisibilityIfNeeded(info.getTaskInfo());
notifyCompatUI(info.getTaskInfo(), listener); notifyCompatUI(info.getTaskInfo(), listener);
mRecentTasks.ifPresent(recentTasks -> recentTasks.onTaskAdded(info.getTaskInfo()));
} }
/** /**

View File

@@ -16,6 +16,8 @@
package com.android.wm.shell.recents; package com.android.wm.shell.recents;
import android.app.ActivityManager;
import com.android.wm.shell.recents.IRecentTasksListener; import com.android.wm.shell.recents.IRecentTasksListener;
import com.android.wm.shell.util.GroupedRecentTaskInfo; import com.android.wm.shell.util.GroupedRecentTaskInfo;
@@ -38,4 +40,9 @@ interface IRecentTasks {
* Gets the set of recent tasks. * Gets the set of recent tasks.
*/ */
GroupedRecentTaskInfo[] getRecentTasks(int maxNum, int flags, int userId) = 3; GroupedRecentTaskInfo[] getRecentTasks(int maxNum, int flags, int userId) = 3;
/**
* Gets the set of running tasks.
*/
ActivityManager.RunningTaskInfo[] getRunningTasks(int maxNum) = 4;
} }

View File

@@ -16,6 +16,8 @@
package com.android.wm.shell.recents; package com.android.wm.shell.recents;
import android.app.ActivityManager;
/** /**
* Listener interface that Launcher attaches to SystemUI to get split-screen callbacks. * Listener interface that Launcher attaches to SystemUI to get split-screen callbacks.
*/ */
@@ -25,4 +27,14 @@ oneway interface IRecentTasksListener {
* Called when the set of recent tasks change. * Called when the set of recent tasks change.
*/ */
void onRecentTasksChanged(); void onRecentTasksChanged();
/**
* Called when a running task appears.
*/
void onRunningTaskAppeared(in ActivityManager.RunningTaskInfo taskInfo);
/**
* Called when a running task vanishes.
*/
void onRunningTaskVanished(in ActivityManager.RunningTaskInfo taskInfo);
} }

View File

@@ -17,6 +17,7 @@
package com.android.wm.shell.recents; package com.android.wm.shell.recents;
import static android.app.ActivityTaskManager.INVALID_TASK_ID; import static android.app.ActivityTaskManager.INVALID_TASK_ID;
import static android.content.pm.PackageManager.FEATURE_PC;
import static com.android.wm.shell.common.ExecutorUtils.executeRemoteCallWithTaskPermission; import static com.android.wm.shell.common.ExecutorUtils.executeRemoteCallWithTaskPermission;
@@ -63,8 +64,9 @@ public class RecentTasksController implements TaskStackListenerCallback,
private final ShellExecutor mMainExecutor; private final ShellExecutor mMainExecutor;
private final TaskStackListenerImpl mTaskStackListener; private final TaskStackListenerImpl mTaskStackListener;
private final RecentTasks mImpl = new RecentTasksImpl(); private final RecentTasks mImpl = new RecentTasksImpl();
private IRecentTasksListener mListener;
private final boolean mIsDesktopMode;
private final ArrayList<Runnable> mCallbacks = new ArrayList<>();
// Mapping of split task ids, mappings are symmetrical (ie. if t1 is the taskid of a task in a // Mapping of split task ids, mappings are symmetrical (ie. if t1 is the taskid of a task in a
// pair, then mSplitTasks[t1] = t2, and mSplitTasks[t2] = t1) // pair, then mSplitTasks[t1] = t2, and mSplitTasks[t2] = t1)
private final SparseIntArray mSplitTasks = new SparseIntArray(); private final SparseIntArray mSplitTasks = new SparseIntArray();
@@ -95,6 +97,7 @@ public class RecentTasksController implements TaskStackListenerCallback,
RecentTasksController(Context context, TaskStackListenerImpl taskStackListener, RecentTasksController(Context context, TaskStackListenerImpl taskStackListener,
ShellExecutor mainExecutor) { ShellExecutor mainExecutor) {
mContext = context; mContext = context;
mIsDesktopMode = mContext.getPackageManager().hasSystemFeature(FEATURE_PC);
mTaskStackListener = taskStackListener; mTaskStackListener = taskStackListener;
mMainExecutor = mainExecutor; mMainExecutor = mainExecutor;
} }
@@ -176,10 +179,15 @@ public class RecentTasksController implements TaskStackListenerCallback,
notifyRecentTasksChanged(); notifyRecentTasksChanged();
} }
public void onTaskRemoved(TaskInfo taskInfo) { public void onTaskAdded(ActivityManager.RunningTaskInfo taskInfo) {
notifyRunningTaskAppeared(taskInfo);
}
public void onTaskRemoved(ActivityManager.RunningTaskInfo taskInfo) {
// Remove any split pairs associated with this task // Remove any split pairs associated with this task
removeSplitPair(taskInfo.taskId); removeSplitPair(taskInfo.taskId);
notifyRecentTasksChanged(); notifyRecentTasksChanged();
notifyRunningTaskVanished(taskInfo);
} }
public void onTaskWindowingModeChanged(TaskInfo taskInfo) { public void onTaskWindowingModeChanged(TaskInfo taskInfo) {
@@ -189,19 +197,50 @@ public class RecentTasksController implements TaskStackListenerCallback,
@VisibleForTesting @VisibleForTesting
void notifyRecentTasksChanged() { void notifyRecentTasksChanged() {
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENT_TASKS, "Notify recent tasks changed"); ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENT_TASKS, "Notify recent tasks changed");
for (int i = 0; i < mCallbacks.size(); i++) { if (mListener == null) {
mCallbacks.get(i).run(); return;
}
try {
mListener.onRecentTasksChanged();
} catch (RemoteException e) {
Slog.w(TAG, "Failed call notifyRecentTasksChanged", e);
} }
} }
private void registerRecentTasksListener(Runnable listener) { /**
if (!mCallbacks.contains(listener)) { * Notify the running task listener that a task appeared on desktop environment.
mCallbacks.add(listener); */
private void notifyRunningTaskAppeared(ActivityManager.RunningTaskInfo taskInfo) {
if (mListener == null || !mIsDesktopMode || taskInfo.realActivity == null) {
return;
}
try {
mListener.onRunningTaskAppeared(taskInfo);
} catch (RemoteException e) {
Slog.w(TAG, "Failed call onRunningTaskAppeared", e);
} }
} }
private void unregisterRecentTasksListener(Runnable listener) { /**
mCallbacks.remove(listener); * Notify the running task listener that a task was removed on desktop environment.
*/
private void notifyRunningTaskVanished(ActivityManager.RunningTaskInfo taskInfo) {
if (mListener == null || !mIsDesktopMode || taskInfo.realActivity == null) {
return;
}
try {
mListener.onRunningTaskVanished(taskInfo);
} catch (RemoteException e) {
Slog.w(TAG, "Failed call onRunningTaskVanished", e);
}
}
private void registerRecentTasksListener(IRecentTasksListener listener) {
mListener = listener;
}
private void unregisterRecentTasksListener() {
mListener = null;
} }
@VisibleForTesting @VisibleForTesting
@@ -280,19 +319,28 @@ public class RecentTasksController implements TaskStackListenerCallback,
private RecentTasksController mController; private RecentTasksController mController;
private final SingleInstanceRemoteListener<RecentTasksController, private final SingleInstanceRemoteListener<RecentTasksController,
IRecentTasksListener> mListener; IRecentTasksListener> mListener;
private final Runnable mRecentTasksListener = private final IRecentTasksListener mRecentTasksListener = new IRecentTasksListener.Stub() {
new Runnable() {
@Override @Override
public void run() { public void onRecentTasksChanged() throws RemoteException {
mListener.call(l -> l.onRecentTasksChanged()); mListener.call(l -> l.onRecentTasksChanged());
} }
@Override
public void onRunningTaskAppeared(ActivityManager.RunningTaskInfo taskInfo) {
mListener.call(l -> l.onRunningTaskAppeared(taskInfo));
}
@Override
public void onRunningTaskVanished(ActivityManager.RunningTaskInfo taskInfo) {
mListener.call(l -> l.onRunningTaskVanished(taskInfo));
}
}; };
public IRecentTasksImpl(RecentTasksController controller) { public IRecentTasksImpl(RecentTasksController controller) {
mController = controller; mController = controller;
mListener = new SingleInstanceRemoteListener<>(controller, mListener = new SingleInstanceRemoteListener<>(controller,
c -> c.registerRecentTasksListener(mRecentTasksListener), c -> c.registerRecentTasksListener(mRecentTasksListener),
c -> c.unregisterRecentTasksListener(mRecentTasksListener)); c -> c.unregisterRecentTasksListener());
} }
/** /**
@@ -331,5 +379,16 @@ public class RecentTasksController implements TaskStackListenerCallback,
true /* blocking */); true /* blocking */);
return out[0]; return out[0];
} }
@Override
public ActivityManager.RunningTaskInfo[] getRunningTasks(int maxNum) {
final ActivityManager.RunningTaskInfo[][] tasks =
new ActivityManager.RunningTaskInfo[][] {null};
executeRemoteCallWithTaskPermission(mController, "getRunningTasks",
(controller) -> tasks[0] = ActivityTaskManager.getInstance().getTasks(maxNum)
.toArray(new ActivityManager.RunningTaskInfo[0]),
true /* blocking */);
return tasks[0];
}
} }
} }

View File

@@ -30,11 +30,13 @@ import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.spy; import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times; import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static java.lang.Integer.MAX_VALUE; import static java.lang.Integer.MAX_VALUE;
import android.app.ActivityManager; import android.app.ActivityManager;
import android.content.Context; import android.content.Context;
import android.content.pm.PackageManager;
import android.graphics.Rect; import android.graphics.Rect;
import android.view.SurfaceControl; import android.view.SurfaceControl;
@@ -77,6 +79,7 @@ public class RecentTasksControllerTest extends ShellTestCase {
@Before @Before
public void setUp() { public void setUp() {
mMainExecutor = new TestShellExecutor(); mMainExecutor = new TestShellExecutor();
when(mContext.getPackageManager()).thenReturn(mock(PackageManager.class));
mRecentTasksController = spy(new RecentTasksController(mContext, mTaskStackListener, mRecentTasksController = spy(new RecentTasksController(mContext, mTaskStackListener,
mMainExecutor)); mMainExecutor));
mShellTaskOrganizer = new ShellTaskOrganizer(mMainExecutor, mContext, mShellTaskOrganizer = new ShellTaskOrganizer(mMainExecutor, mContext,