Merge "WindowState: applyWithNextDraw fixes" into sc-dev
This commit is contained in:
@@ -2235,11 +2235,6 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
win.mPendingPositionChanged = null;
|
||||
}
|
||||
|
||||
if (mUseBLASTSync && win.useBLASTSync() && viewVisibility != View.GONE) {
|
||||
win.prepareDrawHandlers();
|
||||
result |= RELAYOUT_RES_BLAST_SYNC;
|
||||
}
|
||||
|
||||
int attrChanges = 0;
|
||||
int flagChanges = 0;
|
||||
int privateFlagChanges = 0;
|
||||
@@ -2512,6 +2507,12 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
}
|
||||
win.mInRelayout = false;
|
||||
|
||||
if (mUseBLASTSync && win.useBLASTSync() && viewVisibility != View.GONE) {
|
||||
win.prepareDrawHandlers();
|
||||
win.markRedrawForSyncReported();
|
||||
result |= RELAYOUT_RES_BLAST_SYNC;
|
||||
}
|
||||
|
||||
if (configChanged) {
|
||||
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER,
|
||||
"relayoutWindow: postNewConfigurationToHandler");
|
||||
|
||||
@@ -763,6 +763,56 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
|
||||
* into mReadyDrawHandlers. Finally once we get to finishDrawing we know everything in
|
||||
* mReadyDrawHandlers corresponds to state which was observed by the client and we can
|
||||
* invoke the consumers.
|
||||
*
|
||||
* To see in more detail that this works, we can look at it like this:
|
||||
*
|
||||
* The client is in one of these states:
|
||||
*
|
||||
* 1. Asleep
|
||||
* 2. Traversal scheduled
|
||||
* 3. Starting traversal
|
||||
* 4. In relayout
|
||||
* 5. Already drawing
|
||||
*
|
||||
* The property we want to implement with the draw handlers is:
|
||||
* If WM code makes a change to client observable state (e.g. configuration),
|
||||
* and registers a draw handler (without releasing the WM lock in between),
|
||||
* the FIRST frame reflecting that change, will be in the Transaction passed
|
||||
* to the draw handler.
|
||||
*
|
||||
* We describe the expected sequencing in each of the possible client states.
|
||||
* We aim to "prove" that the WM can call applyWithNextDraw() with the client
|
||||
* starting in any state, and achieve the desired result.
|
||||
*
|
||||
* 1. Asleep: The client will wake up in response to MSG_RESIZED, call relayout,
|
||||
* observe the changes. Relayout will return BLAST_SYNC, and the client will
|
||||
* send the transaction to finishDrawing. Since the client was asleep. This
|
||||
* will be the first finishDrawing reflecting the change.
|
||||
* 2, 3: traversal scheduled/starting traversal: These two states can be considered
|
||||
* together. Each has two sub-states:
|
||||
* a) Traversal will call relayout. In this case we proceed like the starting
|
||||
* from asleep case.
|
||||
* b) Traversal will not call relayout. In this case, the client produced
|
||||
* frame will not include the change. Because there is no call to relayout
|
||||
* there is no call to prepareDrawHandlers() and even if the client calls
|
||||
* finish drawing the draw handler will not be invoked. We have to wait
|
||||
* on the client to receive MSG_RESIZED, and will sync on the next frame
|
||||
* 4. In relayout. In this case we are careful to prepare draw handlers and check
|
||||
* whether to return the BLAST flag at the end of relayoutWindow. This means if you
|
||||
* add a draw handler while the client is in relayout, BLAST_SYNC will be
|
||||
* immediately returned, and the client will submit the frame corresponding
|
||||
* to what returns from layout. When we prepare the draw handlers we clear the
|
||||
* flag which would later cause us to report draw for sync. Since we reported
|
||||
* sync through relayout (by luck the client was calling relayout perhaps)
|
||||
* there is no need for a MSG_RESIZED.
|
||||
* 5. Already drawing. This works much like cases 2 and 3. If there is no call to
|
||||
* finishDrawing then of course the draw handlers will not be invoked and we just
|
||||
* wait on the next frame for sync. If there is a call to finishDrawing,
|
||||
* the draw handler will not have been prepared (since we did not call relayout)
|
||||
* and we will have to wait on the next frame.
|
||||
*
|
||||
* By this logic we can see no matter which of the client states we are in when the
|
||||
* draw handler is added, it will always execute on the expected frame.
|
||||
*/
|
||||
private final List<Consumer<SurfaceControl.Transaction>> mPendingDrawHandlers
|
||||
= new ArrayList<>();
|
||||
@@ -3706,7 +3756,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
|
||||
final int displayId = getDisplayId();
|
||||
fillClientWindowFrames(mClientWindowFrames);
|
||||
|
||||
mRedrawForSyncReported = true;
|
||||
markRedrawForSyncReported();
|
||||
|
||||
try {
|
||||
mClient.resized(mClientWindowFrames, reportDraw, mergedConfiguration, forceRelayout,
|
||||
@@ -5850,7 +5900,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
|
||||
* "in relayout", the results may be undefined but at all other times the function
|
||||
* should sort of transparently work like this:
|
||||
* 1. Make changes to WM hierarchy (say change app configuration)
|
||||
* 2. Call apply with next draw.
|
||||
* 2. Call applyWithNextDraw
|
||||
* 3. After finishDrawing, our consumer will be passed the Transaction
|
||||
* containing the buffer, and we can merge in additional operations.
|
||||
* See {@link WindowState#mPendingDrawHandlers}
|
||||
@@ -5879,16 +5929,26 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
|
||||
* See {@link WindowState#mPendingDrawHandlers}
|
||||
*/
|
||||
boolean executeDrawHandlers(SurfaceControl.Transaction t) {
|
||||
if (t == null) t = mTmpTransaction;
|
||||
boolean hadHandlers = false;
|
||||
boolean applyHere = false;
|
||||
if (t == null) {
|
||||
t = mTmpTransaction;
|
||||
applyHere = true;
|
||||
}
|
||||
|
||||
for (int i = 0; i < mReadyDrawHandlers.size(); i++) {
|
||||
mReadyDrawHandlers.get(i).accept(t);
|
||||
hadHandlers = true;
|
||||
}
|
||||
mReadyDrawHandlers.clear();
|
||||
mWmService.mH.removeMessages(WINDOW_STATE_BLAST_SYNC_TIMEOUT, this);
|
||||
|
||||
t.apply();
|
||||
if (hadHandlers) {
|
||||
mReadyDrawHandlers.clear();
|
||||
mWmService.mH.removeMessages(WINDOW_STATE_BLAST_SYNC_TIMEOUT, this);
|
||||
}
|
||||
|
||||
if (applyHere) {
|
||||
t.apply();
|
||||
}
|
||||
|
||||
return hadHandlers;
|
||||
}
|
||||
@@ -5906,4 +5966,8 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
|
||||
@WindowManager.LayoutParams.WindowType int getWindowType() {
|
||||
return mAttrs.type;
|
||||
}
|
||||
|
||||
void markRedrawForSyncReported() {
|
||||
mRedrawForSyncReported = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -272,14 +272,15 @@ class WindowStateAnimator {
|
||||
}
|
||||
mDrawState = COMMIT_DRAW_PENDING;
|
||||
layoutNeeded = true;
|
||||
}
|
||||
|
||||
if (postDrawTransaction != null) {
|
||||
if (postDrawTransaction != null) {
|
||||
if (mLastHidden) {
|
||||
mPostDrawTransaction.merge(postDrawTransaction);
|
||||
layoutNeeded = true;
|
||||
} else {
|
||||
postDrawTransaction.apply();
|
||||
}
|
||||
} else if (postDrawTransaction != null) {
|
||||
// If draw state is not pending we may delay applying this transaction from the client,
|
||||
// so apply it now.
|
||||
postDrawTransaction.apply();
|
||||
}
|
||||
|
||||
return layoutNeeded;
|
||||
|
||||
Reference in New Issue
Block a user