diff options
| author | Adam Powell <adamp@google.com> | 2014-03-06 17:55:16 -0800 |
|---|---|---|
| committer | Adam Powell <adamp@google.com> | 2014-03-10 14:09:18 -0700 |
| commit | fd6b99750bfab7f930ee375a79009874a3196165 (patch) | |
| tree | b122d36116e37ca411dd5bdef134c70d3c685f53 /core/java | |
| parent | c6f0b54d695b49966a13bb196800a985ac6ce212 (diff) | |
Prevent overflow from MeasureSpec.adjust; measure cache fix
Extract the size from the MeasureSpec value before adding the
delta. The opposite order could result in a negative delta causing
overflow into size from the EXACTLY mode, creating a very large size
value in the resulting MeasureSpec.
Don't reapply optical bounds insets after pulling a value from the
measurement cache. (The insets will have already been applied before
insertion into the cache.)
Change-Id: Ib0154f4d6c3a7c31e7fee24fd7d5d10cc5dc71a1
Diffstat (limited to 'core/java')
| -rw-r--r-- | core/java/android/view/View.java | 31 |
1 files changed, 29 insertions, 2 deletions
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index b0bae463112d..9b47cbe24b81 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -16499,7 +16499,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } else { long value = mMeasureCache.valueAt(cacheIndex); // Casting a long to int drops the high 32 bits, no mask needed - setMeasuredDimension((int) (value >> 32), (int) value); + setMeasuredDimensionRaw((int) (value >> 32), (int) value); mPrivateFlags3 |= PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT; } @@ -16594,6 +16594,22 @@ public class View implements Drawable.Callback, KeyEvent.Callback, measuredWidth += optical ? opticalWidth : -opticalWidth; measuredHeight += optical ? opticalHeight : -opticalHeight; } + setMeasuredDimensionRaw(measuredWidth, measuredHeight); + } + + /** + * Sets the measured dimension without extra processing for things like optical bounds. + * Useful for reapplying consistent values that have already been cooked with adjustments + * for optical bounds, etc. such as those from the measurement cache. + * + * @param measuredWidth The measured width of this view. May be a complex + * bit mask as defined by {@link #MEASURED_SIZE_MASK} and + * {@link #MEASURED_STATE_TOO_SMALL}. + * @param measuredHeight The measured height of this view. May be a complex + * bit mask as defined by {@link #MEASURED_SIZE_MASK} and + * {@link #MEASURED_STATE_TOO_SMALL}. + */ + private void setMeasuredDimensionRaw(int measuredWidth, int measuredHeight) { mMeasuredWidth = measuredWidth; mMeasuredHeight = measuredHeight; @@ -18361,7 +18377,18 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } static int adjust(int measureSpec, int delta) { - return makeMeasureSpec(getSize(measureSpec + delta), getMode(measureSpec)); + final int mode = getMode(measureSpec); + if (mode == UNSPECIFIED) { + // No need to adjust size for UNSPECIFIED mode. + return makeMeasureSpec(0, UNSPECIFIED); + } + int size = getSize(measureSpec) + delta; + if (size < 0) { + Log.e(VIEW_LOG_TAG, "MeasureSpec.adjust: new size would be negative! (" + size + + ") spec: " + toString(measureSpec) + " delta: " + delta); + size = 0; + } + return makeMeasureSpec(size, mode); } /** |
