diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java index 9a9283257b032..a1902bbd6764c 100644 --- a/services/core/java/com/android/server/wm/WindowContainer.java +++ b/services/core/java/com/android/server/wm/WindowContainer.java @@ -2476,9 +2476,12 @@ class WindowContainer extends ConfigurationContainer< boolean prepareForSync(BLASTSyncEngine.TransactionReadyListener waitingListener, int waitingId) { - boolean willSync = false; - if (!isVisible()) { - return willSync; + boolean willSync = true; + + // If we are invisible, no need to sync, likewise if we are already engaged in a sync, + // we can't support overlapping syncs on a single container yet. + if (!isVisible() || mWaitingListener != null) { + return false; } mUsingBLASTSyncTransaction = true; diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskOrganizerTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskOrganizerTests.java index 8019e9df5143e..71c837e2b46ed 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TaskOrganizerTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/TaskOrganizerTests.java @@ -550,6 +550,9 @@ public class TaskOrganizerTests extends WindowTestsBase { final Task task = createTaskInStack(stackController1, 0 /* userId */); final ITaskOrganizer organizer = registerMockOrganizer(); + spyOn(task); + doReturn(true).when(task).isVisible(); + BLASTSyncEngine bse = new BLASTSyncEngine(); BLASTSyncEngine.TransactionReadyListener transactionListener = @@ -563,6 +566,35 @@ public class TaskOrganizerTests extends WindowTestsBase { .transactionReady(anyInt(), any()); } + @Test + public void testOverlappingBLASTCallback() throws RemoteException { + final ActivityStack stackController1 = createTaskStackOnDisplay(mDisplayContent); + final Task task = createTaskInStack(stackController1, 0 /* userId */); + final ITaskOrganizer organizer = registerMockOrganizer(); + + spyOn(task); + doReturn(true).when(task).isVisible(); + final WindowState w = createAppWindow(task, TYPE_APPLICATION, "Enlightened Window"); + makeWindowVisible(w); + + BLASTSyncEngine bse = new BLASTSyncEngine(); + + BLASTSyncEngine.TransactionReadyListener transactionListener = + mock(BLASTSyncEngine.TransactionReadyListener.class); + + int id = bse.startSyncSet(transactionListener); + assertEquals(true, bse.addToSyncSet(id, task)); + bse.setReady(id); + + int id2 = bse.startSyncSet(transactionListener); + // We should be rejected from the second sync since we are already + // in one. + assertEquals(false, bse.addToSyncSet(id2, task)); + w.finishDrawing(null); + assertEquals(true, bse.addToSyncSet(id2, task)); + bse.setReady(id2); + } + @Test public void testBLASTCallbackWithWindow() { final ActivityStack stackController1 = createTaskStackOnDisplay(mDisplayContent);