WMS/ViewRoot: Prepare for Async BLAST Sync [1/N]
We would like to make relayoutWindow a non-blocking call, and of course why not, who likes blocking. However it functions as a critical path of BLASTSync. To understand why examine the Guarantee described in BLASTSync.md. In order to implement this guarantee we need to know “Which frame has the client finished drawing” when it calls finishDrawing. The current answer to this question is “The frame reflecting the state observed in the last call to relayoutWindow”. The comments on mPending and mCurrentDrawHandlers also have a lot more context on how this works currently. Since relayoutWindow has a critical section, it also ensures that changes to syncable state and preparation of sync will be observed atomically (since they are both observed over relayoutWindow, which is always called before any frame drawing updated syncable state). We design a new protocol described in BLASTSync.md, which uses a seqId to track which call to finishDrawing reflects which syncable state. We implement this seqId based system. Unfortunately the WindowManager doesn’t quite conform to the requirements specified by the protocol, and a follow up CL ensures that syncable state changes will always be sent with the seqId. This CL simply adds the protocol specification and makes some required interface changes. It can be seen to be a no-op. Bug: 161810301 Bug: 175861051 Bug: 175861127 Bug: 200285149 Change-Id: If2dea07121fe7de5d2524c5b63678dddf955d4b7
This commit is contained in:
parent
f1b86e8ce3
commit
027b59d90a
@ -20,6 +20,7 @@ import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentat
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.os.RemoteException;
|
||||
import android.perftests.utils.BenchmarkState;
|
||||
import android.perftests.utils.PerfStatusReporter;
|
||||
@ -153,7 +154,8 @@ public class RelayoutPerfTest extends WindowManagerPerfTestBase
|
||||
while (state.keepRunning()) {
|
||||
session.relayout(mWindow, mParams, mWidth, mHeight,
|
||||
mViewVisibility.getAsInt(), mFlags, mOutFrames,
|
||||
mOutMergedConfiguration, mOutSurfaceControl, mOutInsetsState, mOutControls);
|
||||
mOutMergedConfiguration, mOutSurfaceControl, mOutInsetsState, mOutControls,
|
||||
new Bundle());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -252,6 +252,7 @@ public abstract class WallpaperService extends Service {
|
||||
final InsetsVisibilities mRequestedVisibilities = new InsetsVisibilities();
|
||||
final InsetsSourceControl[] mTempControls = new InsetsSourceControl[0];
|
||||
final MergedConfiguration mMergedConfiguration = new MergedConfiguration();
|
||||
final Bundle mSyncSeqIdBundle = new Bundle();
|
||||
private final Point mSurfaceSize = new Point();
|
||||
private final Point mLastSurfaceSize = new Point();
|
||||
private final Matrix mTmpMatrix = new Matrix();
|
||||
@ -391,7 +392,7 @@ public abstract class WallpaperService extends Service {
|
||||
@Override
|
||||
public void resized(ClientWindowFrames frames, boolean reportDraw,
|
||||
MergedConfiguration mergedConfiguration, boolean forceLayout,
|
||||
boolean alwaysConsumeSystemBars, int displayId) {
|
||||
boolean alwaysConsumeSystemBars, int displayId, int syncSeqId) {
|
||||
Message msg = mCaller.obtainMessageIO(MSG_WINDOW_RESIZED,
|
||||
reportDraw ? 1 : 0,
|
||||
mergedConfiguration);
|
||||
@ -1151,7 +1152,7 @@ public abstract class WallpaperService extends Service {
|
||||
final int relayoutResult = mSession.relayout(
|
||||
mWindow, mLayout, mWidth, mHeight,
|
||||
View.VISIBLE, 0, mWinFrames, mMergedConfiguration, mSurfaceControl,
|
||||
mInsetsState, mTempControls);
|
||||
mInsetsState, mTempControls, mSyncSeqIdBundle);
|
||||
|
||||
final int transformHint = SurfaceControl.rotationToBufferTransform(
|
||||
(mDisplayInstallOrientation + mDisplay.getRotation()) % 4);
|
||||
@ -1338,7 +1339,8 @@ public abstract class WallpaperService extends Service {
|
||||
mSurfaceCreated = true;
|
||||
if (redrawNeeded) {
|
||||
resetWindowPages();
|
||||
mSession.finishDrawing(mWindow, null /* postDrawTransaction */);
|
||||
mSession.finishDrawing(mWindow, null /* postDrawTransaction */,
|
||||
Integer.MAX_VALUE);
|
||||
processLocalColors(mPendingXOffset, mPendingXOffsetStep);
|
||||
notifyColorsChanged();
|
||||
}
|
||||
|
@ -55,7 +55,8 @@ oneway interface IWindow {
|
||||
|
||||
void resized(in ClientWindowFrames frames, boolean reportDraw,
|
||||
in MergedConfiguration newMergedConfiguration,
|
||||
boolean forceLayout, boolean alwaysConsumeSystemBars, int displayId);
|
||||
boolean forceLayout, boolean alwaysConsumeSystemBars, int displayId,
|
||||
int syncSeqId);
|
||||
|
||||
/**
|
||||
* Called when the window insets configuration has changed.
|
||||
|
@ -104,7 +104,8 @@ interface IWindowSession {
|
||||
int requestedWidth, int requestedHeight, int viewVisibility,
|
||||
int flags, out ClientWindowFrames outFrames,
|
||||
out MergedConfiguration outMergedConfiguration, out SurfaceControl outSurfaceControl,
|
||||
out InsetsState insetsState, out InsetsSourceControl[] activeControls);
|
||||
out InsetsState insetsState, out InsetsSourceControl[] activeControls,
|
||||
out Bundle bundle);
|
||||
|
||||
/*
|
||||
* Notify the window manager that an application is relaunching and
|
||||
@ -142,7 +143,8 @@ interface IWindowSession {
|
||||
* is null if there is no sync required.
|
||||
*/
|
||||
@UnsupportedAppUsage
|
||||
oneway void finishDrawing(IWindow window, in SurfaceControl.Transaction postDrawTransaction);
|
||||
oneway void finishDrawing(IWindow window, in SurfaceControl.Transaction postDrawTransaction,
|
||||
int seqId);
|
||||
|
||||
@UnsupportedAppUsage
|
||||
oneway void setInTouchMode(boolean showFocus);
|
||||
|
@ -830,6 +830,24 @@ public final class ViewRootImpl implements ViewParent,
|
||||
|
||||
private int mLastTransformHint = Integer.MIN_VALUE;
|
||||
|
||||
/**
|
||||
* A temporary object used so relayoutWindow can return the latest SyncSeqId
|
||||
* system. The SyncSeqId system was designed to work without synchronous relayout
|
||||
* window, and actually synchronous relayout window presents a problem. We could have
|
||||
* a sequence like this:
|
||||
* 1. We send MSG_RESIZED to the client with a new syncSeqId to begin a new sync
|
||||
* 2. Due to scheduling the client executes performTraversals before calling MSG_RESIZED
|
||||
* 3. Coincidentally for some random reason it also calls relayout
|
||||
* 4. It observes the new state from relayout, and so the next frame will contain the state
|
||||
* However it hasn't received the seqId yet, and so under the designed operation of
|
||||
* seqId flowing through MSG_RESIZED, the next frame wouldn't be synced. Since it
|
||||
* contains our target sync state, we need to sync it! This problem won't come up once
|
||||
* we get rid of synchronous relayout, until then, we use this bundle to channel the
|
||||
* integer back over relayout.
|
||||
*/
|
||||
private Bundle mRelayoutBundle = new Bundle();
|
||||
private int mSyncSeqId;
|
||||
|
||||
private String mTag = TAG;
|
||||
|
||||
public ViewRootImpl(Context context, Display display) {
|
||||
@ -1711,6 +1729,7 @@ public final class ViewRootImpl implements ViewParent,
|
||||
mPendingBackDropFrame.set(backdropFrame);
|
||||
mForceNextWindowRelayout = forceNextWindowRelayout;
|
||||
mPendingAlwaysConsumeSystemBars = args.argi2 != 0;
|
||||
mSyncSeqId = args.argi4;
|
||||
|
||||
if (msg == MSG_RESIZED_REPORT) {
|
||||
reportNextDraw();
|
||||
@ -4128,7 +4147,7 @@ public final class ViewRootImpl implements ViewParent,
|
||||
mDrawsNeededToReport = 0;
|
||||
|
||||
try {
|
||||
mWindowSession.finishDrawing(mWindow, mSurfaceChangedTransaction);
|
||||
mWindowSession.finishDrawing(mWindow, mSurfaceChangedTransaction, Integer.MAX_VALUE);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(mTag, "Unable to report draw finished", e);
|
||||
mSurfaceChangedTransaction.apply();
|
||||
@ -8071,7 +8090,7 @@ public final class ViewRootImpl implements ViewParent,
|
||||
requestedWidth, requestedHeight, viewVisibility,
|
||||
insetsPending ? WindowManagerGlobal.RELAYOUT_INSETS_PENDING : 0,
|
||||
mTmpFrames, mPendingMergedConfiguration, mSurfaceControl, mTempInsets,
|
||||
mTempControls);
|
||||
mTempControls, mRelayoutBundle);
|
||||
|
||||
final int transformHint = SurfaceControl.rotationToBufferTransform(
|
||||
(mDisplayInstallOrientation + mDisplay.getRotation()) % 4);
|
||||
@ -8497,7 +8516,7 @@ public final class ViewRootImpl implements ViewParent,
|
||||
if ((relayoutWindow(mWindowAttributes, viewVisibility, false)
|
||||
& WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME) != 0) {
|
||||
mWindowSession.finishDrawing(
|
||||
mWindow, null /* postDrawTransaction */);
|
||||
mWindow, null /* postDrawTransaction */, Integer.MAX_VALUE);
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
}
|
||||
@ -8571,7 +8590,7 @@ public final class ViewRootImpl implements ViewParent,
|
||||
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
|
||||
private void dispatchResized(ClientWindowFrames frames, boolean reportDraw,
|
||||
MergedConfiguration mergedConfiguration, boolean forceLayout,
|
||||
boolean alwaysConsumeSystemBars, int displayId) {
|
||||
boolean alwaysConsumeSystemBars, int displayId, int seqId) {
|
||||
final Rect frame = frames.frame;
|
||||
final Rect backDropFrame = frames.backdropFrame;
|
||||
if (DEBUG_LAYOUT) Log.v(mTag, "Resizing " + this + ": frame=" + frame.toShortString()
|
||||
@ -8602,6 +8621,7 @@ public final class ViewRootImpl implements ViewParent,
|
||||
args.argi1 = forceLayout ? 1 : 0;
|
||||
args.argi2 = alwaysConsumeSystemBars ? 1 : 0;
|
||||
args.argi3 = displayId;
|
||||
args.argi4 = seqId;
|
||||
msg.obj = args;
|
||||
mHandler.sendMessage(msg);
|
||||
}
|
||||
@ -9986,11 +10006,11 @@ public final class ViewRootImpl implements ViewParent,
|
||||
@Override
|
||||
public void resized(ClientWindowFrames frames, boolean reportDraw,
|
||||
MergedConfiguration mergedConfiguration, boolean forceLayout,
|
||||
boolean alwaysConsumeSystemBars, int displayId) {
|
||||
boolean alwaysConsumeSystemBars, int displayId, int seqId) {
|
||||
final ViewRootImpl viewAncestor = mViewAncestor.get();
|
||||
if (viewAncestor != null) {
|
||||
viewAncestor.dispatchResized(frames, reportDraw, mergedConfiguration, forceLayout,
|
||||
alwaysConsumeSystemBars, displayId);
|
||||
alwaysConsumeSystemBars, displayId, seqId);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -22,6 +22,7 @@ import android.graphics.PixelFormat;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.Region;
|
||||
import android.os.Binder;
|
||||
import android.os.Bundle;
|
||||
import android.os.IBinder;
|
||||
import android.os.RemoteCallback;
|
||||
import android.os.RemoteException;
|
||||
@ -277,7 +278,7 @@ public class WindowlessWindowManager implements IWindowSession {
|
||||
int requestedWidth, int requestedHeight, int viewFlags, int flags,
|
||||
ClientWindowFrames outFrames, MergedConfiguration mergedConfiguration,
|
||||
SurfaceControl outSurfaceControl, InsetsState outInsetsState,
|
||||
InsetsSourceControl[] outActiveControls) {
|
||||
InsetsSourceControl[] outActiveControls, Bundle outSyncSeqIdBundle) {
|
||||
final State state;
|
||||
synchronized (this) {
|
||||
state = mStateForWindow.get(window.asBinder());
|
||||
@ -354,7 +355,7 @@ public class WindowlessWindowManager implements IWindowSession {
|
||||
|
||||
@Override
|
||||
public void finishDrawing(android.view.IWindow window,
|
||||
android.view.SurfaceControl.Transaction postDrawTransaction) {
|
||||
android.view.SurfaceControl.Transaction postDrawTransaction, int seqId) {
|
||||
synchronized (this) {
|
||||
final ResizeCompleteCallback c =
|
||||
mResizeCompletionForWindow.get(window.asBinder());
|
||||
|
@ -51,10 +51,10 @@ public class BaseIWindow extends IWindow.Stub {
|
||||
@Override
|
||||
public void resized(ClientWindowFrames frames, boolean reportDraw,
|
||||
MergedConfiguration mergedConfiguration, boolean forceLayout,
|
||||
boolean alwaysConsumeSystemBars, int displayId) {
|
||||
boolean alwaysConsumeSystemBars, int displayId, int seqId) {
|
||||
if (reportDraw) {
|
||||
try {
|
||||
mSession.finishDrawing(this, null /* postDrawTransaction */);
|
||||
mSession.finishDrawing(this, null /* postDrawTransaction */, seqId);
|
||||
} catch (RemoteException e) {
|
||||
}
|
||||
}
|
||||
|
@ -344,7 +344,7 @@ public class SystemWindows {
|
||||
@Override
|
||||
public void resized(ClientWindowFrames frames, boolean reportDraw,
|
||||
MergedConfiguration newMergedConfiguration, boolean forceLayout,
|
||||
boolean alwaysConsumeSystemBars, int displayId) {}
|
||||
boolean alwaysConsumeSystemBars, int displayId, int syncSeqId) {}
|
||||
|
||||
@Override
|
||||
public void insetsChanged(InsetsState insetsState, boolean willMove, boolean willResize) {}
|
||||
|
@ -62,6 +62,7 @@ import android.graphics.Point;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.RectF;
|
||||
import android.hardware.HardwareBuffer;
|
||||
import android.os.Bundle;
|
||||
import android.os.IBinder;
|
||||
import android.os.RemoteException;
|
||||
import android.os.Trace;
|
||||
@ -243,7 +244,7 @@ public class TaskSnapshotWindow {
|
||||
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "TaskSnapshot#relayout");
|
||||
session.relayout(window, layoutParams, -1, -1, View.VISIBLE, 0,
|
||||
tmpFrames, tmpMergedConfiguration, surfaceControl, tmpInsetsState,
|
||||
tmpControls);
|
||||
tmpControls, new Bundle());
|
||||
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
|
||||
} catch (RemoteException e) {
|
||||
snapshotSurface.clearWindowSynced();
|
||||
@ -517,7 +518,7 @@ public class TaskSnapshotWindow {
|
||||
|
||||
private void reportDrawn() {
|
||||
try {
|
||||
mSession.finishDrawing(mWindow, null /* postDrawTransaction */);
|
||||
mSession.finishDrawing(mWindow, null /* postDrawTransaction */, Integer.MAX_VALUE);
|
||||
} catch (RemoteException e) {
|
||||
clearWindowSynced();
|
||||
}
|
||||
@ -534,7 +535,7 @@ public class TaskSnapshotWindow {
|
||||
@Override
|
||||
public void resized(ClientWindowFrames frames, boolean reportDraw,
|
||||
MergedConfiguration mergedConfiguration, boolean forceLayout,
|
||||
boolean alwaysConsumeSystemBars, int displayId) {
|
||||
boolean alwaysConsumeSystemBars, int displayId, int seqId) {
|
||||
if (mOuter != null) {
|
||||
mOuter.mSplashScreenExecutor.execute(() -> {
|
||||
if (mergedConfiguration != null
|
||||
|
108
services/core/java/com/android/server/wm/BLASTSync.md
Normal file
108
services/core/java/com/android/server/wm/BLASTSync.md
Normal file
@ -0,0 +1,108 @@
|
||||
= What does it mean for BLAST Sync to work? =
|
||||
There are two BLAST sync primitives on the server side, BLASTSyncEngine and applyWithNextDraw.
|
||||
Both of them are used to solve subclasses of this category of problem:
|
||||
1. You have some server side changes, which will trigger both WM/SysUI initiated SurfaceControl.Transactions,
|
||||
and also trigger a client redraw/update
|
||||
2. You want to synchronize the redraw of those clients with the application of those WM/SysUI side changes.
|
||||
|
||||
Put simply, you would like to synchronize the graphical effects of some WM changes with the graphical output of various windows
|
||||
observing those changes.
|
||||
|
||||
To talk about exactly what the primitives guarantee, we need to clarify what we mean by server side changes.
|
||||
In this document we will use a term syncable state to refer to any state mutated under the WindowManager lock
|
||||
which when observed by the client, produces a visible outcome in the produced frame.
|
||||
For example the current Configuration.
|
||||
|
||||
The guarantee provided by Server-side BLAST Sync Primitives is thus:
|
||||
Guarantee 1: If you make a set of changes to syncable state, at the same time that you begin a sync,
|
||||
then the first frame drawn by the client after observing the syncable state will be sent in a transaction
|
||||
to the consumer of the sync which was begun, rather than directly sent to SurfaceFlinger.
|
||||
|
||||
Here "at the same time" means in the same critical section (while holding the WM lock)
|
||||
For example this guarantee means that you can write code like:
|
||||
window.performConfigurationChange(someConfiguration)
|
||||
window.applyOnNextDraw(consumer)
|
||||
And the consumer will always be passed the first frame containing the configuration change. This can work with any
|
||||
syncable state not just Configuration.
|
||||
|
||||
The following is the protocol and additional requirements for BLAST sync, and an analysis of why it is correct. Due to time
|
||||
constraints we analyze it for a single window only (as this is actually the hard part).
|
||||
|
||||
Protocol requirements:
|
||||
Server protocol, precondition, begin a syncSeqId integer per window at 0:
|
||||
SA: Enter the critical section
|
||||
SB: Change syncable state, any number of times, prepare any number of syncs (and
|
||||
increment the seqId if a sync was prepared, assosciate it with the sync)
|
||||
SC: Leave the critical section
|
||||
SD: Send syncable state updates to the client, always paired with the current seqId
|
||||
SE: When the client calls finishDrawing, execute the consumer for each sync with
|
||||
seqId <= the seqId which the client passed to finishDrawing
|
||||
Client protocol:
|
||||
CA: Observe state and seqid changes up until a fixed frame deadline, then execute performTraversals
|
||||
CB: If the seqId is incremeneted at the time of the frame deadline, configure the renderer to
|
||||
redirect the next draw in to a transaction, record the seqId at the time
|
||||
CC: When the draw is finished, send the transaction containing the draw to WM with the
|
||||
previously recorded seqId
|
||||
Additional requirements/assumptions:
|
||||
1. The server may only send changes to the syncable state paired with the seqId. The client may
|
||||
only receive them together (e.g. not from other sources)
|
||||
2. In between changing and sending syncable state, the lock must be released and acquired again
|
||||
3. The client wont draw a frame reflecting syncable state changes without passing through "performTraversals"
|
||||
4. Drawing never fails
|
||||
5. There are no blocking calls between the client or the server
|
||||
|
||||
Note that the server can begin the protocol at any time, so it may be possible for the client to proceed through
|
||||
phases SA, SB, SC, and SD multiple times before the client receives any messages.
|
||||
|
||||
To show that the guarantee can't be violated, we use a notation of sequences, where we describe interleaving
|
||||
of protocol events. For duplicate events, we attach a number, e.g. SA_1, SA_2.
|
||||
|
||||
We proceed by contradiction, imagine there was some sequence (..., SA_N, ...) for which the guarantee was
|
||||
not upheld. This means that either
|
||||
1. finishDrawing with the assosciate seqId was never sent to the server OR
|
||||
2. It was sent too late (after the first frame was sent to SF instead of WM) OR
|
||||
3. It was sent too early (not containing the state changes originating with SA_N)
|
||||
If it was sent neither too late, nor too early, and contained the assosciated seqId, then protocol step SE
|
||||
says that the frame will be passed to the consumer and we uphold our guarantee.
|
||||
|
||||
The first case is impossible because step SD says that the server always sends the seqId if a sync was prepared.
|
||||
If we send it the client must receive it. Since we only increment the seqId, and the client only takes the
|
||||
seqId from us (requirement 1, protocol step SB), the received ID must be higher than the clients previous seqId.
|
||||
CA says that performTraversals will execute, and CB says that when it does, if the seqId is higher than before
|
||||
it will schedule the render to sync. Requirement 4 says drawing never fails, so CC must execute, and so we will always
|
||||
eventually send every seqId (or a seqId > than it) back to the server.
|
||||
|
||||
It also can't be sent too late. By requirement 2 we must release and acquire the lock
|
||||
after after changing and before emitting syncable state changes. This means it's guaranteed
|
||||
that even in an ordering like AcquireLock, ChangeState, PrepareSync, Release lock we can't
|
||||
send the state changes before prepareSync, and so they can always include at least the seqId
|
||||
assosciated with changestate (or a later one).
|
||||
Since we only receive the SeqId with the State changes (requirement 1),
|
||||
and we wont draw state changes without passing through perform traversals (requirement 3) the first frame
|
||||
containing the state change must have been generated by a call to performTraversals which also observed
|
||||
the seqId change, and so it will appropriately configure the renderer.
|
||||
|
||||
By the same argument it can't be sent too early! Since we only send seqIds we receive from the server,
|
||||
and we only send seqIds after completing a drawing pass of the assosciated state.
|
||||
|
||||
So we can see that no matter at what time the server makes syncable state changes, the first frame will
|
||||
always be delivered to the draw handler. Assuming that the client and server uphold this protocol and these
|
||||
requirements.
|
||||
|
||||
The trickiest part of the implementation at the moment is due to assosciating seqId. Currently we send one of the most
|
||||
most important pieces of syncable state (configuration) over multiple channels. Namely ClientTransaction
|
||||
and MSG_RESIZED. The ordering of these relative to sync preparation in server code is undefined, in fact we have cases like
|
||||
this all the time:
|
||||
acquireLock()
|
||||
changeConfiguration()
|
||||
// time passes, but still in critical section
|
||||
prepareSync()
|
||||
releaseLock()
|
||||
This is exactly the kind of case Guarantee 1 mentions as an example. In previous incarnations of the code this worked
|
||||
because relayoutWindow needed to acquire the same lock and relayoutWindow was a necessary part of completing sync.
|
||||
|
||||
Now that we have no barrier, that could create issues, because at the time we change configuration (and send the change
|
||||
to the client via ClientTransaction), we haven't even incremented the seqId yet, and so how can the client observe it
|
||||
at the same time as the state? We solve this by pushing all client communication through a handler thread that has to
|
||||
acquire the lock. This ensures we uphold requirement 2.
|
||||
|
@ -232,14 +232,14 @@ class Session extends IWindowSession.Stub implements IBinder.DeathRecipient {
|
||||
int requestedWidth, int requestedHeight, int viewFlags, int flags,
|
||||
ClientWindowFrames outFrames, MergedConfiguration mergedConfiguration,
|
||||
SurfaceControl outSurfaceControl, InsetsState outInsetsState,
|
||||
InsetsSourceControl[] outActiveControls) {
|
||||
InsetsSourceControl[] outActiveControls, Bundle outSyncSeqIdBundle) {
|
||||
if (false) Slog.d(TAG_WM, ">>>>>> ENTERED relayout from "
|
||||
+ Binder.getCallingPid());
|
||||
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, mRelayoutTag);
|
||||
int res = mService.relayoutWindow(this, window, attrs,
|
||||
requestedWidth, requestedHeight, viewFlags, flags,
|
||||
outFrames, mergedConfiguration, outSurfaceControl, outInsetsState,
|
||||
outActiveControls);
|
||||
outActiveControls, outSyncSeqIdBundle);
|
||||
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
|
||||
if (false) Slog.d(TAG_WM, "<<<<<< EXITING relayout to "
|
||||
+ Binder.getCallingPid());
|
||||
@ -265,9 +265,9 @@ class Session extends IWindowSession.Stub implements IBinder.DeathRecipient {
|
||||
|
||||
@Override
|
||||
public void finishDrawing(IWindow window,
|
||||
@Nullable SurfaceControl.Transaction postDrawTransaction) {
|
||||
@Nullable SurfaceControl.Transaction postDrawTransaction, int seqId) {
|
||||
if (DEBUG) Slog.v(TAG_WM, "IWindow finishDrawing called for " + window);
|
||||
mService.finishDrawingWindow(this, window, postDrawTransaction);
|
||||
mService.finishDrawingWindow(this, window, postDrawTransaction, seqId);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -2192,7 +2192,7 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
int requestedWidth, int requestedHeight, int viewVisibility, int flags,
|
||||
ClientWindowFrames outFrames, MergedConfiguration mergedConfiguration,
|
||||
SurfaceControl outSurfaceControl, InsetsState outInsetsState,
|
||||
InsetsSourceControl[] outActiveControls) {
|
||||
InsetsSourceControl[] outActiveControls, Bundle outSyncIdBundle) {
|
||||
Arrays.fill(outActiveControls, null);
|
||||
int result = 0;
|
||||
boolean configChanged;
|
||||
@ -2617,7 +2617,7 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
}
|
||||
|
||||
void finishDrawingWindow(Session session, IWindow client,
|
||||
@Nullable SurfaceControl.Transaction postDrawTransaction) {
|
||||
@Nullable SurfaceControl.Transaction postDrawTransaction, int seqId) {
|
||||
if (postDrawTransaction != null) {
|
||||
postDrawTransaction.sanitize();
|
||||
}
|
||||
@ -2628,7 +2628,7 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
WindowState win = windowForClientLocked(session, client, false);
|
||||
ProtoLog.d(WM_DEBUG_ADD_REMOVE, "finishDrawingWindow: %s mDrawState=%s",
|
||||
win, (win != null ? win.mWinAnimator.drawStateToString() : "null"));
|
||||
if (win != null && win.finishDrawing(postDrawTransaction)) {
|
||||
if (win != null && win.finishDrawing(postDrawTransaction, seqId)) {
|
||||
if (win.hasWallpaper()) {
|
||||
win.getDisplayContent().pendingLayoutChanges |=
|
||||
WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
|
||||
|
@ -3946,7 +3946,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
|
||||
|
||||
try {
|
||||
mClient.resized(mClientWindowFrames, reportDraw, mLastReportedConfiguration,
|
||||
forceRelayout, alwaysConsumeSystemBars, displayId);
|
||||
forceRelayout, alwaysConsumeSystemBars, displayId, Integer.MAX_VALUE);
|
||||
if (drawPending && reportOrientation && mOrientationChanging) {
|
||||
mOrientationChangeRedrawRequestTime = SystemClock.elapsedRealtime();
|
||||
ProtoLog.v(WM_DEBUG_ORIENTATION,
|
||||
@ -5938,7 +5938,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
|
||||
super.finishSync(outMergedTransaction, cancel);
|
||||
}
|
||||
|
||||
boolean finishDrawing(SurfaceControl.Transaction postDrawTransaction) {
|
||||
boolean finishDrawing(SurfaceControl.Transaction postDrawTransaction, int syncSeqId) {
|
||||
if (mOrientationChangeRedrawRequestTime > 0) {
|
||||
final long duration =
|
||||
SystemClock.elapsedRealtime() - mOrientationChangeRedrawRequestTime;
|
||||
@ -5985,7 +5985,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
|
||||
|
||||
void immediatelyNotifyBlastSync() {
|
||||
prepareDrawHandlers();
|
||||
finishDrawing(null);
|
||||
finishDrawing(null, Integer.MAX_VALUE);
|
||||
mWmService.mH.removeMessages(WINDOW_STATE_BLAST_SYNC_TIMEOUT, this);
|
||||
if (!useBLASTSync()) return;
|
||||
}
|
||||
|
@ -44,7 +44,7 @@ public class TestIWindow extends IWindow.Stub {
|
||||
@Override
|
||||
public void resized(ClientWindowFrames frames, boolean reportDraw,
|
||||
MergedConfiguration mergedConfig, boolean forceLayout, boolean alwaysConsumeSystemBars,
|
||||
int displayId) throws RemoteException {
|
||||
int displayId, int seqId) throws RemoteException {
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -692,7 +692,8 @@ public class TransitionTests extends WindowTestsBase {
|
||||
statusBar.mWinAnimator.mDrawState = WindowStateAnimator.DRAW_PENDING;
|
||||
final SurfaceControl.Transaction postDrawTransaction =
|
||||
mock(SurfaceControl.Transaction.class);
|
||||
final boolean layoutNeeded = statusBar.finishDrawing(postDrawTransaction);
|
||||
final boolean layoutNeeded = statusBar.finishDrawing(postDrawTransaction,
|
||||
Integer.MAX_VALUE);
|
||||
assertFalse(layoutNeeded);
|
||||
|
||||
transactionCommittedListener.onTransactionCommitted();
|
||||
@ -742,7 +743,7 @@ public class TransitionTests extends WindowTestsBase {
|
||||
player.finish();
|
||||
|
||||
// The controller should be cleared if the target windows are drawn.
|
||||
statusBar.finishDrawing(mWm.mTransactionFactory.get());
|
||||
statusBar.finishDrawing(mWm.mTransactionFactory.get(), Integer.MAX_VALUE);
|
||||
statusBar.setOrientationChanging(false);
|
||||
assertNull(mDisplayContent.getAsyncRotationController());
|
||||
}
|
||||
|
@ -504,7 +504,7 @@ public class WindowStateTests extends WindowTestsBase {
|
||||
assertTrue(win.useBLASTSync());
|
||||
final SurfaceControl.Transaction drawT = new StubTransaction();
|
||||
win.prepareDrawHandlers();
|
||||
assertTrue(win.finishDrawing(drawT));
|
||||
assertTrue(win.finishDrawing(drawT, Integer.MAX_VALUE));
|
||||
assertEquals(drawT, handledT[0]);
|
||||
assertFalse(win.useBLASTSync());
|
||||
|
||||
@ -693,7 +693,7 @@ public class WindowStateTests extends WindowTestsBase {
|
||||
doThrow(new RemoteException("test")).when(win.mClient).resized(any() /* frames */,
|
||||
anyBoolean() /* reportDraw */, any() /* mergedConfig */,
|
||||
anyBoolean() /* forceLayout */, anyBoolean() /* alwaysConsumeSystemBars */,
|
||||
anyInt() /* displayId */);
|
||||
anyInt() /* displayId */, anyInt() /* seqId */);
|
||||
} catch (RemoteException ignored) {
|
||||
}
|
||||
win.reportResized();
|
||||
|
Loading…
x
Reference in New Issue
Block a user