Loading libs/WindowManager/Shell/src/com/android/wm/shell/transition/FocusTransitionObserver.java +4 −5 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/FocusTransitionObserverTest.java +20 −24 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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); Loading @@ -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); } } services/core/java/com/android/server/wm/Transition.java +19 −17 Original line number Diff line number Diff line Loading @@ -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); } 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() { Loading Loading
libs/WindowManager/Shell/src/com/android/wm/shell/transition/FocusTransitionObserver.java +4 −5 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading
libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/FocusTransitionObserverTest.java +20 −24 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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); Loading @@ -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); } }
services/core/java/com/android/server/wm/Transition.java +19 −17 Original line number Diff line number Diff line Loading @@ -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); } 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() { Loading