From 3e73749c1374986695c8db2b379be8e347dd162d Mon Sep 17 00:00:00 2001 From: Vinit Nayak Date: Wed, 24 Jul 2019 13:03:15 -0700 Subject: [PATCH] Create general callback for changes to RecentTaskList New callback called whenever a user visible task is added or removed to the recents list. This results in less work by updating only when recent task list changes instead of listening for active task list changes. Test: atest RecentTasksTest fixes: 111077107 Change-Id: I9acf13762d0c79bfde90b64fa5e0edaf882068cc --- core/java/android/app/ITaskStackListener.aidl | 5 +++ core/java/android/app/TaskStackListener.java | 4 ++ core/java/android/util/LruCache.java | 3 +- .../shared/recents/model/TaskKeyCache.java | 12 ++++++ .../system/TaskStackChangeListener.java | 5 +++ .../system/TaskStackChangeListeners.java | 12 ++++++ .../notification/InstantAppNotifier.java | 10 ----- .../com/android/server/wm/RecentTasks.java | 7 +++- .../wm/TaskChangeNotificationController.java | 17 ++++++++ .../android/server/wm/ActivityTestsBase.java | 1 + .../android/server/wm/RecentTasksTest.java | 42 +++++++++++++++++++ 11 files changed, 106 insertions(+), 12 deletions(-) diff --git a/core/java/android/app/ITaskStackListener.aidl b/core/java/android/app/ITaskStackListener.aidl index 650147b45bd24..61867ea737e77 100644 --- a/core/java/android/app/ITaskStackListener.aidl +++ b/core/java/android/app/ITaskStackListener.aidl @@ -185,4 +185,9 @@ oneway interface ITaskStackListener { * @param newDisplayId id of the new display. */ void onTaskDisplayChanged(int taskId, int newDisplayId); + + /** + * Called when any additions or deletions to the recent tasks list have been made. + */ + void onRecentTaskListUpdated(); } diff --git a/core/java/android/app/TaskStackListener.java b/core/java/android/app/TaskStackListener.java index b63feb590ad13..e3a0e11c3c685 100644 --- a/core/java/android/app/TaskStackListener.java +++ b/core/java/android/app/TaskStackListener.java @@ -182,4 +182,8 @@ public abstract class TaskStackListener extends ITaskStackListener.Stub { @Override public void onTaskDisplayChanged(int taskId, int newDisplayId) throws RemoteException { } + + @Override + public void onRecentTaskListUpdated() throws RemoteException { + } } diff --git a/core/java/android/util/LruCache.java b/core/java/android/util/LruCache.java index f04e7cbc9e8fc..3cbf727d7718a 100644 --- a/core/java/android/util/LruCache.java +++ b/core/java/android/util/LruCache.java @@ -17,6 +17,7 @@ package android.util; import android.annotation.UnsupportedAppUsage; + import java.util.LinkedHashMap; import java.util.Map; @@ -260,7 +261,7 @@ public class LruCache { * @param evicted true if the entry is being removed to make space, false * if the removal was caused by a {@link #put} or {@link #remove}. * @param newValue the new value for {@code key}, if it exists. If non-null, - * this removal was caused by a {@link #put}. Otherwise it was caused by + * this removal was caused by a {@link #put} or a {@link #get}. Otherwise it was caused by * an eviction or a {@link #remove}. */ protected void entryRemoved(boolean evicted, K key, V oldValue, V newValue) {} diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/TaskKeyCache.java b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/TaskKeyCache.java index 342cb75b2c14f..8a244bf81c7cc 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/TaskKeyCache.java +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/TaskKeyCache.java @@ -21,6 +21,9 @@ import android.util.SparseArray; import com.android.systemui.shared.recents.model.Task.TaskKey; +import java.util.ArrayList; +import java.util.Collection; + /** * Base class for both strong and LRU task key cache. */ @@ -76,6 +79,15 @@ public abstract class TaskKeyCache { mKeys.remove(key.id); } + /** @return {@link Collection} of {@link TaskKey} */ + public Collection getValues() { + Collection result = new ArrayList<>(mKeys.size()); + for (int i = 0; i < mKeys.size(); i++) { + result.add(mKeys.valueAt(i)); + } + return result; + } + /** Removes all the entries in the cache. */ public final synchronized void evictAll() { evictAllCache(); diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListener.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListener.java index c215d0fc13d64..77571613f6af2 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListener.java +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListener.java @@ -94,6 +94,11 @@ public abstract class TaskStackChangeListener { */ public void onTaskDisplayChanged(int taskId, int newDisplayId) { } + /** + * Called when any additions or deletions to the recent tasks list have been made. + */ + public void onRecentTaskListUpdated() { } + /** * Checks that the current user matches the process. Since * {@link android.app.ITaskStackListener} is not multi-user aware, handlers of diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListeners.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListeners.java index d570a586f9613..a7f4396fabed8 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListeners.java +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListeners.java @@ -213,6 +213,11 @@ public class TaskStackChangeListeners extends TaskStackListener { mHandler.obtainMessage(H.ON_TASK_DISPLAY_CHANGED, taskId, newDisplayId).sendToTarget(); } + @Override + public void onRecentTaskListUpdated() throws RemoteException { + mHandler.obtainMessage(H.ON_TASK_LIST_UPDATED).sendToTarget(); + } + private final class H extends Handler { private static final int ON_TASK_STACK_CHANGED = 1; private static final int ON_TASK_SNAPSHOT_CHANGED = 2; @@ -234,6 +239,7 @@ public class TaskStackChangeListeners extends TaskStackListener { private static final int ON_BACK_PRESSED_ON_TASK_ROOT = 18; private static final int ON_SINGLE_TASK_DISPLAY_DRAWN = 19; private static final int ON_TASK_DISPLAY_CHANGED = 20; + private static final int ON_TASK_LIST_UPDATED = 21; public H(Looper looper) { @@ -382,6 +388,12 @@ public class TaskStackChangeListeners extends TaskStackListener { } break; } + case ON_TASK_LIST_UPDATED: { + for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) { + mTaskStackListeners.get(i).onRecentTaskListUpdated(); + } + break; + } } } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java index c67512c119225..f3201ec73d639 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java @@ -54,7 +54,6 @@ import com.android.systemui.R; import com.android.systemui.SysUiServiceProvider; import com.android.systemui.SystemUI; import com.android.systemui.UiOffloadThread; -import com.android.systemui.shared.system.TaskStackChangeListener; import com.android.systemui.statusbar.CommandQueue; import com.android.systemui.statusbar.policy.KeyguardMonitor; import com.android.systemui.util.NotificationChannels; @@ -138,15 +137,6 @@ public class InstantAppNotifier extends SystemUI } }; - private final TaskStackChangeListener mTaskListener = - new TaskStackChangeListener() { - @Override - public void onTaskStackChanged() { - // Listen for changes to stacks and then check which instant apps are - // foreground. - updateForegroundInstantApps(); - } - }; private void updateForegroundInstantApps() { NotificationManager noMan = mContext.getSystemService(NotificationManager.class); diff --git a/services/core/java/com/android/server/wm/RecentTasks.java b/services/core/java/com/android/server/wm/RecentTasks.java index 541a8bbc88656..fb6b5da87f2d6 100644 --- a/services/core/java/com/android/server/wm/RecentTasks.java +++ b/services/core/java/com/android/server/wm/RecentTasks.java @@ -126,6 +126,7 @@ class RecentTasks { // iterating through the recents list private static final ActivityInfo NO_ACTIVITY_INFO_TOKEN = new ActivityInfo(); private static final ApplicationInfo NO_APPLICATION_INFO_TOKEN = new ApplicationInfo(); + private TaskChangeNotificationController mTaskNotificationController; /** * Callbacks made when manipulating the list. @@ -228,6 +229,7 @@ class RecentTasks { mTaskPersister = taskPersister; mGlobalMaxNumTasks = ActivityTaskManager.getMaxRecentTasksStatic(); mHasVisibleRecentTasks = true; + mTaskNotificationController = service.getTaskChangeNotificationController(); } RecentTasks(ActivityTaskManagerService service, ActivityStackSupervisor stackSupervisor) { @@ -238,6 +240,7 @@ class RecentTasks { mTaskPersister = new TaskPersister(systemDir, stackSupervisor, service, this, stackSupervisor.mPersisterQueue); mGlobalMaxNumTasks = ActivityTaskManager.getMaxRecentTasksStatic(); + mTaskNotificationController = service.getTaskChangeNotificationController(); mHasVisibleRecentTasks = res.getBoolean(com.android.internal.R.bool.config_hasRecents); loadParametersFromResources(res); } @@ -298,7 +301,7 @@ class RecentTasks { // Resume trimming tasks trimInactiveRecentTasks(); - mService.getTaskChangeNotificationController().notifyTaskStackChanged(); + mTaskNotificationController.notifyTaskStackChanged(); } /** @@ -427,12 +430,14 @@ class RecentTasks { for (int i = 0; i < mCallbacks.size(); i++) { mCallbacks.get(i).onRecentTaskAdded(task); } + mTaskNotificationController.notifyTaskListUpdated(); } private void notifyTaskRemoved(TaskRecord task, boolean wasTrimmed, boolean killProcess) { for (int i = 0; i < mCallbacks.size(); i++) { mCallbacks.get(i).onRecentTaskRemoved(task, wasTrimmed, killProcess); } + mTaskNotificationController.notifyTaskListUpdated(); } /** diff --git a/services/core/java/com/android/server/wm/TaskChangeNotificationController.java b/services/core/java/com/android/server/wm/TaskChangeNotificationController.java index f776062b31a11..c2c4767419638 100644 --- a/services/core/java/com/android/server/wm/TaskChangeNotificationController.java +++ b/services/core/java/com/android/server/wm/TaskChangeNotificationController.java @@ -56,6 +56,7 @@ class TaskChangeNotificationController { private static final int NOTIFY_BACK_PRESSED_ON_TASK_ROOT = 21; private static final int NOTIFY_SINGLE_TASK_DISPLAY_DRAWN = 22; private static final int NOTIFY_TASK_DISPLAY_CHANGED_LISTENERS_MSG = 23; + private static final int NOTIFY_TASK_LIST_UPDATED_LISTENERS_MSG = 24; // Delay in notifying task stack change listeners (in millis) private static final int NOTIFY_TASK_STACK_CHANGE_LISTENERS_DELAY = 100; @@ -164,6 +165,10 @@ class TaskChangeNotificationController { l.onTaskDisplayChanged(m.arg1, m.arg2); }; + private final TaskStackConsumer mNotifyTaskListUpdated = (l, m) -> { + l.onRecentTaskListUpdated(); + }; + @FunctionalInterface public interface TaskStackConsumer { void accept(ITaskStackListener t, Message m) throws RemoteException; @@ -249,6 +254,9 @@ class TaskChangeNotificationController { case NOTIFY_TASK_DISPLAY_CHANGED_LISTENERS_MSG: forAllRemoteListeners(mNotifyTaskDisplayChanged, msg); break; + case NOTIFY_TASK_LIST_UPDATED_LISTENERS_MSG: + forAllRemoteListeners(mNotifyTaskListUpdated, msg); + break; } } } @@ -513,4 +521,13 @@ class TaskChangeNotificationController { forAllLocalListeners(mNotifyTaskStackChanged, msg); msg.sendToTarget(); } + + /** + * Called when any additions or deletions to the recent tasks list have been made. + */ + void notifyTaskListUpdated() { + final Message msg = mHandler.obtainMessage(NOTIFY_TASK_LIST_UPDATED_LISTENERS_MSG); + forAllLocalListeners(mNotifyTaskListUpdated, msg); + msg.sendToTarget(); + } } diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java index ecf3acd32d4f9..e673a627dcd67 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java @@ -467,6 +467,7 @@ class ActivityTestsBase { spyOn(getLifecycleManager()); spyOn(getLockTaskController()); + spyOn(getTaskChangeNotificationController()); doReturn(mock(IPackageManager.class)).when(this).getPackageManager(); // allow background activity starts by default doReturn(true).when(this).isBackgroundActivityStartsEnabled(); diff --git a/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java b/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java index a1999c9017028..b7a85d7bb5b7a 100644 --- a/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java @@ -43,6 +43,8 @@ import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; import static java.lang.Integer.MAX_VALUE; @@ -900,6 +902,46 @@ public class RecentTasksTest extends ActivityTestsBase { true /* showRecents */)); } + @Test + public void addTask_callsTaskNotificationController() { + final TaskRecord task = createTaskBuilder(".Task").build(); + + mRecentTasks.add(task); + mRecentTasks.remove(task); + + TaskChangeNotificationController controller = + mTestService.getTaskChangeNotificationController(); + verify(controller, times(2)).notifyTaskListUpdated(); + } + + @Test + public void removeTask_callsTaskNotificationController() { + final TaskRecord task = createTaskBuilder(".Task").build(); + + mRecentTasks.add(task); + mRecentTasks.remove(task); + + // 2 calls - Once for add and once for remove + TaskChangeNotificationController controller = + mTestService.getTaskChangeNotificationController(); + verify(controller, times(2)).notifyTaskListUpdated(); + } + + @Test + public void removeALlVisibleTask_callsTaskNotificationController_twice() { + final TaskRecord task1 = createTaskBuilder(".Task").build(); + final TaskRecord task2 = createTaskBuilder(".Task2").build(); + + mRecentTasks.add(task1); + mRecentTasks.add(task2); + mRecentTasks.removeAllVisibleTasks(TEST_USER_0_ID); + + // 4 calls - Twice for add and twice for remove + TaskChangeNotificationController controller = + mTestService.getTaskChangeNotificationController(); + verify(controller, times(4)).notifyTaskListUpdated(); + } + /** * Ensures that the raw recent tasks list is in the provided order. Note that the expected tasks * should be ordered from least to most recent.