summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Kazuki Takise <takise@google.com> 2024-09-29 10:49:20 +0000
committer Kazuki Takise <takise@google.com> 2024-10-01 21:17:15 +0000
commitd4e27d9afd1e1d454fb7e4c4d2c4e981d079cd1f (patch)
tree3f6f965559f7997f2d2b4018ddd3d47513964838
parent64e46a09e6023dff77e68f3764555c412708401d (diff)
Report display change for display focus switch
Currently, when display focus has changed, the task that caused the focus switch is reported with the MOVED_TO_TOP flag, and WMShell “infers” the display focus event from it. This is a bit tricky in some cases because even when a task gets "moved to front", sometimes the display may not come on top. For example, when a task gets minimized, the task just behind the originally top task comes on top, but this doesn't involve moving the display to front. To avoid these confusions, with this change, the display itself is reported with the MOVED_TO_TOP flag when display focus switches, which greatly simplifies the logic and saves us considering tricky edge cases. Bug: 369940439 Flag: com.android.window.flags.enable_display_focus_in_shell_transitions Test: TransitionTests Test: atest FocusTransitionObserverTest Change-Id: I61a5649cdc917a7d7a344329f247580cb4218190
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/transition/FocusTransitionObserver.java9
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/FocusTransitionObserverTest.java44
-rw-r--r--services/core/java/com/android/server/wm/Transition.java36
3 files changed, 43 insertions, 46 deletions
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/FocusTransitionObserver.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/FocusTransitionObserver.java
index 2f5059f3161c..399e39a920fc 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/FocusTransitionObserver.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/FocusTransitionObserver.java
@@ -17,13 +17,13 @@
package com.android.wm.shell.transition;
import static android.view.Display.INVALID_DISPLAY;
+import static android.window.TransitionInfo.FLAG_IS_DISPLAY;
import static android.window.TransitionInfo.FLAG_MOVED_TO_TOP;
import static com.android.window.flags.Flags.enableDisplayFocusInShellTransitions;
import static com.android.wm.shell.transition.Transitions.TransitionObserver;
import android.annotation.NonNull;
-import android.app.ActivityManager.RunningTaskInfo;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Slog;
@@ -62,10 +62,9 @@ public class FocusTransitionObserver implements TransitionObserver {
final List<TransitionInfo.Change> changes = info.getChanges();
for (int i = changes.size() - 1; i >= 0; i--) {
final TransitionInfo.Change change = changes.get(i);
- final RunningTaskInfo task = change.getTaskInfo();
- if (task != null && task.isFocused && change.hasFlags(FLAG_MOVED_TO_TOP)) {
- if (mFocusedDisplayId != task.displayId) {
- mFocusedDisplayId = task.displayId;
+ if (change.hasFlags(FLAG_IS_DISPLAY) && change.hasFlags(FLAG_MOVED_TO_TOP)) {
+ if (mFocusedDisplayId != change.getEndDisplayId()) {
+ mFocusedDisplayId = change.getEndDisplayId();
notifyFocusedDisplayChanged();
}
return;
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/FocusTransitionObserverTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/FocusTransitionObserverTest.java
index d37b4cf4b4b3..d63158c29688 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/FocusTransitionObserverTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/FocusTransitionObserverTest.java
@@ -18,7 +18,7 @@ package com.android.wm.shell.transition;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.WindowManager.TRANSIT_OPEN;
-import static android.view.WindowManager.TRANSIT_TO_FRONT;
+import static android.window.TransitionInfo.FLAG_IS_DISPLAY;
import static android.window.TransitionInfo.FLAG_MOVED_TO_TOP;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
@@ -97,50 +97,38 @@ public class FocusTransitionObserverTest extends ShellTestCase {
}
@Test
- public void testTransitionWithMovedToFrontFlagChangesDisplayFocus() throws RemoteException {
+ public void testOnlyDisplayChangeAffectsDisplayFocus() throws RemoteException {
final IBinder binder = mock(IBinder.class);
final SurfaceControl.Transaction tx = mock(SurfaceControl.Transaction.class);
- // Open a task on the default display, which doesn't change display focus because the
- // default display already has it.
+ // Open a task on the secondary display, but it doesn't change display focus because it only
+ // has a task change.
TransitionInfo info = mock(TransitionInfo.class);
final List<TransitionInfo.Change> changes = new ArrayList<>();
- setupChange(changes, 123 /* taskId */, TRANSIT_OPEN, DEFAULT_DISPLAY,
+ setupTaskChange(changes, 123 /* taskId */, TRANSIT_OPEN, SECONDARY_DISPLAY_ID,
true /* focused */);
when(info.getChanges()).thenReturn(changes);
mFocusTransitionObserver.onTransitionReady(binder, info, tx, tx);
verify(mListener, never()).onFocusedDisplayChanged(SECONDARY_DISPLAY_ID);
clearInvocations(mListener);
- // Open a new task on the secondary display and verify display focus changes to the display.
+ // Moving the secondary display to front must change display focus to it.
changes.clear();
- setupChange(changes, 456 /* taskId */, TRANSIT_OPEN, SECONDARY_DISPLAY_ID,
- true /* focused */);
+ setupDisplayToTopChange(changes, SECONDARY_DISPLAY_ID);
when(info.getChanges()).thenReturn(changes);
mFocusTransitionObserver.onTransitionReady(binder, info, tx, tx);
- verify(mListener, times(1)).onFocusedDisplayChanged(SECONDARY_DISPLAY_ID);
- clearInvocations(mListener);
+ verify(mListener, times(1))
+ .onFocusedDisplayChanged(SECONDARY_DISPLAY_ID);
- // Open the first task to front and verify display focus goes back to the default display.
+ // Moving the secondary display to front must change display focus back to it.
changes.clear();
- setupChange(changes, 123 /* taskId */, TRANSIT_TO_FRONT, DEFAULT_DISPLAY,
- true /* focused */);
+ setupDisplayToTopChange(changes, DEFAULT_DISPLAY);
when(info.getChanges()).thenReturn(changes);
mFocusTransitionObserver.onTransitionReady(binder, info, tx, tx);
verify(mListener, times(1)).onFocusedDisplayChanged(DEFAULT_DISPLAY);
- clearInvocations(mListener);
-
- // Open another task on the default display and verify no display focus switch as it's
- // already on the default display.
- changes.clear();
- setupChange(changes, 789 /* taskId */, TRANSIT_OPEN, DEFAULT_DISPLAY,
- true /* focused */);
- when(info.getChanges()).thenReturn(changes);
- mFocusTransitionObserver.onTransitionReady(binder, info, tx, tx);
- verify(mListener, never()).onFocusedDisplayChanged(DEFAULT_DISPLAY);
}
- private void setupChange(List<TransitionInfo.Change> changes, int taskId,
+ private void setupTaskChange(List<TransitionInfo.Change> changes, int taskId,
@TransitionMode int mode, int displayId, boolean focused) {
TransitionInfo.Change change = mock(TransitionInfo.Change.class);
RunningTaskInfo taskInfo = mock(RunningTaskInfo.class);
@@ -152,4 +140,12 @@ public class FocusTransitionObserverTest extends ShellTestCase {
when(change.getMode()).thenReturn(mode);
changes.add(change);
}
+
+ private void setupDisplayToTopChange(List<TransitionInfo.Change> changes, int displayId) {
+ TransitionInfo.Change change = mock(TransitionInfo.Change.class);
+ when(change.hasFlags(FLAG_MOVED_TO_TOP)).thenReturn(true);
+ when(change.hasFlags(FLAG_IS_DISPLAY)).thenReturn(true);
+ when(change.getEndDisplayId()).thenReturn(displayId);
+ changes.add(change);
+ }
}
diff --git a/services/core/java/com/android/server/wm/Transition.java b/services/core/java/com/android/server/wm/Transition.java
index c48590fba00d..fde502f2306c 100644
--- a/services/core/java/com/android/server/wm/Transition.java
+++ b/services/core/java/com/android/server/wm/Transition.java
@@ -2188,30 +2188,32 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener {
for (int i = onTopTasksEnd.size() - 1; i >= 0; --i) {
final Task task = onTopTasksEnd.get(i);
if (task.getDisplayId() != displayId) continue;
- if (!enableDisplayFocusInShellTransitions()
- || mOnTopDisplayStart == onTopDisplayEnd
- || displayId != onTopDisplayEnd.mDisplayId) {
- // If it didn't change since last report, don't report
- if (reportedOnTop == null) {
- if (mOnTopTasksStart.contains(task)) continue;
- } else if (reportedOnTop.contains(task)) {
- continue;
- }
- }
- // Need to report it.
- mParticipants.add(task);
- int changeIdx = mChanges.indexOfKey(task);
- if (changeIdx < 0) {
- mChanges.put(task, new ChangeInfo(task));
- changeIdx = mChanges.indexOfKey(task);
+ if (reportedOnTop == null) {
+ if (mOnTopTasksStart.contains(task)) continue;
+ } else if (reportedOnTop.contains(task)) {
+ continue;
}
- mChanges.valueAt(changeIdx).mFlags |= ChangeInfo.FLAG_CHANGE_MOVED_TO_TOP;
+ addToTopChange(task);
}
// Swap in the latest on-top tasks.
mController.mLatestOnTopTasksReported.put(displayId, onTopTasksEnd);
onTopTasksEnd = reportedOnTop != null ? reportedOnTop : new ArrayList<>();
onTopTasksEnd.clear();
+
+ if (enableDisplayFocusInShellTransitions()
+ && mOnTopDisplayStart != onTopDisplayEnd
+ && displayId == onTopDisplayEnd.mDisplayId) {
+ addToTopChange(onTopDisplayEnd);
+ }
+ }
+ }
+
+ private void addToTopChange(@NonNull WindowContainer wc) {
+ mParticipants.add(wc);
+ if (!mChanges.containsKey(wc)) {
+ mChanges.put(wc, new ChangeInfo(wc));
}
+ mChanges.get(wc).mFlags |= ChangeInfo.FLAG_CHANGE_MOVED_TO_TOP;
}
private void postCleanupOnFailure() {