Make velocity tracker used in panel dependent on config.
The velocity tracker used in PanelView can now be configured with
a boolean value. The default is to use tha platform-standard velocity
tracker, but can be overriden to use our own velocity tracker for
noisy touch screens instead.
Change-Id: I375f4e2675ddbaa003acd6f085065bb3fe59ebf4
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 21eb41c..73b52ae 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -131,5 +131,9 @@
<!-- The maximum count of notifications on Keyguard. The rest will be collapsed in an overflow
card. -->
<integer name="keyguard_max_notification_count">4</integer>
+
+ <!-- Defines the implementation of the velocity tracker to be used for the panel expansion. Can
+ be 'platform' or 'noisy' (i.e. for noisy touch screens). -->
+ <string name="velocity_tracker_impl" translatable="false">platform</string>
</resources>
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NoisyVelocityTracker.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NoisyVelocityTracker.java
new file mode 100644
index 0000000..214dda2
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NoisyVelocityTracker.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar.phone;
+
+import android.util.Log;
+import android.util.Pools;
+import android.view.MotionEvent;
+
+import java.util.ArrayDeque;
+import java.util.Iterator;
+
+/**
+ * A very simple low-pass velocity filter for motion events for noisy touch screens.
+ */
+public class NoisyVelocityTracker implements VelocityTrackerInterface {
+
+ private static final Pools.SynchronizedPool<NoisyVelocityTracker> sNoisyPool =
+ new Pools.SynchronizedPool<>(2);
+
+ private static final float DECAY = 0.75f;
+ private static final boolean DEBUG = false;
+
+ private final int MAX_EVENTS = 8;
+ private ArrayDeque<MotionEventCopy> mEventBuf = new ArrayDeque<MotionEventCopy>(MAX_EVENTS);
+ private float mVX, mVY = 0;
+
+ private static class MotionEventCopy {
+ public MotionEventCopy(float x2, float y2, long eventTime) {
+ this.x = x2;
+ this.y = y2;
+ this.t = eventTime;
+ }
+ float x, y;
+ long t;
+ }
+
+ public static NoisyVelocityTracker obtain() {
+ NoisyVelocityTracker instance = sNoisyPool.acquire();
+ return (instance != null) ? instance : new NoisyVelocityTracker();
+ }
+
+ private NoisyVelocityTracker() {
+ }
+
+ public void addMovement(MotionEvent event) {
+ if (mEventBuf.size() == MAX_EVENTS) {
+ mEventBuf.remove();
+ }
+ mEventBuf.add(new MotionEventCopy(event.getX(), event.getY(), event.getEventTime()));
+ }
+
+ public void computeCurrentVelocity(int units) {
+ if (NoisyVelocityTracker.DEBUG) {
+ Log.v("FlingTracker", "computing velocities for " + mEventBuf.size() + " events");
+ }
+ mVX = mVY = 0;
+ MotionEventCopy last = null;
+ int i = 0;
+ float totalweight = 0f;
+ float weight = 10f;
+ for (final Iterator<MotionEventCopy> iter = mEventBuf.iterator();
+ iter.hasNext();) {
+ final MotionEventCopy event = iter.next();
+ if (last != null) {
+ final float dt = (float) (event.t - last.t) / units;
+ final float dx = (event.x - last.x);
+ final float dy = (event.y - last.y);
+ if (NoisyVelocityTracker.DEBUG) {
+ Log.v("FlingTracker", String.format(
+ " [%d] (t=%d %.1f,%.1f) dx=%.1f dy=%.1f dt=%f vx=%.1f vy=%.1f",
+ i, event.t, event.x, event.y,
+ dx, dy, dt,
+ (dx/dt),
+ (dy/dt)
+ ));
+ }
+ if (event.t == last.t) {
+ // Really not sure what to do with events that happened at the same time,
+ // so we'll skip subsequent events.
+ continue;
+ }
+ mVX += weight * dx / dt;
+ mVY += weight * dy / dt;
+ totalweight += weight;
+ weight *= DECAY;
+ }
+ last = event;
+ i++;
+ }
+ if (totalweight > 0) {
+ mVX /= totalweight;
+ mVY /= totalweight;
+ } else {
+ // so as not to contaminate the velocities with NaN
+ mVX = mVY = 0;
+ }
+
+ if (NoisyVelocityTracker.DEBUG) {
+ Log.v("FlingTracker", "computed: vx=" + mVX + " vy=" + mVY);
+ }
+ }
+
+ public float getXVelocity() {
+ if (Float.isNaN(mVX) || Float.isInfinite(mVX)) {
+ mVX = 0;
+ }
+ return mVX;
+ }
+
+ public float getYVelocity() {
+ if (Float.isNaN(mVY) || Float.isInfinite(mVX)) {
+ mVY = 0;
+ }
+ return mVY;
+ }
+
+ public void recycle() {
+ mEventBuf.clear();
+ sNoisyPool.release(this);
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
index 517f763..a89fc0a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
@@ -80,123 +80,7 @@
private TimeAnimator mTimeAnimator;
private ObjectAnimator mPeekAnimator;
- private FlingTracker mVelocityTracker;
-
- /**
- * A very simple low-pass velocity filter for motion events; not nearly as sophisticated as
- * VelocityTracker but optimized for the kinds of gestures we expect to see in status bar
- * panels.
- */
- private static class FlingTracker {
- static final boolean DEBUG = false;
- final int MAX_EVENTS = 8;
- final float DECAY = 0.75f;
- ArrayDeque<MotionEventCopy> mEventBuf = new ArrayDeque<MotionEventCopy>(MAX_EVENTS);
- float mVX, mVY = 0;
- private static class MotionEventCopy {
- public MotionEventCopy(float x2, float y2, long eventTime) {
- this.x = x2;
- this.y = y2;
- this.t = eventTime;
- }
- public float x, y;
- public long t;
- }
- public FlingTracker() {
- }
- public void addMovement(MotionEvent event) {
- if (mEventBuf.size() == MAX_EVENTS) {
- mEventBuf.remove();
- }
- mEventBuf.add(new MotionEventCopy(event.getX(), event.getY(), event.getEventTime()));
- }
- public void computeCurrentVelocity(long timebase) {
- if (FlingTracker.DEBUG) {
- Log.v("FlingTracker", "computing velocities for " + mEventBuf.size() + " events");
- }
- mVX = mVY = 0;
- MotionEventCopy last = null;
- int i = 0;
- float totalweight = 0f;
- float weight = 10f;
- for (final Iterator<MotionEventCopy> iter = mEventBuf.iterator();
- iter.hasNext();) {
- final MotionEventCopy event = iter.next();
- if (last != null) {
- final float dt = (float) (event.t - last.t) / timebase;
- final float dx = (event.x - last.x);
- final float dy = (event.y - last.y);
- if (FlingTracker.DEBUG) {
- Log.v("FlingTracker", String.format(
- " [%d] (t=%d %.1f,%.1f) dx=%.1f dy=%.1f dt=%f vx=%.1f vy=%.1f",
- i, event.t, event.x, event.y,
- dx, dy, dt,
- (dx/dt),
- (dy/dt)
- ));
- }
- if (event.t == last.t) {
- // Really not sure what to do with events that happened at the same time,
- // so we'll skip subsequent events.
- if (DEBUG_NAN) {
- Log.v("FlingTracker", "skipping simultaneous event at t=" + event.t);
- }
- continue;
- }
- mVX += weight * dx / dt;
- mVY += weight * dy / dt;
- totalweight += weight;
- weight *= DECAY;
- }
- last = event;
- i++;
- }
- if (totalweight > 0) {
- mVX /= totalweight;
- mVY /= totalweight;
- } else {
- if (DEBUG_NAN) {
- Log.v("FlingTracker", "computeCurrentVelocity warning: totalweight=0",
- new Throwable());
- }
- // so as not to contaminate the velocities with NaN
- mVX = mVY = 0;
- }
-
- if (FlingTracker.DEBUG) {
- Log.v("FlingTracker", "computed: vx=" + mVX + " vy=" + mVY);
- }
- }
- public float getXVelocity() {
- if (Float.isNaN(mVX) || Float.isInfinite(mVX)) {
- if (DEBUG_NAN) {
- Log.v("FlingTracker", "warning: vx=" + mVX);
- }
- mVX = 0;
- }
- return mVX;
- }
- public float getYVelocity() {
- if (Float.isNaN(mVY) || Float.isInfinite(mVX)) {
- if (DEBUG_NAN) {
- Log.v("FlingTracker", "warning: vx=" + mVY);
- }
- mVY = 0;
- }
- return mVY;
- }
- public void recycle() {
- mEventBuf.clear();
- }
-
- static FlingTracker sTracker;
- static FlingTracker obtain() {
- if (sTracker == null) {
- sTracker = new FlingTracker();
- }
- return sTracker;
- }
- }
+ private VelocityTrackerInterface mVelocityTracker;
PanelBar mBar;
@@ -385,7 +269,9 @@
mInitialTouchY = y;
mInitialTouchX = x;
- initVelocityTracker();
+ if (mVelocityTracker == null) {
+ initVelocityTracker();
+ }
trackMovement(event);
mTimeAnimator.cancel(); // end any outstanding animations
onTrackingStarted();
@@ -569,7 +455,7 @@
if (mVelocityTracker != null) {
mVelocityTracker.recycle();
}
- mVelocityTracker = FlingTracker.obtain();
+ mVelocityTracker = VelocityTrackerFactory.obtain(getContext());
}
protected boolean isScrolledToBottom() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PlatformVelocityTracker.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PlatformVelocityTracker.java
new file mode 100644
index 0000000..f589c3d
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PlatformVelocityTracker.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar.phone;
+
+import android.util.Pools;
+import android.view.MotionEvent;
+import android.view.VelocityTracker;
+
+/**
+ * An implementation of {@link VelocityTrackerInterface} using the platform-standard
+ * {@link VelocityTracker}.
+ */
+public class PlatformVelocityTracker implements VelocityTrackerInterface {
+
+ private static final Pools.SynchronizedPool<PlatformVelocityTracker> sPool =
+ new Pools.SynchronizedPool<>(2);
+
+ private VelocityTracker mTracker;
+
+ public static PlatformVelocityTracker obtain() {
+ PlatformVelocityTracker tracker = sPool.acquire();
+ if (tracker == null) {
+ tracker = new PlatformVelocityTracker();
+ }
+ tracker.setTracker(VelocityTracker.obtain());
+ return tracker;
+ }
+
+ public void setTracker(VelocityTracker tracker) {
+ mTracker = tracker;
+ }
+
+ @Override
+ public void addMovement(MotionEvent event) {
+ mTracker.addMovement(event);
+ }
+
+ @Override
+ public void computeCurrentVelocity(int units) {
+ mTracker.computeCurrentVelocity(units);
+ }
+
+ @Override
+ public float getXVelocity() {
+ return mTracker.getXVelocity();
+ }
+
+ @Override
+ public float getYVelocity() {
+ return mTracker.getYVelocity();
+ }
+
+ @Override
+ public void recycle() {
+ mTracker.recycle();
+ sPool.release(this);
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/VelocityTrackerFactory.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/VelocityTrackerFactory.java
new file mode 100644
index 0000000..4f43b4d
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/VelocityTrackerFactory.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar.phone;
+
+import android.content.Context;
+
+import com.android.systemui.R;
+
+import static android.util.Pools.SynchronizedPool;
+
+/**
+ * A class to generate {@link VelocityTrackerInterface}, depending on the configuration.
+ */
+public class VelocityTrackerFactory {
+
+ public static final String PLATFORM_IMPL = "platform";
+ public static final String NOISY_IMPL = "noisy";
+
+ public static VelocityTrackerInterface obtain(Context ctx) {
+ String tracker = ctx.getResources().getString(R.string.velocity_tracker_impl);
+ switch (tracker) {
+ case NOISY_IMPL:
+ return NoisyVelocityTracker.obtain();
+ case PLATFORM_IMPL:
+ return PlatformVelocityTracker.obtain();
+ default:
+ throw new IllegalStateException("Invalid tracker: " + tracker);
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/VelocityTrackerInterface.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/VelocityTrackerInterface.java
new file mode 100644
index 0000000..a54b054
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/VelocityTrackerInterface.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar.phone;
+
+import android.view.MotionEvent;
+
+/**
+ * An interface for a velocity tracker to delegate. To be implemented by different velocity tracking
+ * algorithms.
+ */
+public interface VelocityTrackerInterface {
+ public void addMovement(MotionEvent event);
+ public void computeCurrentVelocity(int units);
+ public float getXVelocity();
+ public float getYVelocity();
+ public void recycle();
+}