Merge "Prevent windows from drawing if they're in an active sync set" into tm-qpr-dev

This commit is contained in:
Chavi Weingarten
2022-06-21 21:52:38 +00:00
committed by Android (Google) Code Review
7 changed files with 80 additions and 1 deletions

View File

@@ -384,4 +384,9 @@ interface IWindowSession {
* Clears a touchable region set by {@link #setInsets}.
*/
void clearTouchableRegion(IWindow window);
/**
* Returns whether this window needs to cancel draw and retry later.
*/
boolean cancelDraw(IWindow window);
}

View File

@@ -84,6 +84,7 @@ import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_ADDITIONAL
import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
import static android.view.WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY;
import static android.view.WindowManagerGlobal.RELAYOUT_RES_CANCEL_AND_REDRAW;
import static android.view.WindowManagerGlobal.RELAYOUT_RES_CONSUME_ALWAYS_SYSTEM_BARS;
import static android.view.WindowManagerGlobal.RELAYOUT_RES_SURFACE_CHANGED;
import static android.view.inputmethod.InputMethodEditorTraceProto.InputMethodClientsTraceProto.ClientSideProto.IME_FOCUS_CONTROLLER;
@@ -601,6 +602,14 @@ public final class ViewRootImpl implements ViewParent,
*/
private boolean mSyncBuffer = false;
/**
* Flag to determine whether the client needs to check with WMS if it can draw. WMS will notify
* the client that it can't draw if we're still in the middle of a sync set that includes this
* window. Once the sync is complete, the window can resume drawing. This is to ensure we don't
* deadlock the client by trying to request draws when there may not be any buffers available.
*/
private boolean mCheckIfCanDraw = false;
int mSyncSeqId = 0;
int mLastSyncSeqId = 0;
@@ -2700,6 +2709,9 @@ public final class ViewRootImpl implements ViewParent,
mIsInTraversal = true;
mWillDrawSoon = true;
boolean cancelDraw = false;
boolean isSyncRequest = false;
boolean windowSizeMayChange = false;
WindowManager.LayoutParams lp = mWindowAttributes;
@@ -2969,6 +2981,8 @@ public final class ViewRootImpl implements ViewParent,
mViewFrameInfo.flags |= FrameInfo.FLAG_WINDOW_VISIBILITY_CHANGED;
}
relayoutResult = relayoutWindow(params, viewVisibility, insetsPending);
cancelDraw = (relayoutResult & RELAYOUT_RES_CANCEL_AND_REDRAW)
== RELAYOUT_RES_CANCEL_AND_REDRAW;
final boolean dragResizing = mPendingDragResizing;
if (mSyncSeqId > mLastSyncSeqId) {
mLastSyncSeqId = mSyncSeqId;
@@ -2977,6 +2991,7 @@ public final class ViewRootImpl implements ViewParent,
}
reportNextDraw();
mSyncBuffer = true;
isSyncRequest = true;
}
final boolean surfaceControlChanged =
@@ -3265,6 +3280,19 @@ public final class ViewRootImpl implements ViewParent,
}
}
} else {
// If a relayout isn't going to happen, we still need to check if this window can draw
// when mCheckIfCanDraw is set. This is because it means we had a sync in the past, but
// have not been told by WMS that the sync is complete and that we can continue to draw
if (mCheckIfCanDraw) {
try {
cancelDraw = mWindowSession.cancelDraw(mWindow);
if (DEBUG_BLAST) {
Log.d(mTag, "cancelDraw returned " + cancelDraw);
}
} catch (RemoteException e) {
}
}
// Not the first pass and no window/insets/visibility change but the window
// may have moved and we need check that and if so to update the left and right
// in the attach info. We translate only the window frame since on window move
@@ -3483,7 +3511,9 @@ public final class ViewRootImpl implements ViewParent,
reportNextDraw();
}
boolean cancelAndRedraw = mAttachInfo.mTreeObserver.dispatchOnPreDraw();
mCheckIfCanDraw = isSyncRequest || cancelDraw;
boolean cancelAndRedraw = mAttachInfo.mTreeObserver.dispatchOnPreDraw() || cancelDraw;
if (!cancelAndRedraw) {
createSyncIfNeeded();
}

View File

