1 /* 2 * Copyright (C) 2008 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.cts; 18 19 import static org.junit.Assert.assertEquals; 20 import static org.junit.Assert.assertNotNull; 21 import static org.junit.Assert.assertTrue; 22 23 import android.content.Context; 24 import android.graphics.Point; 25 import android.hardware.input.InputManager; 26 import android.util.TypedValue; 27 import android.view.Display; 28 import android.view.InputDevice; 29 import android.view.MotionEvent; 30 import android.view.ViewConfiguration; 31 import android.view.WindowManager; 32 33 import androidx.test.InstrumentationRegistry; 34 import androidx.test.filters.SmallTest; 35 import androidx.test.runner.AndroidJUnit4; 36 37 import java.util.ArrayList; 38 import java.util.List; 39 40 import org.junit.Test; 41 import org.junit.runner.RunWith; 42 43 /** 44 * Test {@link ViewConfiguration}. 45 */ 46 @SmallTest 47 @RunWith(AndroidJUnit4.class) 48 public class ViewConfigurationTest { 49 @Test testStaticValues()50 public void testStaticValues() { 51 ViewConfiguration.getScrollBarSize(); 52 ViewConfiguration.getFadingEdgeLength(); 53 ViewConfiguration.getPressedStateDuration(); 54 ViewConfiguration.getLongPressTimeout(); 55 assertTrue(ViewConfiguration.getMultiPressTimeout() > 0); 56 ViewConfiguration.getTapTimeout(); 57 ViewConfiguration.getJumpTapTimeout(); 58 ViewConfiguration.getEdgeSlop(); 59 ViewConfiguration.getTouchSlop(); 60 ViewConfiguration.getWindowTouchSlop(); 61 ViewConfiguration.getMinimumFlingVelocity(); 62 ViewConfiguration.getMaximumFlingVelocity(); 63 ViewConfiguration.getMaximumDrawingCacheSize(); 64 ViewConfiguration.getZoomControlsTimeout(); 65 ViewConfiguration.getGlobalActionKeyTimeout(); 66 ViewConfiguration.getScrollFriction(); 67 ViewConfiguration.getScrollBarFadeDuration(); 68 ViewConfiguration.getScrollDefaultDelay(); 69 ViewConfiguration.getDoubleTapTimeout(); 70 ViewConfiguration.getKeyRepeatTimeout(); 71 ViewConfiguration.getKeyRepeatDelay(); 72 ViewConfiguration.getDefaultActionModeHideDuration(); 73 } 74 75 @Test testConstructor()76 public void testConstructor() { 77 new ViewConfiguration(); 78 } 79 80 @Test testInstanceValues()81 public void testInstanceValues() { 82 Context context = InstrumentationRegistry.getTargetContext(); 83 ViewConfiguration vc = ViewConfiguration.get(context); 84 assertNotNull(vc); 85 86 vc.getScaledDoubleTapSlop(); 87 vc.getScaledEdgeSlop(); 88 vc.getScaledFadingEdgeLength(); 89 vc.getScaledMaximumDrawingCacheSize(); 90 vc.getScaledMaximumFlingVelocity(); 91 vc.getScaledMinimumFlingVelocity(); 92 vc.getScaledOverflingDistance(); 93 vc.getScaledOverscrollDistance(); 94 vc.getScaledPagingTouchSlop(); 95 vc.getScaledScrollBarSize(); 96 vc.getScaledHorizontalScrollFactor(); 97 vc.getScaledVerticalScrollFactor(); 98 vc.getScaledTouchSlop(); 99 vc.getScaledHandwritingSlop(); 100 vc.getScaledWindowTouchSlop(); 101 vc.hasPermanentMenuKey(); 102 103 float pixelsToMmRatio = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_MM, 1, 104 context.getResources().getDisplayMetrics()); 105 106 // Verify that the min scaling span size is reasonable. 107 float scaledMinScalingSpanMm = vc.getScaledMinimumScalingSpan() / pixelsToMmRatio; 108 assertTrue(scaledMinScalingSpanMm > 0); 109 assertTrue(scaledMinScalingSpanMm < 40.5); // 1.5 times the recommended size of 27mm 110 } 111 112 @Test 113 public void testExceptionsThrown() { 114 ViewConfiguration vc = new ViewConfiguration(); 115 boolean correctExceptionThrown = false; 116 try { 117 vc.getScaledMinimumScalingSpan(); 118 } catch (IllegalStateException e) { 119 if (e.getMessage().equals("Min scaling span cannot be determined when this " 120 + "method is called on a ViewConfiguration that was instantiated using a " 121 + "constructor with no Context parameter")) { 122 correctExceptionThrown = true; 123 } 124 } 125 assertTrue(correctExceptionThrown); 126 } 127 128 /** 129 * The purpose of the ambiguous gesture multiplier is to potentially increase the touch slop 130 * and the long press timeout to allow the gesture classifier an additional window to 131 * make the classification. Therefore, this multiplier should be always greater or equal to 1. 132 */ 133 @Test 134 public void testGetAmbiguousGestureMultiplier() { 135 final float staticMultiplier = ViewConfiguration.getAmbiguousGestureMultiplier(); 136 assertTrue(staticMultiplier >= 1); 137 138 ViewConfiguration vc = ViewConfiguration.get(InstrumentationRegistry.getTargetContext()); 139 final float instanceMultiplier = vc.getAmbiguousGestureMultiplier(); 140 assertTrue(instanceMultiplier >= 1); 141 } 142 143 @Test testFlingThresholds_forInvalidInputDeviceIds()144 public void testFlingThresholds_forInvalidInputDeviceIds() { 145 Context context = InstrumentationRegistry.getTargetContext(); 146 InputManager inputManager = context.getSystemService(InputManager.class); 147 148 ViewConfiguration contextBasedVc = ViewConfiguration.get(context); 149 ViewConfiguration contextLessVc = new ViewConfiguration(); 150 for (ViewConfiguration vc : new ViewConfiguration[] {contextBasedVc, contextLessVc}) { 151 // "50" randomly chosen to cover some array of integers. 152 for (int deviceId = -50; deviceId < 50; deviceId++) { 153 InputDevice device = inputManager.getInputDevice(deviceId); 154 if (device != null) { 155 continue; // Test only invalid device IDs. Continue... 156 } 157 158 // Test with some source-axis combinations. Any source-axis combination should 159 // provide the no-fling thresholds, since the device ID is known to be invalid. 160 verifyNoFlingThresholds( 161 vc, deviceId, InputDevice.SOURCE_TOUCHSCREEN, MotionEvent.AXIS_X); 162 verifyNoFlingThresholds( 163 vc, deviceId, InputDevice.SOURCE_TOUCHSCREEN, MotionEvent.AXIS_Y); 164 verifyNoFlingThresholds( 165 vc, deviceId, InputDevice.SOURCE_ROTARY_ENCODER, MotionEvent.AXIS_SCROLL); 166 } 167 } 168 } 169 170 @Test testFlingThresholds_forAllAvailableDevices()171 public void testFlingThresholds_forAllAvailableDevices() { 172 Context context = InstrumentationRegistry.getTargetContext(); 173 InputManager inputManager = context.getSystemService(InputManager.class); 174 int[] deviceIds = context.getSystemService(InputManager.class).getInputDeviceIds(); 175 176 ViewConfiguration contextBasedVc = ViewConfiguration.get(context); 177 ViewConfiguration contextLessVc = new ViewConfiguration(); 178 for (ViewConfiguration vc : new ViewConfiguration[] {contextBasedVc, contextLessVc}) { 179 for (int deviceId : deviceIds) { 180 InputDevice device = inputManager.getInputDevice(deviceId); 181 for (InputDevice.MotionRange motionRange : device.getMotionRanges()) { 182 int axis = motionRange.getAxis(); 183 int source = motionRange.getSource(); 184 185 int minVel = vc.getScaledMinimumFlingVelocity(deviceId, axis, source); 186 int maxVel = vc.getScaledMaximumFlingVelocity(deviceId, axis, source); 187 188 // These min/max thresholds are thresholds for a valid InputDevice ID, on a 189 // source and axis applicable to the InputDevice represented by the ID. Check 190 // that the provided thresholds are within the valid bounds. 191 verifyFlingThresholdRange(minVel, maxVel); 192 } 193 194 // Test with source-axis combinations that we know are not valid. Since the 195 // source-axis combinations will be invalid, we expect the no-fling thresholds, 196 // despite the fact that we're using a valid InputDevice ID. 197 verifyNoFlingThresholds( 198 vc, deviceId, InputDevice.SOURCE_ROTARY_ENCODER, MotionEvent.AXIS_X); 199 verifyNoFlingThresholds( 200 vc, deviceId, InputDevice.SOURCE_TOUCHSCREEN, MotionEvent.AXIS_WHEEL); 201 } 202 } 203 } 204 205 @Test testGetScaledAmbiguousGestureMultiplier()206 public void testGetScaledAmbiguousGestureMultiplier() { 207 ViewConfiguration vc = ViewConfiguration.get(InstrumentationRegistry.getTargetContext()); 208 final float instanceMultiplier = vc.getScaledAmbiguousGestureMultiplier(); 209 assertTrue(instanceMultiplier >= 1); 210 } 211 212 @Test testGetMaximumDrawingCacheSize()213 public void testGetMaximumDrawingCacheSize() { 214 Context context = InstrumentationRegistry.getTargetContext(); 215 ViewConfiguration vc = ViewConfiguration.get(context); 216 assertNotNull(vc); 217 218 // Should be at least the size of the screen we're supposed to draw into. 219 final WindowManager win = context.getSystemService(WindowManager.class); 220 final Display display = win.getDefaultDisplay(); 221 final Point size = new Point(); 222 display.getSize(size); 223 assertTrue(vc.getScaledMaximumDrawingCacheSize() >= size.x * size.y * 4); 224 225 // This deprecated value should just be what it's historically hardcoded to be. 226 assertEquals(480 * 800 * 4, vc.getMaximumDrawingCacheSize()); 227 } 228 229 /** Verifies whether or not the given fling thresholds are within the valid range. */ verifyFlingThresholdRange(int minVel, int maxVel)230 private static void verifyFlingThresholdRange(int minVel, int maxVel) { 231 if (minVel > maxVel) { 232 // The only case where we expect the minimum velocity to exceed the maximum velocity is 233 // for InputDevices that do not support fling, in which case the minimum and maximum 234 // velocties are set to Integer's max and min values, respectively. 235 verifyNoFlingThresholds(minVel, maxVel); 236 } else { 237 // If the minimum velocity is <= the maximum velocity, the velocities should represent 238 // valid thresholds, which should not be negative values (as the thresholds are defined 239 // as absolute values). 240 assertTrue(minVel >= 0); 241 assertTrue(maxVel >= 0); 242 } 243 } 244 verifyNoFlingThresholds( ViewConfiguration viewConfiguration, int deviceId, int source, int axis)245 private static void verifyNoFlingThresholds( 246 ViewConfiguration viewConfiguration, int deviceId, int source, int axis) { 247 verifyNoFlingThresholds( 248 viewConfiguration.getScaledMinimumFlingVelocity(deviceId, axis, source), 249 viewConfiguration.getScaledMaximumFlingVelocity(deviceId, axis, source)); 250 } 251 252 /** 253 * Verifies that the given min and max fling velocities represent the values used to suppress 254 * fling. 255 */ verifyNoFlingThresholds(int minVel, int maxVel)256 private static void verifyNoFlingThresholds(int minVel, int maxVel) { 257 assertEquals(Integer.MAX_VALUE, minVel); 258 assertEquals(Integer.MIN_VALUE, maxVel); 259 } 260 } 261