Merge "Prevent windows from drawing if they're in an active sync set" into tm-qpr-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
7534f6e76f
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -552,4 +552,9 @@ public class WindowlessWindowManager implements IWindowSession {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean cancelDraw(IWindow window) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user