diff options
| -rw-r--r-- | core/java/android/view/SurfaceControlViewHost.java | 2 | ||||
| -rw-r--r-- | core/java/android/view/ViewRootImpl.java | 69 | ||||
| -rw-r--r-- | core/java/android/view/ViewTreeObserver.java | 19 |
3 files changed, 79 insertions, 11 deletions
diff --git a/core/java/android/view/SurfaceControlViewHost.java b/core/java/android/view/SurfaceControlViewHost.java index d75ff2fc7dc2..5721fa6dd11a 100644 --- a/core/java/android/view/SurfaceControlViewHost.java +++ b/core/java/android/view/SurfaceControlViewHost.java @@ -422,7 +422,7 @@ public class SurfaceControlViewHost { public void relayout(WindowManager.LayoutParams attrs, WindowlessWindowManager.ResizeCompleteCallback callback) { mViewRoot.setLayoutParams(attrs, false); - mViewRoot.setReportNextDraw(true /* syncBuffer */); + mViewRoot.setReportNextDraw(true /* syncBuffer */, "scvh_relayout"); mWm.setCompletionCallback(mViewRoot.mWindow.asBinder(), callback); } diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index e1966a0f1177..4d094ffd287f 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -587,8 +587,21 @@ public final class ViewRootImpl implements ViewParent, int mContentCaptureEnabled = CONTENT_CAPTURE_ENABLED_NOT_CHECKED; boolean mPerformContentCapture; - boolean mReportNextDraw; + /** Set only while mReportNextDraw=true, indicating the last reason that was triggered */ + String mLastReportNextDrawReason; + /** The reaason the last call to performDraw() returned false */ + String mLastPerformDrawSkippedReason; + /** The reason the last call to performTraversals() returned without drawing */ + String mLastPerformTraversalsSkipDrawReason; + /** The state of the local sync, if one is in progress. Can be one of the states below. */ + int mLocalSyncState; + + // The possible states of the local sync, see createSyncIfNeeded() + private final int LOCAL_SYNC_NONE = 0; + private final int LOCAL_SYNC_PENDING = 1; + private final int LOCAL_SYNC_RETURNED = 2; + private final int LOCAL_SYNC_MERGED = 3; /** * Set whether the draw should send the buffer to system server. When set to true, VRI will @@ -1836,7 +1849,7 @@ public final class ViewRootImpl implements ViewParent, mSyncSeqId = args.argi4 > mSyncSeqId ? args.argi4 : mSyncSeqId; if (msg == MSG_RESIZED_REPORT) { - reportNextDraw(); + reportNextDraw("resized"); } if (mView != null && (frameChanged || configChanged)) { @@ -2741,6 +2754,8 @@ public final class ViewRootImpl implements ViewParent, } private void performTraversals() { + mLastPerformTraversalsSkipDrawReason = null; + // cache mView since it is used so much below... final View host = mView; if (DBG) { @@ -2750,12 +2765,14 @@ public final class ViewRootImpl implements ViewParent, } if (host == null || !mAdded) { + mLastPerformTraversalsSkipDrawReason = host == null ? "no_host" : "not_added"; return; } mIsInTraversal = true; mWillDrawSoon = true; boolean cancelDraw = false; + String cancelReason = null; boolean isSyncRequest = false; boolean windowSizeMayChange = false; @@ -3038,13 +3055,14 @@ public final class ViewRootImpl implements ViewParent, relayoutResult = relayoutWindow(params, viewVisibility, insetsPending); cancelDraw = (relayoutResult & RELAYOUT_RES_CANCEL_AND_REDRAW) == RELAYOUT_RES_CANCEL_AND_REDRAW; + cancelReason = "relayout"; final boolean dragResizing = mPendingDragResizing; if (mSyncSeqId > mLastSyncSeqId) { mLastSyncSeqId = mSyncSeqId; if (DEBUG_BLAST) { Log.d(mTag, "Relayout called with blastSync"); } - reportNextDraw(); + reportNextDraw("relayout"); mSyncBuffer = true; isSyncRequest = true; if (!cancelDraw) { @@ -3147,6 +3165,7 @@ public final class ViewRootImpl implements ViewParent, } } catch (OutOfResourcesException e) { handleOutOfResourcesException(e); + mLastPerformTraversalsSkipDrawReason = "oom_initialize_renderer"; return; } } @@ -3184,6 +3203,7 @@ public final class ViewRootImpl implements ViewParent, mAttachInfo.mThreadedRenderer.updateSurface(mSurface); } catch (OutOfResourcesException e) { handleOutOfResourcesException(e); + mLastPerformTraversalsSkipDrawReason = "oom_update_surface"; return; } } @@ -3349,6 +3369,7 @@ public final class ViewRootImpl implements ViewParent, if (mCheckIfCanDraw) { try { cancelDraw = mWindowSession.cancelDraw(mWindow); + cancelReason = "wm_sync"; if (DEBUG_BLAST) { Log.d(mTag, "cancelDraw returned " + cancelDraw); } @@ -3571,19 +3592,21 @@ public final class ViewRootImpl implements ViewParent, mImeFocusController.onTraversal(hasWindowFocus, mWindowAttributes); if ((relayoutResult & WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME) != 0) { - reportNextDraw(); + reportNextDraw("first_relayout"); } mCheckIfCanDraw = isSyncRequest || cancelDraw; - boolean cancelAndRedraw = - mAttachInfo.mTreeObserver.dispatchOnPreDraw() || (cancelDraw && mDrewOnceForSync); + boolean cancelDueToPreDrawListener = mAttachInfo.mTreeObserver.dispatchOnPreDraw(); + boolean cancelAndRedraw = cancelDueToPreDrawListener + || (cancelDraw && mDrewOnceForSync); if (!cancelAndRedraw) { createSyncIfNeeded(); mDrewOnceForSync = true; } if (!isViewVisible) { + mLastPerformTraversalsSkipDrawReason = "view_not_visible"; if (mPendingTransitions != null && mPendingTransitions.size() > 0) { for (int i = 0; i < mPendingTransitions.size(); ++i) { mPendingTransitions.get(i).endChangingAnimations(); @@ -3595,6 +3618,9 @@ public final class ViewRootImpl implements ViewParent, mSyncBufferCallback.onBufferReady(null); } } else if (cancelAndRedraw) { + mLastPerformTraversalsSkipDrawReason = cancelDueToPreDrawListener + ? "predraw_" + mAttachInfo.mTreeObserver.getLastDispatchOnPreDrawCanceledReason() + : "cancel_" + cancelReason; // Try again scheduleTraversals(); } else { @@ -3618,11 +3644,13 @@ public final class ViewRootImpl implements ViewParent, if (!cancelAndRedraw) { mReportNextDraw = false; + mLastReportNextDrawReason = null; mSyncBufferCallback = null; mSyncBuffer = false; if (isInLocalSync()) { mSyncGroup.markSyncReady(); mSyncGroup = null; + mLocalSyncState = LOCAL_SYNC_NONE; } } } @@ -3634,12 +3662,15 @@ public final class ViewRootImpl implements ViewParent, } final int seqId = mSyncSeqId; + mLocalSyncState = LOCAL_SYNC_PENDING; mSyncGroup = new SurfaceSyncGroup(transaction -> { + mLocalSyncState = LOCAL_SYNC_RETURNED; // Callback will be invoked on executor thread so post to main thread. mHandler.postAtFrontOfQueue(() -> { if (transaction != null) { mSurfaceChangedTransaction.merge(transaction); } + mLocalSyncState = LOCAL_SYNC_MERGED; reportDrawFinished(seqId); }); }); @@ -4353,9 +4384,12 @@ public final class ViewRootImpl implements ViewParent, } private boolean performDraw() { + mLastPerformDrawSkippedReason = null; if (mAttachInfo.mDisplayState == Display.STATE_OFF && !mReportNextDraw) { + mLastPerformDrawSkippedReason = "screen_off"; return false; } else if (mView == null) { + mLastPerformDrawSkippedReason = "no_root_view"; return false; } @@ -8458,6 +8492,21 @@ public final class ViewRootImpl implements ViewParent, if (mTraversalScheduled) { writer.println(innerPrefix + " (barrier=" + mTraversalBarrier + ")"); } + writer.println(innerPrefix + "mReportNextDraw=" + mReportNextDraw); + if (mReportNextDraw) { + writer.println(innerPrefix + " (reason=" + mLastReportNextDrawReason + ")"); + } + if (mLastPerformTraversalsSkipDrawReason != null) { + writer.println(innerPrefix + "mLastPerformTraversalsFailedReason=" + + mLastPerformTraversalsSkipDrawReason); + } + if (mLastPerformDrawSkippedReason != null) { + writer.println(innerPrefix + "mLastPerformDrawFailedReason=" + + mLastPerformDrawSkippedReason); + } + if (mLocalSyncState != LOCAL_SYNC_NONE) { + writer.println(innerPrefix + "mLocalSyncState=" + mLocalSyncState); + } writer.println(innerPrefix + "mIsAmbientMode=" + mIsAmbientMode); writer.println(innerPrefix + "mUnbufferedInputSource=" + Integer.toHexString(mUnbufferedInputSource)); @@ -9958,11 +10007,12 @@ public final class ViewRootImpl implements ViewParent, } } - private void reportNextDraw() { + private void reportNextDraw(String reason) { if (DEBUG_BLAST) { Log.d(mTag, "reportNextDraw " + Debug.getCallers(5)); } mReportNextDraw = true; + mLastReportNextDrawReason = reason; } /** @@ -9975,11 +10025,12 @@ public final class ViewRootImpl implements ViewParent, * @param syncBuffer If true, the transaction that contains the buffer from the draw should be * sent to system to be synced. If false, VRI will not try to sync the buffer, * but only report back that a buffer was drawn. + * @param reason A debug string indicating the reason for reporting the next draw * @hide */ - public void setReportNextDraw(boolean syncBuffer) { + public void setReportNextDraw(boolean syncBuffer, String reason) { mSyncBuffer = syncBuffer; - reportNextDraw(); + reportNextDraw(reason); invalidate(); } diff --git a/core/java/android/view/ViewTreeObserver.java b/core/java/android/view/ViewTreeObserver.java index 2c077c3e9e63..c9526fde27df 100644 --- a/core/java/android/view/ViewTreeObserver.java +++ b/core/java/android/view/ViewTreeObserver.java @@ -74,6 +74,9 @@ public final class ViewTreeObserver { * that the listener will be immediately called. */ private boolean mWindowShown; + // The reason that the last call to dispatchOnPreDraw() returned true to cancel and redraw + private String mLastDispatchOnPreDrawCanceledReason; + private boolean mAlive = true; /** @@ -1161,6 +1164,7 @@ public final class ViewTreeObserver { */ @SuppressWarnings("unchecked") public final boolean dispatchOnPreDraw() { + mLastDispatchOnPreDrawCanceledReason = null; boolean cancelDraw = false; final CopyOnWriteArray<OnPreDrawListener> listeners = mOnPreDrawListeners; if (listeners != null && listeners.size() > 0) { @@ -1168,7 +1172,11 @@ public final class ViewTreeObserver { try { int count = access.size(); for (int i = 0; i < count; i++) { - cancelDraw |= !(access.get(i).onPreDraw()); + final OnPreDrawListener preDrawListener = access.get(i); + cancelDraw |= !(preDrawListener.onPreDraw()); + if (cancelDraw) { + mLastDispatchOnPreDrawCanceledReason = preDrawListener.getClass().getName(); + } } } finally { listeners.end(); @@ -1178,6 +1186,15 @@ public final class ViewTreeObserver { } /** + * @return the reason that the last call to dispatchOnPreDraw() returned true to cancel the + * current draw, or null if the last call did not cancel. + * @hide + */ + final String getLastDispatchOnPreDrawCanceledReason() { + return mLastDispatchOnPreDrawCanceledReason; + } + + /** * Notifies registered listeners that the window is now shown * @hide */ |