Merge "WMS/ViewRoot: Prepare for Async BLAST Sync [1/N]" into tm-dev
This commit is contained in:
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user