[wm] Add APIs to notify task focused & task focus lost
- Let listeners know which task is going to front or back.
onTaskFocusChanged(taskId, focused)
- calls when the task gets or loses focus.
Test: atest ActivityStackSupervisorTest#testNotifyTaskFocusChanged
Bug: 129951708
Change-Id: I92bfdb760f4c5f1db00334f4eff41fe52115b942
diff --git a/core/java/android/app/ITaskStackListener.aidl b/core/java/android/app/ITaskStackListener.aidl
index 06288c0..37bdda0 100644
--- a/core/java/android/app/ITaskStackListener.aidl
+++ b/core/java/android/app/ITaskStackListener.aidl
@@ -204,4 +204,12 @@
* @param frozen if true, Recents Tasks list is currently frozen, false otherwise
*/
void onRecentTaskListFrozenChanged(boolean frozen);
+
+ /**
+ * Called when a task gets or loses focus.
+ *
+ * @param taskId id of the task.
+ * @param {@code true} if the task got focus, {@code false} if it lost it.
+ */
+ void onTaskFocusChanged(int taskId, boolean focused);
}
diff --git a/core/java/android/app/TaskStackListener.java b/core/java/android/app/TaskStackListener.java
index 343b386..da0aadb 100644
--- a/core/java/android/app/TaskStackListener.java
+++ b/core/java/android/app/TaskStackListener.java
@@ -199,4 +199,8 @@
@Override
public void onRecentTaskListFrozenChanged(boolean frozen) {
}
+
+ @Override
+ public void onTaskFocusChanged(int taskId, boolean focused) {
+ }
}
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 5f3e3a3..41d4ff7 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -5554,11 +5554,20 @@
if (mLastResumedActivity != null && r.mUserId != mLastResumedActivity.mUserId) {
mAmInternal.sendForegroundProfileChanged(r.mUserId);
}
+ final Task prevTask = mLastResumedActivity != null ? mLastResumedActivity.getTask() : null;
+
updateResumedAppTrace(r);
mLastResumedActivity = r;
r.getDisplay().setFocusedApp(r, true);
+ if (prevTask == null || task != prevTask) {
+ if (prevTask != null) {
+ mTaskChangeNotificationController.notifyTaskFocusChanged(prevTask.mTaskId, false);
+ }
+ mTaskChangeNotificationController.notifyTaskFocusChanged(task.mTaskId, true);
+ }
+
applyUpdateLockStateLocked(r);
applyUpdateVrModeLocked(r);
diff --git a/services/core/java/com/android/server/wm/TaskChangeNotificationController.java b/services/core/java/com/android/server/wm/TaskChangeNotificationController.java
index 2dde0ba..f715d8f 100644
--- a/services/core/java/com/android/server/wm/TaskChangeNotificationController.java
+++ b/services/core/java/com/android/server/wm/TaskChangeNotificationController.java
@@ -59,6 +59,7 @@
private static final int NOTIFY_TASK_LIST_UPDATED_LISTENERS_MSG = 24;
private static final int NOTIFY_SINGLE_TASK_DISPLAY_EMPTY = 25;
private static final int NOTIFY_TASK_LIST_FROZEN_UNFROZEN_MSG = 26;
+ private static final int NOTIFY_TASK_FOCUS_CHANGED_MSG = 27;
// Delay in notifying task stack change listeners (in millis)
private static final int NOTIFY_TASK_STACK_CHANGE_LISTENERS_DELAY = 100;
@@ -179,6 +180,10 @@
l.onRecentTaskListFrozenChanged(m.arg1 != 0);
};
+ private final TaskStackConsumer mNotifyTaskFocusChanged = (l, m) -> {
+ l.onTaskFocusChanged(m.arg1, m.arg2 != 0);
+ };
+
@FunctionalInterface
public interface TaskStackConsumer {
void accept(ITaskStackListener t, Message m) throws RemoteException;
@@ -273,6 +278,9 @@
case NOTIFY_TASK_LIST_FROZEN_UNFROZEN_MSG:
forAllRemoteListeners(mNotifyTaskListFrozen, msg);
break;
+ case NOTIFY_TASK_FOCUS_CHANGED_MSG:
+ forAllRemoteListeners(mNotifyTaskFocusChanged, msg);
+ break;
}
}
}
@@ -565,4 +573,12 @@
forAllLocalListeners(mNotifyTaskListFrozen, msg);
msg.sendToTarget();
}
+
+ /** @see ITaskStackListener#onTaskFocusChanged(int, boolean) */
+ void notifyTaskFocusChanged(int taskId, boolean focused) {
+ final Message msg = mHandler.obtainMessage(NOTIFY_TASK_FOCUS_CHANGED_MSG,
+ taskId, focused ? 1 : 0);
+ forAllLocalListeners(mNotifyTaskFocusChanged, msg);
+ msg.sendToTarget();
+ }
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStackSupervisorTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStackSupervisorTests.java
index 9647178..e8c0362 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStackSupervisorTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStackSupervisorTests.java
@@ -144,4 +144,33 @@
anyInt() /* reason */, anyString() /* packageName */);
verify(taskChangeNotifier, never()).notifyActivityDismissingDockedStack();
}
+
+ /**
+ * Ensures that notify focus task changes.
+ */
+ @Test
+ public void testNotifyTaskFocusChanged() {
+ final ActivityRecord fullScreenActivityA = new ActivityBuilder(mService).setCreateTask(true)
+ .setStack(mFullscreenStack).build();
+ final Task taskA = fullScreenActivityA.getTask();
+
+ final TaskChangeNotificationController taskChangeNotifier =
+ mService.getTaskChangeNotificationController();
+ spyOn(taskChangeNotifier);
+
+ mService.setResumedActivityUncheckLocked(fullScreenActivityA, "resumeA");
+ verify(taskChangeNotifier).notifyTaskFocusChanged(eq(taskA.mTaskId) /* taskId */,
+ eq(true) /* focused */);
+ reset(taskChangeNotifier);
+
+ final ActivityRecord fullScreenActivityB = new ActivityBuilder(mService).setCreateTask(true)
+ .setStack(mFullscreenStack).build();
+ final Task taskB = fullScreenActivityB.getTask();
+
+ mService.setResumedActivityUncheckLocked(fullScreenActivityB, "resumeB");
+ verify(taskChangeNotifier).notifyTaskFocusChanged(eq(taskA.mTaskId) /* taskId */,
+ eq(false) /* focused */);
+ verify(taskChangeNotifier).notifyTaskFocusChanged(eq(taskB.mTaskId) /* taskId */,
+ eq(true) /* focused */);
+ }
}