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 package android.graphics.cts; 17 18 import static androidx.test.InstrumentationRegistry.getInstrumentation; 19 20 import static org.junit.Assert.assertEquals; 21 import static org.junit.Assert.assertTrue; 22 23 import android.content.res.Resources; 24 import android.graphics.Color; 25 import android.util.Log; 26 import android.util.TypedValue; 27 28 import androidx.test.filters.SmallTest; 29 import androidx.test.runner.AndroidJUnit4; 30 31 import org.junit.Test; 32 import org.junit.runner.RunWith; 33 34 import java.lang.annotation.Annotation; 35 import java.lang.reflect.Field; 36 import java.util.Arrays; 37 import java.util.List; 38 39 @SmallTest 40 @RunWith(AndroidJUnit4.class) 41 public class ColorTest { 42 43 private static final String LOG_TAG = ColorTest.class.getSimpleName(); 44 45 @Test 46 public void resourceColor() { 47 int colors [][] = { 48 { 0xff000000, android.R.color.background_dark }, 49 { 0xffffffff, android.R.color.background_light }, 50 { 0xff000000, android.R.color.black }, 51 { 0xffaaaaaa, android.R.color.darker_gray }, 52 { 0xff00ddff, android.R.color.holo_blue_bright }, 53 { 0xff0099cc, android.R.color.holo_blue_dark }, 54 { 0xff33b5e5, android.R.color.holo_blue_light }, 55 { 0xff669900, android.R.color.holo_green_dark }, 56 { 0xff99cc00, android.R.color.holo_green_light }, 57 { 0xffff8800, android.R.color.holo_orange_dark }, 58 { 0xffffbb33, android.R.color.holo_orange_light }, 59 { 0xffaa66cc, android.R.color.holo_purple }, 60 { 0xffcc0000, android.R.color.holo_red_dark }, 61 { 0xffff4444, android.R.color.holo_red_light }, 62 { 0xffffffff, android.R.color.primary_text_dark }, 63 { 0xffffffff, android.R.color.primary_text_dark_nodisable }, 64 { 0xff000000, android.R.color.primary_text_light }, 65 { 0xff000000, android.R.color.primary_text_light_nodisable }, 66 { 0xffbebebe, android.R.color.secondary_text_dark }, 67 { 0xffbebebe, android.R.color.secondary_text_dark_nodisable }, 68 { 0xff323232, android.R.color.secondary_text_light }, 69 { 0xffbebebe, android.R.color.secondary_text_light_nodisable }, 70 { 0xff808080, android.R.color.tab_indicator_text }, 71 { 0xff808080, android.R.color.tertiary_text_dark }, 72 { 0xff808080, android.R.color.tertiary_text_light }, 73 { 0x00000000, android.R.color.transparent }, 74 { 0xffffffff, android.R.color.white }, 75 { 0xff000000, android.R.color.widget_edittext_dark }, 76 }; 77 78 List<Integer> expectedColorStateLists = Arrays.asList( 79 android.R.color.primary_text_dark, 80 android.R.color.primary_text_dark_nodisable, 81 android.R.color.primary_text_light, 82 android.R.color.primary_text_light_nodisable, 83 android.R.color.secondary_text_dark, 84 android.R.color.secondary_text_dark_nodisable, 85 android.R.color.secondary_text_light, 86 android.R.color.secondary_text_light_nodisable, 87 android.R.color.tab_indicator_text, 88 android.R.color.tertiary_text_dark, 89 android.R.color.tertiary_text_light, 90 android.R.color.widget_edittext_dark 91 ); 92 93 Resources resources = getInstrumentation().getTargetContext().getResources(); 94 for (int[] pair : colors) { 95 final int resourceId = pair[1]; 96 final int expectedColor = pair[0]; 97 98 // validate color from getColor 99 int observedColor = resources.getColor(resourceId, null); 100 assertEquals("Color = " + Integer.toHexString(observedColor) + ", " 101 + Integer.toHexString(expectedColor) + " expected", 102 expectedColor, 103 observedColor); 104 105 // validate color from getValue 106 TypedValue value = new TypedValue(); 107 resources.getValue(resourceId, value, true); 108 109 // colors shouldn't depend on config changes 110 assertEquals(0, value.changingConfigurations); 111 112 if (expectedColorStateLists.contains(resourceId)) { 113 // ColorStateLists are strings 114 assertEquals("CSLs should be strings", TypedValue.TYPE_STRING, value.type); 115 } else { 116 // colors should be raw ints 117 assertTrue("Type should be int", 118 value.type >= TypedValue.TYPE_FIRST_INT 119 && value.type <= TypedValue.TYPE_LAST_INT); 120 121 // Validate color from getValue 122 assertEquals("Color should be expected value", expectedColor, value.data); 123 } 124 } 125 126 // System-API colors are used to allow updateable platform components to use the same colors 127 // as the system. The actualy value of the color does not matter. Hence only enforce that 128 // 'colors' contains all the public colors and ignore System-api colors. 129 int numPublicApiColors = 0; 130 for (Field declaredColor : android.R.color.class.getDeclaredFields()) { 131 if (Arrays.stream(declaredColor.getDeclaredAnnotations()).anyMatch( 132 (Annotation a) -> a.toString().contains("SystemApi"))) { 133 Log.i(LOG_TAG, declaredColor.getName() + " is SystemApi"); 134 } else { 135 numPublicApiColors++; 136 } 137 } 138 139 assertEquals("Test no longer in sync with colors in android.R.color", 140 colors.length, numPublicApiColors); 141 } 142 143 @Test 144 public void testAlpha() { 145 assertEquals(0xff, Color.alpha(Color.RED)); 146 assertEquals(0xff, Color.alpha(Color.YELLOW)); 147 } 148 149 @Test 150 public void testArgb() { 151 assertEquals(Color.RED, Color.argb(0xff, 0xff, 0x00, 0x00)); 152 assertEquals(Color.YELLOW, Color.argb(0xff, 0xff, 0xff, 0x00)); 153 assertEquals(Color.RED, Color.argb(1.0f, 1.0f, 0.0f, 0.0f)); 154 assertEquals(Color.YELLOW, Color.argb(1.0f, 1.0f, 1.0f, 0.0f)); 155 } 156 157 @Test 158 public void testBlue() { 159 assertEquals(0x00, Color.blue(Color.RED)); 160 assertEquals(0x00, Color.blue(Color.YELLOW)); 161 } 162 163 @Test 164 public void testGreen() { 165 assertEquals(0x00, Color.green(Color.RED)); 166 assertEquals(0xff, Color.green(Color.GREEN)); 167 } 168 169 @Test(expected=RuntimeException.class) 170 public void testHSVToColorArrayTooShort() { 171 // abnormal case: hsv length less than 3 172 float[] hsv = new float[2]; 173 Color.HSVToColor(hsv); 174 } 175 176 @Test 177 public void testHSVToColor() { 178 float[] hsv = new float[3]; 179 Color.colorToHSV(Color.RED, hsv); 180 assertEquals(Color.RED, Color.HSVToColor(hsv)); 181 } 182 183 @Test 184 public void testHSVToColorWithAlpha() { 185 float[] hsv = new float[3]; 186 Color.colorToHSV(Color.RED, hsv); 187 assertEquals(Color.RED, Color.HSVToColor(0xff, hsv)); 188 } 189 190 @Test(expected=IllegalArgumentException.class) 191 public void testParseColorStringOfInvalidLength() { 192 // abnormal case: colorString starts with '#' but length is neither 7 nor 9 193 Color.parseColor("#ff00ff0"); 194 } 195 196 @Test 197 public void testParseColor() { 198 assertEquals(Color.RED, Color.parseColor("#ff0000")); 199 assertEquals(Color.RED, Color.parseColor("#ffff0000")); 200 201 assertEquals(Color.BLACK, Color.parseColor("black")); 202 assertEquals(Color.DKGRAY, Color.parseColor("darkgray")); 203 assertEquals(Color.GRAY, Color.parseColor("gray")); 204 assertEquals(Color.LTGRAY, Color.parseColor("lightgray")); 205 assertEquals(Color.WHITE, Color.parseColor("white")); 206 assertEquals(Color.RED, Color.parseColor("red")); 207 assertEquals(Color.GREEN, Color.parseColor("green")); 208 assertEquals(Color.BLUE, Color.parseColor("blue")); 209 assertEquals(Color.YELLOW, Color.parseColor("yellow")); 210 assertEquals(Color.CYAN, Color.parseColor("cyan")); 211 assertEquals(Color.MAGENTA, Color.parseColor("magenta")); 212 } 213 214 @Test(expected=IllegalArgumentException.class) 215 public void testParseColorUnsupportedFormat() { 216 // abnormal case: colorString doesn't start with '#' and is unknown color 217 Color.parseColor("hello"); 218 } 219 220 @Test 221 public void testRed() { 222 assertEquals(0xff, Color.red(Color.RED)); 223 assertEquals(0xff, Color.red(Color.YELLOW)); 224 } 225 226 @Test 227 public void testRgb() { 228 assertEquals(Color.RED, Color.rgb(0xff, 0x00, 0x00)); 229 assertEquals(Color.YELLOW, Color.rgb(0xff, 0xff, 0x00)); 230 assertEquals(Color.RED, Color.rgb(1.0f, 0.0f, 0.0f)); 231 assertEquals(Color.YELLOW, Color.rgb(1.0f, 1.0f, 0.0f)); 232 } 233 234 @Test(expected=RuntimeException.class) 235 public void testRGBToHSVArrayTooShort() { 236 // abnormal case: hsv length less than 3 237 float[] hsv = new float[2]; 238 Color.RGBToHSV(0xff, 0x00, 0x00, hsv); 239 } 240 241 @Test 242 public void testRGBToHSV() { 243 float[] hsv = new float[3]; 244 Color.RGBToHSV(0xff, 0x00, 0x00, hsv); 245 assertEquals(Color.RED, Color.HSVToColor(hsv)); 246 } 247 248 @Test 249 public void testLuminance() { 250 assertEquals(0, Color.luminance(Color.BLACK), 0); 251 float eps = 0.000001f; 252 assertEquals(0.0722, Color.luminance(Color.BLUE), eps); 253 assertEquals(0.2126, Color.luminance(Color.RED), eps); 254 assertEquals(0.7152, Color.luminance(Color.GREEN), eps); 255 assertEquals(1, Color.luminance(Color.WHITE), 0); 256 } 257 } 258