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