From d86fb2ce37b6b812992a28e7210a82f169d1cdcf Mon Sep 17 00:00:00 2001 From: Chet Haase Date: Wed, 4 May 2016 07:26:02 -0700 Subject: [PATCH] Force second measure pass when there is a configuration change It's possible for a call to updateConfiguration() to happen in the middle of performTraversals(), after the measure phase has happened, but before the layout phase. During the configuration call, it's possible for views to have requestLayout() called on them. This can result in the request flag not getting cleared, because views that have had layout requested, but which have not yet been measured, may not be told to layout. The correct flow should be that any code path causing requestLayout() (which could be anything that calls out to user/app code) should happen before the measure phase (or cause a second measure to occur). For now, causing the second measure to occur is a low-risk simple change that fixes the immediate problem. Issue #28152259 Calling requestLayout from inside View.onConfigurationChanged can cause problems Change-Id: I3b532eeacc3784d8d21193d01ddd7fa15ac0684e --- core/java/android/view/ViewRootImpl.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index edf05ba5fc33c..ab3d09864e99c 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -1679,6 +1679,7 @@ public final class ViewRootImpl implements ViewParent, boolean insetsPending = false; int relayoutResult = 0; + boolean updatedConfiguration = false; final int surfaceGenerationId = mSurface.getGenerationId(); @@ -1741,6 +1742,7 @@ public final class ViewRootImpl implements ViewParent, + mPendingConfiguration); updateConfiguration(new Configuration(mPendingConfiguration), !mFirst); mPendingConfiguration.seq = 0; + updatedConfiguration = true; } final boolean overscanInsetsChanged = !mPendingOverscanInsets.equals( @@ -1978,7 +1980,8 @@ public final class ViewRootImpl implements ViewParent, boolean focusChangedDueToTouchMode = ensureTouchModeLocally( (relayoutResult&WindowManagerGlobal.RELAYOUT_RES_IN_TOUCH_MODE) != 0); if (focusChangedDueToTouchMode || mWidth != host.getMeasuredWidth() - || mHeight != host.getMeasuredHeight() || contentInsetsChanged) { + || mHeight != host.getMeasuredHeight() || contentInsetsChanged || + updatedConfiguration) { int childWidthMeasureSpec = getRootMeasureSpec(mWidth, lp.width); int childHeightMeasureSpec = getRootMeasureSpec(mHeight, lp.height);