Home | History | Annotate | Download | only in view
      1 /*
      2  * Copyright (C) 2010 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package android.view;
     18 
     19 import junit.framework.Assert;
     20 
     21 import android.test.InstrumentationTestCase;
     22 import android.test.suitebuilder.annotation.MediumTest;
     23 import android.view.animation.AccelerateInterpolator;
     24 import android.view.animation.DecelerateInterpolator;
     25 import android.view.animation.Interpolator;
     26 import android.view.animation.LinearInterpolator;
     27 
     28 /**
     29  * Exercises {@link android.view.VelocityTracker} to compute correct velocity.<br>
     30  * To launch this test, use :<br>
     31  * <code>./development/testrunner/runtest.py framework -c android.view.VelocityTest</code>
     32  */
     33 public class VelocityTest extends InstrumentationTestCase {
     34 
     35     @MediumTest
     36     public void testInitialCondiditions() {
     37         VelocityTracker vt = VelocityTracker.obtain();
     38         assertNotNull(vt);
     39         vt.recycle();
     40     }
     41 
     42     /**
     43      * Test that {@link android.view.VelocityTracker}.clear() clears
     44      * the previous values after a call to computeCurrentVelocity()
     45      */
     46     @MediumTest
     47     public void testClear() {
     48         long t = System.currentTimeMillis();
     49         VelocityTracker vt = VelocityTracker.obtain();
     50         drag(vt, 100, 200, 100, 200, 10, t, 300);
     51         vt.computeCurrentVelocity(1);
     52         assertFalse("Velocity should not be null", vt.getXVelocity() == 0.0f);
     53         assertFalse("Velocity should not be null", vt.getYVelocity() == 0.0f);
     54         vt.clear();
     55         vt.computeCurrentVelocity(1);
     56         assertEquals(0.0f, vt.getXVelocity());
     57         assertEquals(0.0f, vt.getYVelocity());
     58         vt.recycle();
     59     }
     60 
     61     @MediumTest
     62     public void testDragAcceleration () {
     63         long t = System.currentTimeMillis();
     64         VelocityTracker vt = VelocityTracker.obtain();
     65         drag(vt, 100, 200, 100, 200, 15, t, 400, new AccelerateInterpolator());
     66         vt.computeCurrentVelocity(1000);
     67         assertGreater(250.0f, vt.getXVelocity());
     68         assertGreater(250.0f, vt.getYVelocity());
     69         vt.recycle();
     70     }
     71 
     72     @MediumTest
     73     public void testDragDeceleration () {
     74         long t = System.currentTimeMillis();
     75         VelocityTracker vt = VelocityTracker.obtain();
     76         drag(vt, 100, 200, 100, 200, 15, t, 400, new DecelerateInterpolator());
     77         vt.computeCurrentVelocity(1000);
     78         assertLower(250.0f, vt.getXVelocity());
     79         assertLower(250.0f, vt.getYVelocity());
     80         vt.recycle();
     81     }
     82 
     83     @MediumTest
     84     public void testDragLinearHorizontal() {
     85         long t = System.currentTimeMillis();
     86         VelocityTracker vt = VelocityTracker.obtain();
     87         // 100px in 400ms => 250px/s
     88         drag(vt, 100, 200, 200, 200, 15, t, 400);
     89         vt.computeCurrentVelocity(1000);
     90         assertEquals(0.0f, vt.getYVelocity());
     91         assertEqualFuzzy(250.0f, vt.getXVelocity(), 4f);
     92         vt.recycle();
     93     }
     94 
     95     @MediumTest
     96     public void testDragLinearVertical() {
     97         long t = System.currentTimeMillis();
     98         VelocityTracker vt = VelocityTracker.obtain();
     99         // 100px in 400ms => 250px/s
    100         drag(vt, 200, 200, 100, 200, 15, t, 400);
    101         vt.computeCurrentVelocity(1000);
    102         assertEquals(0.0f, vt.getXVelocity());
    103         assertEqualFuzzy(250.0f, vt.getYVelocity(), 4f);
    104         vt.recycle();
    105     }
    106 
    107     /**
    108      * Test dragging with two points only
    109      * (velocity must be an exact value)
    110      */
    111     @MediumTest
    112     public void testDragWith2Points () {
    113         long t = System.currentTimeMillis();
    114         VelocityTracker vt = VelocityTracker.obtain();
    115         // 100px, 2 steps, 100ms => 1000px/s
    116         drag(vt, 100, 200, 100, 200, 2, t, 100);
    117         vt.computeCurrentVelocity(1000);
    118         assertEquals(1000.0f, vt.getXVelocity());
    119         assertEquals(1000.0f, vt.getYVelocity());
    120         vt.recycle();
    121     }
    122 
    123     /**
    124      * Velocity is independent of the number of points used during
    125      * the same interval
    126      */
    127     @MediumTest
    128     public void testStabilityInNbPoints () {
    129         long t = System.currentTimeMillis();
    130         VelocityTracker vt = VelocityTracker.obtain();
    131         drag(vt, 100, 200, 100, 200, 10, t, 400); // 10 steps over 400ms
    132         vt.computeCurrentVelocity(1);
    133         float firstX = vt.getXVelocity();
    134         float firstY = vt.getYVelocity();
    135         vt.clear();
    136         drag(vt, 100, 200, 100, 200, 20, t, 400); // 20 steps over 400ms
    137         vt.computeCurrentVelocity(1);
    138         float secondX = vt.getXVelocity();
    139         float secondY = vt.getYVelocity();
    140         assertEqualFuzzy(firstX, secondX, 0.1f);
    141         assertEqualFuzzy(firstY, secondY, 0.1f);
    142         vt.recycle();
    143     }
    144 
    145     /**
    146      * Velocity is independent of the time when the events occurs,
    147      * it only depends on delays between the events.
    148      */
    149     @MediumTest
    150     public void testStabilityInTime () {
    151         long t = System.currentTimeMillis();
    152         VelocityTracker vt = VelocityTracker.obtain();
    153         drag(vt, 100, 200, 100, 200, 10, t, 400);
    154         vt.computeCurrentVelocity(1);
    155         float firstX = vt.getXVelocity();
    156         float firstY = vt.getYVelocity();
    157         vt.clear();
    158         drag(vt, 100, 200, 100, 200, 10, t + 3600*1000, 400); // on hour later
    159         vt.computeCurrentVelocity(1);
    160         float secondX = vt.getXVelocity();
    161         float secondY = vt.getYVelocity();
    162         assertEqualFuzzy(firstX, secondX, 0.1f);
    163         assertEqualFuzzy(firstY, secondY, 0.1f);
    164         vt.recycle();
    165     }
    166 
    167     /**
    168      * Velocity is independent of the position of the events,
    169      * it only depends on their relative distance.
    170      */
    171     @MediumTest
    172     public void testStabilityInSpace () {
    173         long t = System.currentTimeMillis();
    174         VelocityTracker vt = VelocityTracker.obtain();
    175         drag(vt, 100, 200, 100, 200, 10, t, 400);
    176         vt.computeCurrentVelocity(1);
    177         float firstX = vt.getXVelocity();
    178         float firstY = vt.getYVelocity();
    179         vt.clear();
    180         drag(vt, 200, 300, 200, 300, 10, t, 400); // 100px further
    181         vt.computeCurrentVelocity(1);
    182         float secondX = vt.getXVelocity();
    183         float secondY = vt.getYVelocity();
    184         assertEqualFuzzy(firstX, secondX, 0.1f);
    185         assertEqualFuzzy(firstY, secondY, 0.1f);
    186         vt.recycle();
    187     }
    188 
    189     /**
    190      * Test that calls to {@link android.view.VelocityTracker}.computeCurrentVelocity()
    191      * will output same values when using the same data.
    192      */
    193     @MediumTest
    194     public void testStabilityOfComputation() {
    195         long t = System.currentTimeMillis();
    196         VelocityTracker vt = VelocityTracker.obtain();
    197         drag(vt, 100, 200, 100, 200, 10, t, 300);
    198         vt.computeCurrentVelocity(1);
    199         float firstX = vt.getXVelocity();
    200         float firstY = vt.getYVelocity();
    201         vt.computeCurrentVelocity(1);
    202         float secondX = vt.getXVelocity();
    203         float secondY = vt.getYVelocity();
    204         assertEquals(firstX, secondX);
    205         assertEquals(firstY, secondY);
    206         vt.recycle();
    207     }
    208 
    209     /**
    210      * Test the units parameter of {@link android.view.VelocityTracker}.computeCurrentVelocity()
    211      */
    212     @MediumTest
    213     public void testStabilityOfUnits() {
    214         long t = System.currentTimeMillis();
    215         VelocityTracker vt = VelocityTracker.obtain();
    216         drag(vt, 100, 200, 100, 200, 10, t, 300);
    217         vt.computeCurrentVelocity(1);
    218         float firstX = vt.getXVelocity();
    219         float firstY = vt.getYVelocity();
    220         vt.computeCurrentVelocity(1000);
    221         float secondX = vt.getXVelocity();
    222         float secondY = vt.getYVelocity();
    223         assertEqualFuzzy(firstX, secondX / 1000.0f, 0.1f);
    224         assertEqualFuzzy(firstY, secondY / 1000.0f, 0.1f);
    225         vt.recycle();
    226     }
    227 
    228     /**
    229      * Simulate a drag by giving directly MotionEvents to
    230      * the VelocityTracker using a linear interpolator
    231      */
    232     private void drag(VelocityTracker vt, int startX, int endX, int startY, int endY, int steps,
    233             long startime, int duration) {
    234         drag(vt, startX, endX, startY, endY, steps, startime, duration, new LinearInterpolator());
    235     }
    236 
    237     /**
    238      * Simulate a drag by giving directly MotionEvents to
    239      * the VelocityTracker using a given interpolator
    240      */
    241     private void drag(VelocityTracker vt, int startX, int endX, int startY, int endY, int steps,
    242             long startime, int duration, Interpolator interpolator) {
    243         addMotionEvent(vt, startX, startY, startime, MotionEvent.ACTION_DOWN);
    244         float dt = duration / (float)steps;
    245         int distX = endX - startX;
    246         int distY = endY - startY;
    247         for (int i=1; i<steps-1; i++) {
    248             float ii = interpolator.getInterpolation(i / (float)steps);
    249             int x = (int) (startX + distX * ii);
    250             int y = (int) (startY + distY * ii);
    251             long time = startime + (int) (i * dt);
    252             addMotionEvent(vt, x, y, time, MotionEvent.ACTION_MOVE);
    253         }
    254         addMotionEvent(vt, endX, endY, startime + duration, MotionEvent.ACTION_UP);
    255     }
    256 
    257     private void addMotionEvent(VelocityTracker vt, int x, int y, long time, int action) {
    258         MotionEvent me = MotionEvent.obtain(time, time, action, x, y, 0);
    259         vt.addMovement(me);
    260         me.recycle();
    261     }
    262 
    263     /**
    264      * Float imprecision of the average computations and filtering
    265      * (removing last MotionEvent for N > 3) implies that tests
    266      *  accepts some approximated values.
    267      */
    268     private void assertEqualFuzzy(float expected, float actual, float threshold) {
    269         boolean fuzzyEqual = actual >= expected - threshold && actual <= expected + threshold;
    270         Assert.assertTrue("Expected: <"+expected+"> but was: <"+actual+
    271                 "> while accepting a variation of: <"+threshold+">", fuzzyEqual);
    272     }
    273 
    274     private void assertGreater(float minExpected, float actual) {
    275         Assert.assertTrue("Expected: minimum <"+minExpected+"> but was: <"+actual+">",
    276                 actual > minExpected);
    277     }
    278 
    279     private void assertLower(float maxExpected, float actual) {
    280         Assert.assertTrue("Expected: maximum <"+maxExpected+"> but was: <"+actual+">",
    281                 actual < maxExpected);
    282     }
    283 }
    284