@@ -82,6 +82,11 @@ public final class WindowManagerGlobal {
*/
public static final int RELAYOUT_RES_CONSUME_ALWAYS_SYSTEM_BARS = 1 << 3;
/**
* The window manager has told the window it cannot draw this frame and should retry again.
*/
public static final int RELAYOUT_RES_CANCEL_AND_REDRAW = 1 << 4;
/**
* Flag for relayout: the client will be later giving
* internal insets; as a result, the window will not impact other window

View File

@@ -552,4 +552,9 @@ public class WindowlessWindowManager implements IWindowSession {
}
}
}
@Override
public boolean cancelDraw(IWindow window) {
return false;
}
}

View File

@@ -249,6 +249,11 @@ class Session extends IWindowSession.Stub implements IBinder.DeathRecipient {
mService.setWillReplaceWindows(appToken, childrenOnly);
}
@Override
public boolean cancelDraw(IWindow window) {
return mService.cancelDraw(this, window);
}
@Override
public int relayout(IWindow window, WindowManager.LayoutParams attrs,
int requestedWidth, int requestedHeight, int viewFlags, int flags,

View File

@@ -89,6 +89,7 @@ import static android.view.WindowManager.REMOVE_CONTENT_MODE_UNDEFINED;
import static android.view.WindowManager.TRANSIT_NONE;
import static android.view.WindowManager.TRANSIT_RELAUNCH;
import static android.view.WindowManagerGlobal.ADD_OKAY;
import static android.view.WindowManagerGlobal.RELAYOUT_RES_CANCEL_AND_REDRAW;
import static android.view.WindowManagerGlobal.RELAYOUT_RES_SURFACE_CHANGED;
import static android.view.WindowManagerPolicyConstants.NAV_BAR_INVALID;
import static android.view.WindowManagerPolicyConstants.TYPE_LAYER_MULTIPLIER;
@@ -2212,6 +2213,20 @@ public class WindowManagerService extends IWindowManager.Stub
== PackageManager.PERMISSION_GRANTED;
}
/**
* Returns whether this window can proceed with drawing or needs to retry later.
*/
public boolean cancelDraw(Session session, IWindow client) {
synchronized (mGlobalLock) {
final WindowState win = windowForClientLocked(session, client, false);
if (win == null) {
return false;
}
return win.cancelAndRedraw();
}
}
public int relayoutWindow(Session session, IWindow client, LayoutParams attrs,
int requestedWidth, int requestedHeight, int viewVisibility, int flags,
ClientWindowFrames outFrames, MergedConfiguration mergedConfiguration,
@@ -2228,6 +2243,11 @@ public class WindowManagerService extends IWindowManager.Stub
if (win == null) {
return 0;
}
if (win.cancelAndRedraw()) {
result |= RELAYOUT_RES_CANCEL_AND_REDRAW;
}
final DisplayContent displayContent = win.getDisplayContent();
final DisplayPolicy displayPolicy = displayContent.getDisplayPolicy();
@@ -2530,6 +2550,7 @@ public class WindowManagerService extends IWindowManager.Stub
win.mLastSeqIdSentToRelayout = win.mSyncSeqId;
outSyncIdBundle.putInt("seqid", win.mSyncSeqId);
win.mAlreadyRequestedSync = true;
} else {
outSyncIdBundle.putInt("seqid", -1);
}

View File

@@ -391,6 +391,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
*/
int mSyncSeqId = 0;
int mLastSeqIdSentToRelayout = 0;
boolean mAlreadyRequestedSync;
/**
* {@code true} when the client was still drawing for sync when the sync-set was finished or
@@ -4406,6 +4407,8 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
pw.println(prefix + "Requested visibilities: " + visibilityString);
}
}
pw.println(prefix + "mAlreadyRequestedSync=" + mAlreadyRequestedSync);
}
@Override
@@ -5933,6 +5936,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
if (mSyncState == SYNC_STATE_WAITING_FOR_DRAW && mRedrawForSyncReported) {
mClientWasDrawingForSync = true;
}
mAlreadyRequestedSync = false;
super.finishSync(outMergedTransaction, cancel);
}
@@ -6199,4 +6203,8 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
@WindowTraceLogLevel int logLevel) {
dumpDebug(proto, fieldId, logLevel);
}
public boolean cancelAndRedraw() {
return mSyncState != SYNC_STATE_NONE && mAlreadyRequestedSync;
}
}