1 /* 2 * Copyright 2024 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.test.input 18 19 import android.content.Context 20 import android.content.res.Configuration 21 import android.content.res.Resources 22 import android.view.ContextThemeWrapper 23 import android.view.PointerIcon 24 import android.view.flags.Flags.enableVectorCursorA11ySettings 25 import android.view.flags.Flags.enableVectorCursors 26 import androidx.test.ext.junit.runners.AndroidJUnit4 27 import androidx.test.filters.SmallTest 28 import androidx.test.platform.app.InstrumentationRegistry 29 import org.junit.Assume.assumeTrue 30 import org.junit.Before 31 import org.junit.Rule 32 import org.junit.Test 33 import org.junit.rules.TestName 34 import org.junit.runner.RunWith 35 import platform.test.screenshot.GoldenPathManager 36 import platform.test.screenshot.PathConfig 37 import platform.test.screenshot.ScreenshotTestRule 38 import platform.test.screenshot.assertAgainstGolden 39 import platform.test.screenshot.matchers.BitmapMatcher 40 import platform.test.screenshot.matchers.PixelPerfectMatcher 41 42 /** 43 * Unit tests for PointerIcon. 44 * 45 * Run with: atest InputTests:com.android.test.input.PointerIconLoadingTest 46 */ 47 @SmallTest 48 @RunWith(AndroidJUnit4::class) 49 class PointerIconLoadingTest { 50 private lateinit var context: Context 51 private lateinit var exactScreenshotMatcher: BitmapMatcher 52 53 @get:Rule val testName = TestName() 54 55 @get:Rule 56 val screenshotRule = 57 ScreenshotTestRule( 58 GoldenPathManager( 59 InstrumentationRegistry.getInstrumentation().getContext(), 60 ASSETS_PATH, 61 TEST_OUTPUT_PATH, 62 PathConfig(), 63 ), 64 disableIconPool = false, 65 ) 66 67 @Before setUpnull68 fun setUp() { 69 context = InstrumentationRegistry.getInstrumentation().targetContext 70 val config = 71 Configuration(context.resources.configuration).apply { 72 densityDpi = DENSITY_DPI 73 screenWidthDp = SCREEN_WIDTH_DP 74 screenHeightDp = SCREEN_HEIGHT_DP 75 smallestScreenWidthDp = SCREEN_WIDTH_DP 76 } 77 context = context.createConfigurationContext(config) 78 79 exactScreenshotMatcher = PixelPerfectMatcher() 80 } 81 82 @Test testPointerFillStylenull83 fun testPointerFillStyle() { 84 assumeTrue(enableVectorCursors()) 85 assumeTrue(enableVectorCursorA11ySettings()) 86 87 val theme: Resources.Theme = context.getResources().newTheme() 88 theme.setTo(context.getTheme()) 89 theme.applyStyle( 90 PointerIcon.vectorFillStyleToResource(PointerIcon.POINTER_ICON_VECTOR_STYLE_FILL_GREEN), 91 /* force= */ true, 92 ) 93 theme.applyStyle( 94 PointerIcon.vectorStrokeStyleToResource( 95 PointerIcon.POINTER_ICON_VECTOR_STYLE_STROKE_WHITE 96 ), 97 /* force= */ true, 98 ) 99 100 val pointerIcon = 101 PointerIcon.getLoadedSystemIcon( 102 ContextThemeWrapper(context, theme), 103 PointerIcon.TYPE_ARROW, 104 /* useLargeIcons= */ false, 105 /* pointerScale= */ 1f, 106 ) 107 108 pointerIcon 109 .getBitmap() 110 .assertAgainstGolden(screenshotRule, testName.methodName, exactScreenshotMatcher) 111 } 112 113 @Test testPointerStrokeStylenull114 fun testPointerStrokeStyle() { 115 assumeTrue(enableVectorCursors()) 116 assumeTrue(enableVectorCursorA11ySettings()) 117 118 val theme: Resources.Theme = context.getResources().newTheme() 119 theme.setTo(context.getTheme()) 120 theme.applyStyle( 121 PointerIcon.vectorFillStyleToResource(PointerIcon.POINTER_ICON_VECTOR_STYLE_FILL_BLACK), 122 /* force= */ true, 123 ) 124 theme.applyStyle( 125 PointerIcon.vectorStrokeStyleToResource( 126 PointerIcon.POINTER_ICON_VECTOR_STYLE_STROKE_BLACK 127 ), 128 /* force= */ true, 129 ) 130 131 val pointerIcon = 132 PointerIcon.getLoadedSystemIcon( 133 ContextThemeWrapper(context, theme), 134 PointerIcon.TYPE_ARROW, 135 /* useLargeIcons= */ false, 136 /* pointerScale= */ 1f, 137 ) 138 139 pointerIcon 140 .getBitmap() 141 .assertAgainstGolden(screenshotRule, testName.methodName, exactScreenshotMatcher) 142 } 143 144 @Test testPointerScalenull145 fun testPointerScale() { 146 assumeTrue(enableVectorCursors()) 147 assumeTrue(enableVectorCursorA11ySettings()) 148 149 val theme: Resources.Theme = context.getResources().newTheme() 150 theme.setTo(context.getTheme()) 151 theme.applyStyle( 152 PointerIcon.vectorFillStyleToResource(PointerIcon.POINTER_ICON_VECTOR_STYLE_FILL_BLACK), 153 /* force= */ true, 154 ) 155 theme.applyStyle( 156 PointerIcon.vectorStrokeStyleToResource( 157 PointerIcon.POINTER_ICON_VECTOR_STYLE_STROKE_WHITE 158 ), 159 /* force= */ true, 160 ) 161 val pointerScale = 2f 162 163 val pointerIcon = 164 PointerIcon.getLoadedSystemIcon( 165 ContextThemeWrapper(context, theme), 166 PointerIcon.TYPE_ARROW, 167 /* useLargeIcons= */ false, 168 pointerScale, 169 ) 170 171 pointerIcon 172 .getBitmap() 173 .assertAgainstGolden(screenshotRule, testName.methodName, exactScreenshotMatcher) 174 } 175 176 companion object { 177 const val DENSITY_DPI = 160 178 const val SCREEN_WIDTH_DP = 480 179 const val SCREEN_HEIGHT_DP = 800 180 const val ASSETS_PATH = "tests/input/assets" 181 val TEST_OUTPUT_PATH = 182 "/sdcard/Download/InputTests/" + PointerIconLoadingTest::class.java.simpleName 183 } 184 } 185