Loading services/core/java/com/android/server/wm/WindowContainer.java +15 −6 Original line number Diff line number Diff line Loading @@ -2461,6 +2461,19 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer< mWaitingSyncId = -1; } /** * Returns true if any of the children elected to participate in the Sync */ boolean addChildrenToSyncSet(int localId) { boolean willSync = false; for (int i = 0; i < mChildren.size(); i++) { final WindowContainer child = mChildren.get(i); willSync |= mBLASTSyncEngine.addToSyncSet(localId, child); } return willSync; } boolean prepareForSync(BLASTSyncEngine.TransactionReadyListener waitingListener, int waitingId) { boolean willSync = false; Loading @@ -2469,16 +2482,12 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer< } mUsingBLASTSyncTransaction = true; int localId = mBLASTSyncEngine.startSyncSet(this); for (int i = 0; i < mChildren.size(); i++) { final WindowContainer child = mChildren.get(i); willSync = mBLASTSyncEngine.addToSyncSet(localId, child) | willSync; } // Make sure to set these before we call setReady in case the sync was a no-op mWaitingSyncId = waitingId; mWaitingListener = waitingListener; int localId = mBLASTSyncEngine.startSyncSet(this); willSync |= addChildrenToSyncSet(localId); mBLASTSyncEngine.setReady(localId); return willSync; Loading services/core/java/com/android/server/wm/WindowState.java +26 −5 Original line number Diff line number Diff line Loading @@ -679,6 +679,15 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP */ int mFrameRateSelectionPriority = RefreshRatePolicy.LAYER_PRIORITY_UNSET; /** * BLASTSyncEngine ID corresponding to a sync-set for all * our children. We add our children to this set in Sync, * but we save it and don't mark it as ready until finishDrawing * this way we have a two way latch between all our children finishing * and drawing ourselves. */ private int mLocalSyncId = -1; static final int BLAST_TIMEOUT_DURATION = 5000; /* milliseconds */ /** Loading Loading @@ -5684,11 +5693,13 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP @Override boolean prepareForSync(BLASTSyncEngine.TransactionReadyListener waitingListener, int waitingId) { // TODO(b/148871522): Support child window mWaitingListener = waitingListener; mWaitingSyncId = waitingId; mUsingBLASTSyncTransaction = true; mLocalSyncId = mBLASTSyncEngine.startSyncSet(this); addChildrenToSyncSet(mLocalSyncId); mWmService.mH.removeMessages(WINDOW_STATE_BLAST_SYNC_TIMEOUT, this); mWmService.mH.sendNewMessageDelayed(WINDOW_STATE_BLAST_SYNC_TIMEOUT, this, BLAST_TIMEOUT_DURATION); Loading @@ -5702,11 +5713,21 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP } mWmService.mH.removeMessages(WINDOW_STATE_BLAST_SYNC_TIMEOUT, this); if (postDrawTransaction == null) { postDrawTransaction = new SurfaceControl.Transaction(); if (postDrawTransaction != null) { mBLASTSyncTransaction.merge(postDrawTransaction); } postDrawTransaction.merge(mBLASTSyncTransaction); mWaitingListener.transactionReady(mWaitingSyncId, postDrawTransaction); // If localSyncId is >0 then we are syncing with children and will // invoke transaction ready from our own #transactionReady callback // we just need to signal our side of the sync (setReady). But if we // have no sync operation at this level transactionReady will never // be invoked and we need to invoke it ourself. if (mLocalSyncId >= 0) { mBLASTSyncEngine.setReady(mLocalSyncId); } else { mWaitingListener.transactionReady(mWaitingSyncId, mBLASTSyncTransaction); } mUsingBLASTSyncTransaction = false; mWaitingSyncId = 0; Loading services/tests/wmtests/src/com/android/server/wm/TaskOrganizerTests.java +33 −0 Original line number Diff line number Diff line Loading @@ -32,6 +32,7 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock; import static com.android.dx.mockito.inline.extended.ExtendedMockito.never; import static com.android.dx.mockito.inline.extended.ExtendedMockito.reset; import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; import static com.android.dx.mockito.inline.extended.ExtendedMockito.times; import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify; Loading Loading @@ -567,6 +568,38 @@ public class TaskOrganizerTests extends WindowTestsBase { .transactionReady(anyInt(), any()); } @Test public void testBLASTCallbackWithChildWindow() { final ActivityStack stackController1 = createTaskStackOnDisplay(mDisplayContent); final Task task = createTaskInStack(stackController1, 0 /* userId */); final ITaskOrganizer organizer = registerMockOrganizer(); final WindowState w = createAppWindow(task, TYPE_APPLICATION, "Enlightened Window"); final WindowState child = createWindow(w, TYPE_APPLICATION, "Other Window"); w.mActivityRecord.setVisible(true); makeWindowVisible(w, child); 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); w.finishDrawing(null); // Since we have a child window we still shouldn't be done. verify(transactionListener, never()) .transactionReady(anyInt(), any()); reset(transactionListener); child.finishDrawing(null); // Ah finally! Done verify(transactionListener) .transactionReady(anyInt(), any()); } class StubOrganizer extends ITaskOrganizer.Stub { RunningTaskInfo mInfo; Loading Loading
services/core/java/com/android/server/wm/WindowContainer.java +15 −6 Original line number Diff line number Diff line Loading @@ -2461,6 +2461,19 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer< mWaitingSyncId = -1; } /** * Returns true if any of the children elected to participate in the Sync */ boolean addChildrenToSyncSet(int localId) { boolean willSync = false; for (int i = 0; i < mChildren.size(); i++) { final WindowContainer child = mChildren.get(i); willSync |= mBLASTSyncEngine.addToSyncSet(localId, child); } return willSync; } boolean prepareForSync(BLASTSyncEngine.TransactionReadyListener waitingListener, int waitingId) { boolean willSync = false; Loading @@ -2469,16 +2482,12 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer< } mUsingBLASTSyncTransaction = true; int localId = mBLASTSyncEngine.startSyncSet(this); for (int i = 0; i < mChildren.size(); i++) { final WindowContainer child = mChildren.get(i); willSync = mBLASTSyncEngine.addToSyncSet(localId, child) | willSync; } // Make sure to set these before we call setReady in case the sync was a no-op mWaitingSyncId = waitingId; mWaitingListener = waitingListener; int localId = mBLASTSyncEngine.startSyncSet(this); willSync |= addChildrenToSyncSet(localId); mBLASTSyncEngine.setReady(localId); return willSync; Loading
services/core/java/com/android/server/wm/WindowState.java +26 −5 Original line number Diff line number Diff line Loading @@ -679,6 +679,15 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP */ int mFrameRateSelectionPriority = RefreshRatePolicy.LAYER_PRIORITY_UNSET; /** * BLASTSyncEngine ID corresponding to a sync-set for all * our children. We add our children to this set in Sync, * but we save it and don't mark it as ready until finishDrawing * this way we have a two way latch between all our children finishing * and drawing ourselves. */ private int mLocalSyncId = -1; static final int BLAST_TIMEOUT_DURATION = 5000; /* milliseconds */ /** Loading Loading @@ -5684,11 +5693,13 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP @Override boolean prepareForSync(BLASTSyncEngine.TransactionReadyListener waitingListener, int waitingId) { // TODO(b/148871522): Support child window mWaitingListener = waitingListener; mWaitingSyncId = waitingId; mUsingBLASTSyncTransaction = true; mLocalSyncId = mBLASTSyncEngine.startSyncSet(this); addChildrenToSyncSet(mLocalSyncId); mWmService.mH.removeMessages(WINDOW_STATE_BLAST_SYNC_TIMEOUT, this); mWmService.mH.sendNewMessageDelayed(WINDOW_STATE_BLAST_SYNC_TIMEOUT, this, BLAST_TIMEOUT_DURATION); Loading @@ -5702,11 +5713,21 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP } mWmService.mH.removeMessages(WINDOW_STATE_BLAST_SYNC_TIMEOUT, this); if (postDrawTransaction == null) { postDrawTransaction = new SurfaceControl.Transaction(); if (postDrawTransaction != null) { mBLASTSyncTransaction.merge(postDrawTransaction); } postDrawTransaction.merge(mBLASTSyncTransaction); mWaitingListener.transactionReady(mWaitingSyncId, postDrawTransaction); // If localSyncId is >0 then we are syncing with children and will // invoke transaction ready from our own #transactionReady callback // we just need to signal our side of the sync (setReady). But if we // have no sync operation at this level transactionReady will never // be invoked and we need to invoke it ourself. if (mLocalSyncId >= 0) { mBLASTSyncEngine.setReady(mLocalSyncId); } else { mWaitingListener.transactionReady(mWaitingSyncId, mBLASTSyncTransaction); } mUsingBLASTSyncTransaction = false; mWaitingSyncId = 0; Loading
services/tests/wmtests/src/com/android/server/wm/TaskOrganizerTests.java +33 −0 Original line number Diff line number Diff line Loading @@ -32,6 +32,7 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock; import static com.android.dx.mockito.inline.extended.ExtendedMockito.never; import static com.android.dx.mockito.inline.extended.ExtendedMockito.reset; import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; import static com.android.dx.mockito.inline.extended.ExtendedMockito.times; import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify; Loading Loading @@ -567,6 +568,38 @@ public class TaskOrganizerTests extends WindowTestsBase { .transactionReady(anyInt(), any()); } @Test public void testBLASTCallbackWithChildWindow() { final ActivityStack stackController1 = createTaskStackOnDisplay(mDisplayContent); final Task task = createTaskInStack(stackController1, 0 /* userId */); final ITaskOrganizer organizer = registerMockOrganizer(); final WindowState w = createAppWindow(task, TYPE_APPLICATION, "Enlightened Window"); final WindowState child = createWindow(w, TYPE_APPLICATION, "Other Window"); w.mActivityRecord.setVisible(true); makeWindowVisible(w, child); 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); w.finishDrawing(null); // Since we have a child window we still shouldn't be done. verify(transactionListener, never()) .transactionReady(anyInt(), any()); reset(transactionListener); child.finishDrawing(null); // Ah finally! Done verify(transactionListener) .transactionReady(anyInt(), any()); } class StubOrganizer extends ITaskOrganizer.Stub { RunningTaskInfo mInfo; Loading