diff options
| author | 2022-12-06 05:46:04 +0000 | |
|---|---|---|
| committer | 2022-12-06 05:46:04 +0000 | |
| commit | 80c145dca032eb727292abfe3b02e3b0df3777ff (patch) | |
| tree | 4e36d7895644ab24b616a5b4e3e56b222c7ad295 | |
| parent | 73420439bcfdbca4672a2bc9f55e9144bfe22664 (diff) | |
| parent | adfbe26af2d63684b73af8973de78a00d663dcb2 (diff) | |
Merge "Reduce unnecessary measure" into tm-qpr-dev
| -rw-r--r-- | core/java/android/view/ViewRootImpl.java | 71 |
1 files changed, 63 insertions, 8 deletions
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index b4698dee6019..d21ba014e166 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -77,6 +77,7 @@ import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE; import static android.view.WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING; import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD; +import static android.view.WindowManager.LayoutParams.TYPE_NOTIFICATION_SHADE; 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; @@ -502,6 +503,13 @@ public final class ViewRootImpl implements ViewParent, Region mTouchableRegion; Region mPreviousTouchableRegion; + private int mMeasuredWidth; + private int mMeasuredHeight; + + // This indicates that we've already known the window size but without measuring the views. + // If this is true, we must measure the views before laying out them. + private boolean mViewMeasureDeferred; + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) int mWidth; @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) @@ -2566,7 +2574,8 @@ public final class ViewRootImpl implements ViewParent, } private boolean measureHierarchy(final View host, final WindowManager.LayoutParams lp, - final Resources res, final int desiredWindowWidth, final int desiredWindowHeight) { + final Resources res, final int desiredWindowWidth, final int desiredWindowHeight, + boolean forRootSizeOnly) { int childWidthMeasureSpec; int childHeightMeasureSpec; boolean windowSizeMayChange = false; @@ -2622,7 +2631,15 @@ public final class ViewRootImpl implements ViewParent, lp.privateFlags); childHeightMeasureSpec = getRootMeasureSpec(desiredWindowHeight, lp.height, lp.privateFlags); - performMeasure(childWidthMeasureSpec, childHeightMeasureSpec); + if (!forRootSizeOnly || !setMeasuredRootSizeFromSpec( + childWidthMeasureSpec, childHeightMeasureSpec)) { + performMeasure(childWidthMeasureSpec, childHeightMeasureSpec); + } else { + // We already know how big the window should be before measuring the views. + // We can measure the views before laying out them. This is to avoid unnecessary + // measure. + mViewMeasureDeferred = true; + } if (mWidth != host.getMeasuredWidth() || mHeight != host.getMeasuredHeight()) { windowSizeMayChange = true; } @@ -2638,6 +2655,25 @@ public final class ViewRootImpl implements ViewParent, } /** + * Sets the measured root size for requesting the window frame. + * + * @param widthMeasureSpec contains the size and the mode of the width. + * @param heightMeasureSpec contains the size and the mode of the height. + * @return {@code true} if we actually set the measured size; {@code false} otherwise. + */ + private boolean setMeasuredRootSizeFromSpec(int widthMeasureSpec, int heightMeasureSpec) { + final int widthMode = MeasureSpec.getMode(widthMeasureSpec); + final int heightMode = MeasureSpec.getMode(heightMeasureSpec); + if (widthMode != MeasureSpec.EXACTLY || heightMode != MeasureSpec.EXACTLY) { + // We don't know the exact size. We need to measure the hierarchy to know that. + return false; + } + mMeasuredWidth = MeasureSpec.getSize(widthMeasureSpec); + mMeasuredHeight = MeasureSpec.getSize(heightMeasureSpec); + return true; + } + + /** * Modifies the input matrix such that it maps view-local coordinates to * on-screen coordinates. * @@ -2724,6 +2760,14 @@ public final class ViewRootImpl implements ViewParent, || lp.type == TYPE_VOLUME_OVERLAY; } + /** + * @return {@code true} if we should reduce unnecessary measure for the window. + * TODO(b/260382739): Apply this to all windows. + */ + private static boolean shouldOptimizeMeasure(final WindowManager.LayoutParams lp) { + return lp.type == TYPE_NOTIFICATION_SHADE; + } + private Rect getWindowBoundsInsetSystemBars() { final Rect bounds = new Rect( mContext.getResources().getConfiguration().windowConfiguration.getBounds()); @@ -2774,6 +2818,7 @@ public final class ViewRootImpl implements ViewParent, mAppVisibilityChanged = false; final boolean viewUserVisibilityChanged = !mFirst && ((mViewVisibility == View.VISIBLE) != (viewVisibility == View.VISIBLE)); + final boolean shouldOptimizeMeasure = shouldOptimizeMeasure(lp); WindowManager.LayoutParams params = null; CompatibilityInfo compatibilityInfo = @@ -2895,7 +2940,7 @@ public final class ViewRootImpl implements ViewParent, // Ask host how big it wants to be windowSizeMayChange |= measureHierarchy(host, lp, mView.getContext().getResources(), - desiredWindowWidth, desiredWindowHeight); + desiredWindowWidth, desiredWindowHeight, shouldOptimizeMeasure); } if (collectViewAttributes()) { @@ -2935,8 +2980,8 @@ public final class ViewRootImpl implements ViewParent, // we don't need to go through two layout passes when things // change due to fitting system windows, which can happen a lot. windowSizeMayChange |= measureHierarchy(host, lp, - mView.getContext().getResources(), - desiredWindowWidth, desiredWindowHeight); + mView.getContext().getResources(), desiredWindowWidth, desiredWindowHeight, + shouldOptimizeMeasure); } } @@ -3351,6 +3396,13 @@ public final class ViewRootImpl implements ViewParent, maybeHandleWindowMove(frame); } + if (mViewMeasureDeferred) { + // It's time to measure the views since we are going to layout them. + performMeasure( + MeasureSpec.makeMeasureSpec(frame.width(), MeasureSpec.EXACTLY), + MeasureSpec.makeMeasureSpec(frame.height(), MeasureSpec.EXACTLY)); + } + if (!mRelayoutRequested && mCheckIfCanDraw) { // We had a sync previously, but we didn't call IWindowSession#relayout in this // traversal. So we don't know if the sync is complete that we can continue to draw. @@ -3940,6 +3992,9 @@ public final class ViewRootImpl implements ViewParent, } finally { Trace.traceEnd(Trace.TRACE_TAG_VIEW); } + mMeasuredWidth = mView.getMeasuredWidth(); + mMeasuredHeight = mView.getMeasuredHeight(); + mViewMeasureDeferred = false; } /** @@ -4035,7 +4090,7 @@ public final class ViewRootImpl implements ViewParent, view.requestLayout(); } measureHierarchy(host, lp, mView.getContext().getResources(), - desiredWindowWidth, desiredWindowHeight); + desiredWindowWidth, desiredWindowHeight, false /* forRootSizeOnly */); mInLayout = true; host.layout(0, 0, host.getMeasuredWidth(), host.getMeasuredHeight()); @@ -8101,8 +8156,8 @@ public final class ViewRootImpl implements ViewParent, final WindowConfiguration winConfigFromWm = mLastReportedMergedConfiguration.getGlobalConfiguration().windowConfiguration; final WindowConfiguration winConfig = getCompatWindowConfiguration(); - final int measuredWidth = mView.getMeasuredWidth(); - final int measuredHeight = mView.getMeasuredHeight(); + final int measuredWidth = mMeasuredWidth; + final int measuredHeight = mMeasuredHeight; final boolean relayoutAsync; if (LOCAL_LAYOUT && (mViewFrameInfo.flags & FrameInfo.FLAG_WINDOW_VISIBILITY_CHANGED) == 0 |