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