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
This commit is contained in:
Adam Powell
2014-03-06 17:55:16 -08:00
parent c6f0b54d69
commit fd6b99750b

View File

@@ -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);
}
/**