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