Loading packages/SystemUI/res/values/config.xml +4 −0 Original line number Diff line number Diff line Loading @@ -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> packages/SystemUI/src/com/android/systemui/statusbar/phone/NoisyVelocityTracker.java 0 → 100644 +135 −0 Original line number Diff line number Diff line /* * 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); } } packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java +5 −119 Original line number Diff line number Diff line Loading @@ -80,123 +80,7 @@ public class PanelView extends FrameLayout { 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; Loading Loading @@ -385,7 +269,9 @@ public class PanelView extends FrameLayout { mInitialTouchY = y; mInitialTouchX = x; if (mVelocityTracker == null) { initVelocityTracker(); } trackMovement(event); mTimeAnimator.cancel(); // end any outstanding animations onTrackingStarted(); Loading Loading @@ -569,7 +455,7 @@ public class PanelView extends FrameLayout { if (mVelocityTracker != null) { mVelocityTracker.recycle(); } mVelocityTracker = FlingTracker.obtain(); mVelocityTracker = VelocityTrackerFactory.obtain(getContext()); } protected boolean isScrolledToBottom() { Loading packages/SystemUI/src/com/android/systemui/statusbar/phone/PlatformVelocityTracker.java 0 → 100644 +72 −0 Original line number Diff line number Diff line /* * 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); } } packages/SystemUI/src/com/android/systemui/statusbar/phone/VelocityTrackerFactory.java 0 → 100644 +44 −0 Original line number Diff line number Diff line /* * 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); } } } Loading
packages/SystemUI/res/values/config.xml +4 −0 Original line number Diff line number Diff line Loading @@ -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>
packages/SystemUI/src/com/android/systemui/statusbar/phone/NoisyVelocityTracker.java 0 → 100644 +135 −0 Original line number Diff line number Diff line /* * 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); } }
packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java +5 −119 Original line number Diff line number Diff line Loading @@ -80,123 +80,7 @@ public class PanelView extends FrameLayout { 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; Loading Loading @@ -385,7 +269,9 @@ public class PanelView extends FrameLayout { mInitialTouchY = y; mInitialTouchX = x; if (mVelocityTracker == null) { initVelocityTracker(); } trackMovement(event); mTimeAnimator.cancel(); // end any outstanding animations onTrackingStarted(); Loading Loading @@ -569,7 +455,7 @@ public class PanelView extends FrameLayout { if (mVelocityTracker != null) { mVelocityTracker.recycle(); } mVelocityTracker = FlingTracker.obtain(); mVelocityTracker = VelocityTrackerFactory.obtain(getContext()); } protected boolean isScrolledToBottom() { Loading
packages/SystemUI/src/com/android/systemui/statusbar/phone/PlatformVelocityTracker.java 0 → 100644 +72 −0 Original line number Diff line number Diff line /* * 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); } }
packages/SystemUI/src/com/android/systemui/statusbar/phone/VelocityTrackerFactory.java 0 → 100644 +44 −0 Original line number Diff line number Diff line /* * 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); } } }