summaryrefslogtreecommitdiffstats
path: root/core/java/android
diff options
context:
space:
mode:
authorBrad Fitzpatrick <bradfitz@android.com>2010-11-21 18:46:08 -0800
committerBrad Fitzpatrick <bradfitz@android.com>2010-11-23 12:44:08 -0800
commitce81f3a955a0e77e44e1f76c976905ec2a52c1d0 (patch)
tree4c6f95fbdc3e42937c2d2a18dbacafa35a47a856 /core/java/android
parentb43d7589cf6201fc05f4c9d8b4a0c44d7cdba81e (diff)
downloadframeworks_base-ce81f3a955a0e77e44e1f76c976905ec2a52c1d0.zip
frameworks_base-ce81f3a955a0e77e44e1f76c976905ec2a52c1d0.tar.gz
frameworks_base-ce81f3a955a0e77e44e1f76c976905ec2a52c1d0.tar.bz2
StrictMode.Span annotations for ScrollView.
Between the animation system, ListView, and this, we can now account for the large majority of animations in-flight at any point and annotate StrictMode violations accordingly. Note that StrictMode.Span goes out of its way to not allocate memory and is very light-weight, especially on user builds where it's a no-op. I've tested this with the LOG_V debugging in StrictMode and I think I've gotten all the entry/exit cases of ScrollView's animations. At least, I'm not able to get it out-of-sync at least, even with orientation changes during scroll/fling, etc. It's possible I missed a path, but that should show up as excessive false positives during dropbox uploads if so. Change-Id: I3b0545111a775d9fa8e171f2a190031f1b56c4c0
Diffstat (limited to 'core/java/android')
-rw-r--r--core/java/android/widget/ScrollView.java91
1 files changed, 70 insertions, 21 deletions
diff --git a/core/java/android/widget/ScrollView.java b/core/java/android/widget/ScrollView.java
index 3faec55..900c9ec 100644
--- a/core/java/android/widget/ScrollView.java
+++ b/core/java/android/widget/ScrollView.java
@@ -24,6 +24,7 @@ import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
+import android.os.StrictMode;
import android.util.AttributeSet;
import android.view.FocusFinder;
import android.view.KeyEvent;
@@ -128,7 +129,16 @@ public class ScrollView extends FrameLayout {
* drags/flings if multiple pointers are used.
*/
private int mActivePointerId = INVALID_POINTER;
-
+
+ /**
+ * The StrictMode "critical time span" objects to catch animation
+ * stutters. Non-null when a time-sensitive animation is
+ * in-flight. Must call finish() on them when done animating.
+ * These are no-ops on user builds.
+ */
+ private StrictMode.Span mScrollStrictSpan = null; // aka "drag"
+ private StrictMode.Span mFlingStrictSpan = null;
+
/**
* Sentinel value for no current active pointer.
* Used by {@link #mActivePointerId}.
@@ -437,6 +447,9 @@ public class ScrollView extends FrameLayout {
if (yDiff > mTouchSlop) {
mIsBeingDragged = true;
mLastMotionY = y;
+ if (mScrollStrictSpan == null) {
+ mScrollStrictSpan = StrictMode.enterCriticalSpan("ScrollView-scroll");
+ }
}
break;
}
@@ -461,6 +474,9 @@ public class ScrollView extends FrameLayout {
* being flinged.
*/
mIsBeingDragged = !mScroller.isFinished();
+ if (mIsBeingDragged && mScrollStrictSpan == null) {
+ mScrollStrictSpan = StrictMode.enterCriticalSpan("ScrollView-scroll");
+ }
break;
}
@@ -512,6 +528,10 @@ public class ScrollView extends FrameLayout {
*/
if (!mScroller.isFinished()) {
mScroller.abortAnimation();
+ if (mFlingStrictSpan != null) {
+ mFlingStrictSpan.finish();
+ mFlingStrictSpan = null;
+ }
}
// Remember where the motion event started
@@ -577,16 +597,7 @@ public class ScrollView extends FrameLayout {
}
mActivePointerId = INVALID_POINTER;
- mIsBeingDragged = false;
-
- if (mVelocityTracker != null) {
- mVelocityTracker.recycle();
- mVelocityTracker = null;
- }
- if (mEdgeGlowTop != null) {
- mEdgeGlowTop.onRelease();
- mEdgeGlowBottom.onRelease();
- }
+ endDrag();
}
break;
case MotionEvent.ACTION_CANCEL:
@@ -595,15 +606,7 @@ public class ScrollView extends FrameLayout {
invalidate();
}
mActivePointerId = INVALID_POINTER;
- mIsBeingDragged = false;
- if (mVelocityTracker != null) {
- mVelocityTracker.recycle();
- mVelocityTracker = null;
- }
- if (mEdgeGlowTop != null) {
- mEdgeGlowTop.onRelease();
- mEdgeGlowBottom.onRelease();
- }
+ endDrag();
}
break;
case MotionEvent.ACTION_POINTER_UP:
@@ -1004,6 +1007,10 @@ public class ScrollView extends FrameLayout {
} else {
if (!mScroller.isFinished()) {
mScroller.abortAnimation();
+ if (mFlingStrictSpan != null) {
+ mFlingStrictSpan.finish();
+ mFlingStrictSpan = null;
+ }
}
scrollBy(dx, dy);
}
@@ -1122,6 +1129,11 @@ public class ScrollView extends FrameLayout {
// Keep on drawing until the animation has finished.
postInvalidate();
+ } else {
+ if (mFlingStrictSpan != null) {
+ mFlingStrictSpan.finish();
+ mFlingStrictSpan = null;
+ }
}
}
@@ -1296,6 +1308,20 @@ public class ScrollView extends FrameLayout {
}
@Override
+ protected void onDetachedFromWindow() {
+ super.onDetachedFromWindow();
+
+ if (mScrollStrictSpan != null) {
+ mScrollStrictSpan.finish();
+ mScrollStrictSpan = null;
+ }
+ if (mFlingStrictSpan != null) {
+ mFlingStrictSpan.finish();
+ mFlingStrictSpan = null;
+ }
+ }
+
+ @Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
mIsLayoutDirty = false;
@@ -1368,11 +1394,34 @@ public class ScrollView extends FrameLayout {
mScrollViewMovedFocus = true;
mScrollViewMovedFocus = false;
}
-
+
+ if (mFlingStrictSpan == null) {
+ mFlingStrictSpan = StrictMode.enterCriticalSpan("ScrollView-fling");
+ }
+
invalidate();
}
}
+ private void endDrag() {
+ mIsBeingDragged = false;
+
+ if (mVelocityTracker != null) {
+ mVelocityTracker.recycle();
+ mVelocityTracker = null;
+ }
+
+ if (mEdgeGlowTop != null) {
+ mEdgeGlowTop.onRelease();
+ mEdgeGlowBottom.onRelease();
+ }
+
+ if (mScrollStrictSpan != null) {
+ mScrollStrictSpan.finish();
+ mScrollStrictSpan = null;
+ }
+ }
+
/**
* {@inheritDoc}
*