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
This commit is contained in:
Vinit Nayak
2019-07-24 13:03:15 -07:00
parent 2c79b41c80
commit 3e73749c13
11 changed files with 106 additions and 12 deletions

View File

@@ -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();
}

View File

@@ -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 {
}
}

View File

@@ -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<K, V> {
* @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) {}

View File

@@ -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<V> {
mKeys.remove(key.id);
}
/** @return {@link Collection} of {@link TaskKey} */
public Collection<TaskKey> getValues() {
Collection<TaskKey> 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();

View File

@@ -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

View File

@@ -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;
}
}
}
}

View File

@@ -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);

View File

@@ -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();
}
/**

View File

@@ -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();
}
}

View File

@@ -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();

View File

@@ -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.