diff options
Diffstat (limited to 'core/java/android')
| -rw-r--r-- | core/java/android/os/Message.java | 17 | ||||
| -rw-r--r-- | core/java/android/text/SpannableStringBuilder.java | 132 | ||||
| -rw-r--r-- | core/java/android/view/DisplayList.java | 24 | ||||
| -rw-r--r-- | core/java/android/view/GLES20Canvas.java | 7 | ||||
| -rw-r--r-- | core/java/android/view/GLES20DisplayList.java | 16 | ||||
| -rw-r--r-- | core/java/android/view/HardwareCanvas.java | 12 | ||||
| -rw-r--r-- | core/java/android/view/HardwareRenderer.java | 54 | ||||
| -rwxr-xr-x | core/java/android/view/KeyEvent.java | 28 | ||||
| -rw-r--r-- | core/java/android/view/View.java | 78 | ||||
| -rw-r--r-- | core/java/android/widget/RemoteViewsAdapter.java | 21 |
10 files changed, 261 insertions, 128 deletions
diff --git a/core/java/android/os/Message.java b/core/java/android/os/Message.java index b816b11..4aa7fe2 100644 --- a/core/java/android/os/Message.java +++ b/core/java/android/os/Message.java @@ -16,9 +16,6 @@ package android.os; -import android.os.Bundle; -import android.os.Parcel; -import android.os.Parcelable; import android.util.TimeUtils; /** @@ -368,13 +365,13 @@ public final class Message implements Parcelable { * * Asynchronous messages represent interrupts or events that do not require global ordering * with represent to synchronous messages. Asynchronous messages are not subject to - * the synchronization barriers introduced by {@link MessageQueue#acquireSyncBarrier()}. + * the synchronization barriers introduced by {@link MessageQueue#enqueueSyncBarrier(long)}. * * @return True if the message is asynchronous. * * @see #setAsynchronous(boolean) - * @see MessageQueue#acquireSyncBarrier() - * @see MessageQueue#releaseSyncBarrier() + * @see MessageQueue#enqueueSyncBarrier(long) + * @see MessageQueue#removeSyncBarrier(int) * * @hide */ @@ -387,13 +384,13 @@ public final class Message implements Parcelable { * * Asynchronous messages represent interrupts or events that do not require global ordering * with represent to synchronous messages. Asynchronous messages are not subject to - * the synchronization barriers introduced by {@link MessageQueue#acquireSyncBarrier()}. + * the synchronization barriers introduced by {@link MessageQueue#enqueueSyncBarrier(long)}. * * @param async True if the message is asynchronous. * * @see #isAsynchronous() - * @see MessageQueue#acquireSyncBarrier() - * @see MessageQueue#releaseSyncBarrier() + * @see MessageQueue#enqueueSyncBarrier(long) + * @see MessageQueue#removeSyncBarrier(int) * * @hide */ @@ -506,7 +503,7 @@ public final class Message implements Parcelable { Messenger.writeMessengerOrNullToParcel(replyTo, dest); } - private final void readFromParcel(Parcel source) { + private void readFromParcel(Parcel source) { what = source.readInt(); arg1 = source.readInt(); arg2 = source.readInt(); diff --git a/core/java/android/text/SpannableStringBuilder.java b/core/java/android/text/SpannableStringBuilder.java index d0c87c6..f7a7eb8 100644 --- a/core/java/android/text/SpannableStringBuilder.java +++ b/core/java/android/text/SpannableStringBuilder.java @@ -262,19 +262,8 @@ public class SpannableStringBuilder implements CharSequence, GetChars, Spannable return append(String.valueOf(text)); } - private int change(int start, int end, CharSequence tb, int tbstart, int tbend) { - return change(true, start, end, tb, tbstart, tbend); - } - - private int change(boolean notify, int start, int end, - CharSequence tb, int tbstart, int tbend) { + private void change(int start, int end, CharSequence tb, int tbstart, int tbend) { checkRange("replace", start, end); - int ret = tbend - tbstart; - TextWatcher[] recipients = null; - - if (notify) { - recipients = sendTextWillChange(start, end - start, tbend - tbstart); - } for (int i = mSpanCount - 1; i >= 0; i--) { if ((mSpanFlags[i] & SPAN_PARAGRAPH) == SPAN_PARAGRAPH) { @@ -338,7 +327,7 @@ public class SpannableStringBuilder implements CharSequence, GetChars, Spannable en = tbend; if (getSpanStart(spans[i]) < 0) { - setSpan(true, spans[i], + setSpan(false, spans[i], st - tbstart + start, en - tbstart + start, sp.getSpanFlags(spans[i])); @@ -346,51 +335,37 @@ public class SpannableStringBuilder implements CharSequence, GetChars, Spannable } } - // no need for span fixup on pure insertion - if (tbend > tbstart && end - start == 0) { - if (notify) { - sendTextChange(recipients, start, end - start, tbend - tbstart); - sendTextHasChanged(recipients); - } - - return ret; - } - - boolean atend = (mGapStart + mGapLength == mText.length); + if (end > start) { + // no need for span fixup on pure insertion + boolean atEnd = (mGapStart + mGapLength == mText.length); - for (int i = mSpanCount - 1; i >= 0; i--) { - if (mSpanStarts[i] >= start && - mSpanStarts[i] < mGapStart + mGapLength) { - int flag = (mSpanFlags[i] & START_MASK) >> START_SHIFT; + for (int i = mSpanCount - 1; i >= 0; i--) { + if (mSpanStarts[i] >= start && + mSpanStarts[i] < mGapStart + mGapLength) { + int flag = (mSpanFlags[i] & START_MASK) >> START_SHIFT; - if (flag == POINT || (flag == PARAGRAPH && atend)) + if (flag == POINT || (flag == PARAGRAPH && atEnd)) mSpanStarts[i] = mGapStart + mGapLength; else mSpanStarts[i] = start; - } + } - if (mSpanEnds[i] >= start && - mSpanEnds[i] < mGapStart + mGapLength) { - int flag = (mSpanFlags[i] & END_MASK); + if (mSpanEnds[i] >= start && + mSpanEnds[i] < mGapStart + mGapLength) { + int flag = (mSpanFlags[i] & END_MASK); - if (flag == POINT || (flag == PARAGRAPH && atend)) - mSpanEnds[i] = mGapStart + mGapLength; - else - mSpanEnds[i] = start; - } + if (flag == POINT || (flag == PARAGRAPH && atEnd)) + mSpanEnds[i] = mGapStart + mGapLength; + else + mSpanEnds[i] = start; + } - // remove 0-length SPAN_EXCLUSIVE_EXCLUSIVE - if (mSpanEnds[i] < mSpanStarts[i]) { - removeSpan(i); + // remove 0-length SPAN_EXCLUSIVE_EXCLUSIVE + if (mSpanEnds[i] < mSpanStarts[i]) { + removeSpan(i); + } } } - - if (notify) { - sendTextChange(recipients, start, end - start, tbend - tbstart); - sendTextHasChanged(recipients); - } - - return ret; } private void removeSpan(int i) { @@ -425,8 +400,7 @@ public class SpannableStringBuilder implements CharSequence, GetChars, Spannable CharSequence tb, int tbstart, int tbend) { int filtercount = mFilters.length; for (int i = 0; i < filtercount; i++) { - CharSequence repl = mFilters[i].filter(tb, tbstart, tbend, - this, start, end); + CharSequence repl = mFilters[i].filter(tb, tbstart, tbend, this, start, end); if (repl != null) { tb = repl; @@ -435,11 +409,17 @@ public class SpannableStringBuilder implements CharSequence, GetChars, Spannable } } - if (end == start && tbstart == tbend) { + final int origLen = end - start; + final int newLen = tbend - tbstart; + + if (origLen == 0 && newLen == 0) { return this; } - if (end == start || tbstart == tbend) { + TextWatcher[] textWatchers = getSpans(start, start + origLen, TextWatcher.class); + sendBeforeTextChanged(textWatchers, start, origLen, newLen); + + if (origLen == 0 || newLen == 0) { change(start, end, tb, tbstart, tbend); } else { int selstart = Selection.getSelectionStart(this); @@ -450,11 +430,6 @@ public class SpannableStringBuilder implements CharSequence, GetChars, Spannable checkRange("replace", start, end); moveGapTo(end); - TextWatcher[] recipients; - - int origlen = end - start; - - recipients = sendTextWillChange(start, origlen, tbend - tbstart); if (mGapLength < 2) resizeFor(length() + 1); @@ -475,9 +450,9 @@ public class SpannableStringBuilder implements CharSequence, GetChars, Spannable new Exception("mGapLength < 1").printStackTrace(); } - int inserted = change(false, start + 1, start + 1, tb, tbstart, tbend); - change(false, start, start + 1, "", 0, 0); - change(false, start + inserted, start + inserted + origlen, "", 0, 0); + change(start + 1, start + 1, tb, tbstart, tbend); + change(start, start + 1, "", 0, 0); + change(start + newLen, start + newLen + origLen, "", 0, 0); /* * Special case to keep the cursor in the same position @@ -490,7 +465,7 @@ public class SpannableStringBuilder implements CharSequence, GetChars, Spannable if (selstart > start && selstart < end) { long off = selstart - start; - off = off * inserted / (end - start); + off = off * newLen / (end - start); selstart = (int) off + start; setSpan(false, Selection.SELECTION_START, selstart, selstart, @@ -499,15 +474,16 @@ public class SpannableStringBuilder implements CharSequence, GetChars, Spannable if (selend > start && selend < end) { long off = selend - start; - off = off * inserted / (end - start); + off = off * newLen / (end - start); selend = (int) off + start; setSpan(false, Selection.SELECTION_END, selend, selend, Spanned.SPAN_POINT_POINT); } - sendTextChange(recipients, start, origlen, inserted); - sendTextHasChanged(recipients); } + sendTextChanged(textWatchers, start, origLen, newLen); + sendAfterTextChanged(textWatchers); + return this; } @@ -872,30 +848,27 @@ public class SpannableStringBuilder implements CharSequence, GetChars, Spannable return new String(buf); } - private TextWatcher[] sendTextWillChange(int start, int before, int after) { - TextWatcher[] recip = getSpans(start, start + before, TextWatcher.class); - int n = recip.length; + private void sendBeforeTextChanged(TextWatcher[] watchers, int start, int before, int after) { + int n = watchers.length; for (int i = 0; i < n; i++) { - recip[i].beforeTextChanged(this, start, before, after); + watchers[i].beforeTextChanged(this, start, before, after); } - - return recip; } - private void sendTextChange(TextWatcher[] recip, int start, int before, int after) { - int n = recip.length; + private void sendTextChanged(TextWatcher[] watchers, int start, int before, int after) { + int n = watchers.length; for (int i = 0; i < n; i++) { - recip[i].onTextChanged(this, start, before, after); + watchers[i].onTextChanged(this, start, before, after); } } - private void sendTextHasChanged(TextWatcher[] recip) { - int n = recip.length; + private void sendAfterTextChanged(TextWatcher[] watchers) { + int n = watchers.length; for (int i = 0; i < n; i++) { - recip[i].afterTextChanged(this); + watchers[i].afterTextChanged(this); } } @@ -1037,8 +1010,7 @@ public class SpannableStringBuilder implements CharSequence, GetChars, Spannable * Don't call this yourself -- exists for Canvas to use internally. * {@hide} */ - public void drawText(Canvas c, int start, int end, - float x, float y, Paint p) { + public void drawText(Canvas c, int start, int end, float x, float y, Paint p) { checkRange("drawText", start, end); if (end <= mGapStart) { @@ -1059,8 +1031,7 @@ public class SpannableStringBuilder implements CharSequence, GetChars, Spannable * Don't call this yourself -- exists for Canvas to use internally. * {@hide} */ - public void drawTextRun(Canvas c, int start, int end, - int contextStart, int contextEnd, + public void drawTextRun(Canvas c, int start, int end, int contextStart, int contextEnd, float x, float y, int flags, Paint p) { checkRange("drawTextRun", start, end); @@ -1262,6 +1233,7 @@ public class SpannableStringBuilder implements CharSequence, GetChars, Spannable private int[] mSpanFlags; private int mSpanCount; + // TODO These value are tightly related to the public SPAN_MARK/POINT values in {@link Spanned} private static final int POINT = 2; private static final int PARAGRAPH = 3; diff --git a/core/java/android/view/DisplayList.java b/core/java/android/view/DisplayList.java index e2aafa9..33631b7 100644 --- a/core/java/android/view/DisplayList.java +++ b/core/java/android/view/DisplayList.java @@ -16,6 +16,8 @@ package android.view; +import android.graphics.Matrix; + /** * A display lists records a series of graphics related operation and can replay * them later. Display lists are usually built by recording operations on a @@ -117,12 +119,26 @@ public abstract class DisplayList { public abstract void setClipChildren(boolean clipChildren); /** - * Set the application scale on the DisplayList. This scale is incurred by applications that - * are auto-scaled for compatibility reasons. By default, the value is 1 (unscaled). + * Set the static matrix on the DisplayList. This matrix exists if a custom ViewGroup + * overrides + * {@link ViewGroup#getChildStaticTransformation(View, android.view.animation.Transformation)} + * and also has {@link ViewGroup#setStaticTransformationsEnabled(boolean)} set to true. + * This matrix will be concatenated with any other matrices in the DisplayList to position + * the view appropriately. + * + * @param matrix The matrix + */ + public abstract void setStaticMatrix(Matrix matrix); + + /** + * Set the Animation matrix on the DisplayList. This matrix exists if an Animation is + * currently playing on a View, and is set on the DisplayList during at draw() time. When + * the Animation finishes, the matrix should be cleared by sending <code>null</code> + * for the matrix parameter. * - * @param scale The scaling factor + * @param matrix The matrix, null indicates that the matrix should be cleared. */ - public abstract void setApplicationScale(float scale); + public abstract void setAnimationMatrix(Matrix matrix); /** * Sets the alpha value for the DisplayList diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java index 5b0433e..bedafc7 100644 --- a/core/java/android/view/GLES20Canvas.java +++ b/core/java/android/view/GLES20Canvas.java @@ -259,6 +259,13 @@ class GLES20Canvas extends HardwareCanvas { private static native int nCallDrawGLFunction(int renderer, int drawGLFunction); + @Override + public int invokeFunctors(Rect dirty) { + return nInvokeFunctors(mRenderer, dirty); + } + + private static native int nInvokeFunctors(int renderer, Rect dirty); + /////////////////////////////////////////////////////////////////////////// // Memory /////////////////////////////////////////////////////////////////////////// diff --git a/core/java/android/view/GLES20DisplayList.java b/core/java/android/view/GLES20DisplayList.java index 9b4cf21..bc3bce0 100644 --- a/core/java/android/view/GLES20DisplayList.java +++ b/core/java/android/view/GLES20DisplayList.java @@ -17,6 +17,7 @@ package android.view; import android.graphics.Bitmap; +import android.graphics.Matrix; import java.util.ArrayList; @@ -119,9 +120,18 @@ class GLES20DisplayList extends DisplayList { } @Override - public void setApplicationScale(float scale) { + public void setStaticMatrix(Matrix matrix) { try { - nSetApplicationScale(getNativeDisplayList(), scale); + nSetStaticMatrix(getNativeDisplayList(), matrix.native_instance); + } catch (IllegalStateException e) { + // invalid DisplayList okay: we'll set current values the next time we render to it + } + } + + @Override + public void setAnimationMatrix(Matrix matrix) { + try { + nSetAnimationMatrix(getNativeDisplayList(), matrix.native_instance); } catch (IllegalStateException e) { // invalid DisplayList okay: we'll set current values the next time we render to it } @@ -335,6 +345,8 @@ class GLES20DisplayList extends DisplayList { private static native void nSetTransformationInfo(int displayList, float alpha, float translationX, float translationY, float rotation, float rotationX, float rotationY, float scaleX, float scaleY); + private static native void nSetStaticMatrix(int displayList, int nativeMatrix); + private static native void nSetAnimationMatrix(int displayList, int animationMatrix); /////////////////////////////////////////////////////////////////////////// diff --git a/core/java/android/view/HardwareCanvas.java b/core/java/android/view/HardwareCanvas.java index 2636ea2..de8c62d 100644 --- a/core/java/android/view/HardwareCanvas.java +++ b/core/java/android/view/HardwareCanvas.java @@ -98,4 +98,16 @@ public abstract class HardwareCanvas extends Canvas { // Noop - this is done in the display list recorder subclass return DisplayList.STATUS_DONE; } + + /** + * Invoke all the functors who requested to be invoked during the previous frame. + * + * @param dirty The region to redraw when the functors return {@link DisplayList#STATUS_DRAW} + * + * @return One of {@link DisplayList#STATUS_DONE}, {@link DisplayList#STATUS_DRAW} or + * {@link DisplayList#STATUS_INVOKE} + */ + public int invokeFunctors(Rect dirty) { + return DisplayList.STATUS_DONE; + } } diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java index 133f601..b100a0c 100644 --- a/core/java/android/view/HardwareRenderer.java +++ b/core/java/android/view/HardwareRenderer.java @@ -502,7 +502,9 @@ public abstract class HardwareRenderer { static final int SURFACE_STATE_ERROR = 0; static final int SURFACE_STATE_SUCCESS = 1; static final int SURFACE_STATE_UPDATED = 2; - + + static final int FUNCTOR_PROCESS_DELAY = 2; + static EGL10 sEgl; static EGLDisplay sEglDisplay; static EGLConfig sEglConfig; @@ -549,7 +551,9 @@ public abstract class HardwareRenderer { private boolean mDestroyed; private final Rect mRedrawClip = new Rect(); + private final int[] mSurfaceSize = new int[2]; + private final FunctorsRunnable mFunctorsRunnable = new FunctorsRunnable(); GlRenderer(int glVersion, boolean translucent) { mGlVersion = glVersion; @@ -957,6 +961,24 @@ public abstract class HardwareRenderer { void onPostDraw() { } + class FunctorsRunnable implements Runnable { + View.AttachInfo attachInfo; + + @Override + public void run() { + final HardwareRenderer renderer = attachInfo.mHardwareRenderer; + if (renderer == null || !renderer.isEnabled() || renderer != GlRenderer.this) { + return; + } + + final int surfaceState = checkCurrent(); + if (surfaceState != SURFACE_STATE_ERROR) { + int status = mCanvas.invokeFunctors(mRedrawClip); + handleFunctorStatus(attachInfo, status); + } + } + } + @Override boolean draw(View view, View.AttachInfo attachInfo, HardwareDrawCallbacks callbacks, Rect dirty) { @@ -1051,15 +1073,7 @@ public abstract class HardwareRenderer { } } - if (status != DisplayList.STATUS_DONE) { - if (mRedrawClip.isEmpty()) { - attachInfo.mViewRootImpl.invalidate(); - } else { - attachInfo.mViewRootImpl.invalidateChildInParent( - null, mRedrawClip); - mRedrawClip.setEmpty(); - } - } + handleFunctorStatus(attachInfo, status); } else { // Shouldn't reach here view.draw(canvas); @@ -1111,6 +1125,26 @@ public abstract class HardwareRenderer { return false; } + private void handleFunctorStatus(View.AttachInfo attachInfo, int status) { + // If the draw flag is set, functors will be invoked while executing + // the tree of display lists + if ((status & DisplayList.STATUS_DRAW) != 0) { + if (mRedrawClip.isEmpty()) { + attachInfo.mViewRootImpl.invalidate(); + } else { + attachInfo.mViewRootImpl.invalidateChildInParent(null, mRedrawClip); + mRedrawClip.setEmpty(); + } + } + + if ((status & DisplayList.STATUS_INVOKE) != 0) { + attachInfo.mHandler.removeCallbacks(mFunctorsRunnable); + mFunctorsRunnable.attachInfo = attachInfo; + // delay the functor callback by a few ms so it isn't polled constantly + attachInfo.mHandler.postDelayed(mFunctorsRunnable, FUNCTOR_PROCESS_DELAY); + } + } + /** * Ensures the current EGL context is the one we expect. * diff --git a/core/java/android/view/KeyEvent.java b/core/java/android/view/KeyEvent.java index 104ed6a..e4a4a75 100755 --- a/core/java/android/view/KeyEvent.java +++ b/core/java/android/view/KeyEvent.java @@ -591,8 +591,24 @@ public class KeyEvent extends InputEvent implements Parcelable { /** Key code constant: Calculator special function key. * Used to launch a calculator application. */ public static final int KEYCODE_CALCULATOR = 210; - - private static final int LAST_KEYCODE = KEYCODE_CALCULATOR; + /** Key code constant: Japanese full-width / half-width key. */ + public static final int KEYCODE_ZENKAKU_HANKAKU = 211; + /** Key code constant: Japanese alphanumeric key. */ + public static final int KEYCODE_EISU = 212; + /** Key code constant: Japanese non-conversion key. */ + public static final int KEYCODE_MUHENKAN = 213; + /** Key code constant: Japanese conversion key. */ + public static final int KEYCODE_HENKAN = 214; + /** Key code constant: Japanese katakana / hiragana key. */ + public static final int KEYCODE_KATAKANA_HIRAGANA = 215; + /** Key code constant: Japanese Yen key. */ + public static final int KEYCODE_YEN = 216; + /** Key code constant: Japanese Ro key. */ + public static final int KEYCODE_RO = 217; + /** Key code constant: Japanese kana key. */ + public static final int KEYCODE_KANA = 218; + + private static final int LAST_KEYCODE = KEYCODE_KANA; // NOTE: If you add a new keycode here you must also add it to: // isSystem() @@ -825,6 +841,14 @@ public class KeyEvent extends InputEvent implements Parcelable { names.append(KEYCODE_CALENDAR, "KEYCODE_CALENDAR"); names.append(KEYCODE_MUSIC, "KEYCODE_MUSIC"); names.append(KEYCODE_CALCULATOR, "KEYCODE_CALCULATOR"); + names.append(KEYCODE_ZENKAKU_HANKAKU, "KEYCODE_ZENKAKU_HANKAKU"); + names.append(KEYCODE_EISU, "KEYCODE_EISU"); + names.append(KEYCODE_MUHENKAN, "KEYCODE_MUHENKAN"); + names.append(KEYCODE_HENKAN, "KEYCODE_HENKAN"); + names.append(KEYCODE_KATAKANA_HIRAGANA, "KEYCODE_KATAKANA_HIRAGANA"); + names.append(KEYCODE_YEN, "KEYCODE_YEN"); + names.append(KEYCODE_RO, "KEYCODE_RO"); + names.append(KEYCODE_KANA, "KEYCODE_KANA"); }; // Symbolic names of all metakeys in bit order from least significant to most significant. diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 99743e4..18e1697 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -1464,7 +1464,7 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal * apps. * @hide */ - public static final boolean USE_DISPLAY_LIST_PROPERTIES = false; + public static final boolean USE_DISPLAY_LIST_PROPERTIES = true; /** * Map used to store views' tags. @@ -11529,12 +11529,34 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal displayList.setClipChildren( (((ViewGroup)mParent).mGroupFlags & ViewGroup.FLAG_CLIP_CHILDREN) != 0); } - if (mAttachInfo != null && mAttachInfo.mScalingRequired && - mAttachInfo.mApplicationScale != 1.0f) { - displayList.setApplicationScale(1f / mAttachInfo.mApplicationScale); + float alpha = 1; + if (mParent instanceof ViewGroup && (((ViewGroup) mParent).mGroupFlags & + ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) { + ViewGroup parentVG = (ViewGroup) mParent; + final boolean hasTransform = + parentVG.getChildStaticTransformation(this, parentVG.mChildTransformation); + if (hasTransform) { + Transformation transform = parentVG.mChildTransformation; + final int transformType = parentVG.mChildTransformation.getTransformationType(); + if (transformType != Transformation.TYPE_IDENTITY) { + if ((transformType & Transformation.TYPE_ALPHA) != 0) { + alpha = transform.getAlpha(); + } + if ((transformType & Transformation.TYPE_MATRIX) != 0) { + displayList.setStaticMatrix(transform.getMatrix()); + } + } + } } if (mTransformationInfo != null) { - displayList.setTransformationInfo(mTransformationInfo.mAlpha, + alpha *= mTransformationInfo.mAlpha; + if (alpha < 1) { + final int multipliedAlpha = (int) (255 * alpha); + if (onSetAlpha(multipliedAlpha)) { + alpha = 1; + } + } + displayList.setTransformationInfo(alpha, mTransformationInfo.mTranslationX, mTransformationInfo.mTranslationY, mTransformationInfo.mRotation, mTransformationInfo.mRotationX, mTransformationInfo.mRotationY, mTransformationInfo.mScaleX, @@ -11548,6 +11570,8 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal displayList.setPivotX(getPivotX()); displayList.setPivotY(getPivotY()); } + } else if (alpha < 1) { + displayList.setAlpha(alpha); } } } @@ -11580,6 +11604,7 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal if ((flags & ViewGroup.FLAG_CHILDREN_DRAWN_WITH_CACHE) != 0 || (flags & ViewGroup.FLAG_ALWAYS_DRAWN_WITH_CACHE) != 0) { caching = true; + // Auto-scaled apps are not hw-accelerated, no need to set scaling flag on DisplayList if (mAttachInfo != null) scalingRequired = mAttachInfo.mScalingRequired; } else { caching = (layerType != LAYER_TYPE_NONE) || hardwareAccelerated; @@ -11590,7 +11615,8 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal more = drawAnimation(parent, drawingTime, a, scalingRequired); concatMatrix = a.willChangeTransformationMatrix(); transformToApply = parent.mChildTransformation; - } else if ((flags & ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) { + } else if (!useDisplayListProperties && + (flags & ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) { final boolean hasTransform = parent.getChildStaticTransformation(this, parent.mChildTransformation); if (hasTransform) { @@ -11658,6 +11684,17 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal } } useDisplayListProperties &= hasDisplayList; + if (useDisplayListProperties) { + displayList = getDisplayList(); + if (!displayList.isValid()) { + // Uncommon, but possible. If a view is removed from the hierarchy during the call + // to getDisplayList(), the display list will be marked invalid and we should not + // try to use it again. + displayList = null; + hasDisplayList = false; + useDisplayListProperties = false; + } + } final boolean hasNoCache = cache == null || hasDisplayList; final boolean offsetForScroll = cache == null && !hasDisplayList && @@ -11675,6 +11712,7 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal } if (scalingRequired) { if (useDisplayListProperties) { + // TODO: Might not need this if we put everything inside the DL restoreTo = canvas.save(); } // mAttachInfo cannot be null, otherwise scalingRequired == false @@ -11684,7 +11722,7 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal } float alpha = useDisplayListProperties ? 1 : getAlpha(); - if (transformToApply != null || alpha < 1.0f || !hasIdentityMatrix()) { + if (transformToApply != null || alpha < 1 || !hasIdentityMatrix()) { if (transformToApply != null || !childHasIdentityMatrix) { int transX = 0; int transY = 0; @@ -11696,16 +11734,20 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal if (transformToApply != null) { if (concatMatrix) { - // Undo the scroll translation, apply the transformation matrix, - // then redo the scroll translate to get the correct result. - canvas.translate(-transX, -transY); - canvas.concat(transformToApply.getMatrix()); - canvas.translate(transX, transY); + if (useDisplayListProperties) { + displayList.setAnimationMatrix(transformToApply.getMatrix()); + } else { + // Undo the scroll translation, apply the transformation matrix, + // then redo the scroll translate to get the correct result. + canvas.translate(-transX, -transY); + canvas.concat(transformToApply.getMatrix()); + canvas.translate(transX, transY); + } parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION; } float transformAlpha = transformToApply.getAlpha(); - if (transformAlpha < 1.0f) { + if (transformAlpha < 1) { alpha *= transformToApply.getAlpha(); parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION; } @@ -11718,7 +11760,7 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal } } - if (alpha < 1.0f) { + if (alpha < 1) { parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION; if (hasNoCache) { final int multipliedAlpha = (int) (255 * alpha); @@ -11728,7 +11770,9 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal layerType != LAYER_TYPE_NONE) { layerFlags |= Canvas.CLIP_TO_LAYER_SAVE_FLAG; } - if (layerType == LAYER_TYPE_NONE) { + if (useDisplayListProperties) { + displayList.setAlpha(alpha * getAlpha()); + } else if (layerType == LAYER_TYPE_NONE) { final int scrollX = hasDisplayList ? 0 : sx; final int scrollY = hasDisplayList ? 0 : sy; canvas.saveLayerAlpha(scrollX, scrollY, scrollX + mRight - mLeft, @@ -11758,7 +11802,7 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal } } - if (hasDisplayList) { + if (!useDisplayListProperties && hasDisplayList) { displayList = getDisplayList(); if (!displayList.isValid()) { // Uncommon, but possible. If a view is removed from the hierarchy during the call @@ -11815,7 +11859,7 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal cachePaint.setDither(false); parent.mCachePaint = cachePaint; } - if (alpha < 1.0f) { + if (alpha < 1) { cachePaint.setAlpha((int) (alpha * 255)); parent.mGroupFlags |= ViewGroup.FLAG_ALPHA_LOWER_THAN_ONE; } else if ((flags & ViewGroup.FLAG_ALPHA_LOWER_THAN_ONE) != 0) { diff --git a/core/java/android/widget/RemoteViewsAdapter.java b/core/java/android/widget/RemoteViewsAdapter.java index 586fdf4..8067435 100644 --- a/core/java/android/widget/RemoteViewsAdapter.java +++ b/core/java/android/widget/RemoteViewsAdapter.java @@ -477,8 +477,11 @@ public class RemoteViewsAdapter extends BaseAdapter implements Handler.Callback private static final String TAG = "FixedSizeRemoteViewsCache"; // The meta data related to all the RemoteViews, ie. count, is stable, etc. - private RemoteViewsMetaData mMetaData; - private RemoteViewsMetaData mTemporaryMetaData; + // The meta data objects are made final so that they can be locked on independently + // of the FixedSizeRemoteViewsCache. If we ever lock on both meta data objects, it is in + // the order mTemporaryMetaData followed by mMetaData. + private final RemoteViewsMetaData mMetaData; + private final RemoteViewsMetaData mTemporaryMetaData; // The cache/mapping of position to RemoteViewsMetaData. This set is guaranteed to be // greater than or equal to the set of RemoteViews. @@ -939,6 +942,10 @@ public class RemoteViewsAdapter extends BaseAdapter implements Handler.Callback * which wouldn't otherwise be possible. */ public void setVisibleRangeHint(int lowerBound, int upperBound) { + if (lowerBound < 0 || upperBound < 0) { + throw new RuntimeException("Attempted to set invalid range: lowerBound="+lowerBound + + "," + "upperBound="+upperBound); + } mVisibleWindowLowerBound = lowerBound; mVisibleWindowUpperBound = upperBound; } @@ -1072,12 +1079,20 @@ public class RemoteViewsAdapter extends BaseAdapter implements Handler.Callback // Re-request the new metadata (only after the notification to the factory) updateTemporaryMetaData(); + int newCount; + synchronized(mCache.getTemporaryMetaData()) { + newCount = mCache.getTemporaryMetaData().count; + } // Pre-load (our best guess of) the views which are currently visible in the AdapterView. // This mitigates flashing and flickering of loading views when a widget notifies that // its data has changed. for (int i = mVisibleWindowLowerBound; i <= mVisibleWindowUpperBound; i++) { - updateRemoteViews(i, false, false); + // Because temporary meta data is only ever modified from this thread (ie. + // mWorkerThread), it is safe to assume that count is a valid representation. + if (i < newCount) { + updateRemoteViews(i, false, false); + } } // Propagate the notification back to the base adapter |
