1 /* 2 * Copyright (C) 2021 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.hardware.input; 18 19 import static android.hardware.lights.LightsRequest.Builder; 20 21 import static com.google.common.truth.Truth.assertThat; 22 23 import static junit.framework.TestCase.assertEquals; 24 import static junit.framework.TestCase.assertNotNull; 25 26 import static org.junit.Assert.assertTrue; 27 import static org.mockito.ArgumentMatchers.any; 28 import static org.mockito.ArgumentMatchers.anyInt; 29 import static org.mockito.ArgumentMatchers.eq; 30 import static org.mockito.Mockito.doAnswer; 31 import static org.mockito.Mockito.spy; 32 import static org.mockito.Mockito.verify; 33 import static org.mockito.Mockito.when; 34 35 import android.content.Context; 36 import android.content.ContextWrapper; 37 import android.hardware.lights.Light; 38 import android.hardware.lights.LightState; 39 import android.hardware.lights.LightsManager; 40 import android.hardware.lights.LightsRequest; 41 import android.os.IBinder; 42 import android.platform.test.annotations.Presubmit; 43 import android.util.ArrayMap; 44 import android.view.InputDevice; 45 46 import androidx.test.platform.app.InstrumentationRegistry; 47 48 import com.android.test.input.MockInputManagerRule; 49 50 import org.junit.After; 51 import org.junit.Before; 52 import org.junit.Rule; 53 import org.junit.Test; 54 import org.junit.runner.RunWith; 55 import org.mockito.junit.MockitoJUnitRunner; 56 57 import java.util.ArrayList; 58 import java.util.Arrays; 59 import java.util.List; 60 61 /** 62 * Tests for {@link InputDeviceLightsManager}. 63 * 64 * Build/Install/Run: 65 * atest InputTests:InputDeviceLightsManagerTest 66 */ 67 @Presubmit 68 @RunWith(MockitoJUnitRunner.class) 69 public class InputDeviceLightsManagerTest { 70 private static final String TAG = "InputDeviceLightsManagerTest"; 71 72 private static final int DEVICE_ID = 1000; 73 private static final int PLAYER_ID = 3; 74 75 @Rule 76 public final MockInputManagerRule mInputManagerRule = new MockInputManagerRule(); 77 78 private InputManager mInputManager; 79 80 private InputManagerGlobal.TestSession mInputManagerGlobalSession; 81 82 @Before setUp()83 public void setUp() throws Exception { 84 final Context context = spy( 85 new ContextWrapper(InstrumentationRegistry.getInstrumentation().getContext())); 86 when(mInputManagerRule.getMock().getInputDeviceIds()).thenReturn(new int[]{DEVICE_ID}); 87 88 when(mInputManagerRule.getMock().getInputDevice(eq(DEVICE_ID))).thenReturn( 89 createInputDevice(DEVICE_ID)); 90 91 mInputManager = new InputManager(context); 92 when(context.getSystemService(eq(Context.INPUT_SERVICE))).thenReturn(mInputManager); 93 94 ArrayMap<Integer, LightState> lightStatesById = new ArrayMap<>(); 95 doAnswer(invocation -> { 96 final int[] lightIds = (int[]) invocation.getArguments()[1]; 97 final LightState[] lightStates = 98 (LightState[]) invocation.getArguments()[2]; 99 for (int i = 0; i < lightIds.length; i++) { 100 lightStatesById.put(lightIds[i], lightStates[i]); 101 } 102 return null; 103 }).when(mInputManagerRule.getMock()).setLightStates(eq(DEVICE_ID), 104 any(int[].class), any(LightState[].class), any(IBinder.class)); 105 106 doAnswer(invocation -> { 107 int lightId = (int) invocation.getArguments()[1]; 108 if (lightStatesById.containsKey(lightId)) { 109 return lightStatesById.get(lightId); 110 } 111 return new LightState(0); 112 }).when(mInputManagerRule.getMock()).getLightState(eq(DEVICE_ID), anyInt()); 113 } 114 115 @After tearDown()116 public void tearDown() { 117 if (mInputManagerGlobalSession != null) { 118 mInputManagerGlobalSession.close(); 119 } 120 } 121 createInputDevice(int id)122 private InputDevice createInputDevice(int id) { 123 return new InputDevice.Builder() 124 .setId(id) 125 .setName("Test Device " + id) 126 .build(); 127 } 128 mockLights(Light[] lights)129 private void mockLights(Light[] lights) throws Exception { 130 // Mock the Lights returned form InputManagerService 131 when(mInputManagerRule.getMock().getLights(eq(DEVICE_ID))).thenReturn( 132 new ArrayList(Arrays.asList(lights))); 133 } 134 135 @Test testGetInputDeviceLights()136 public void testGetInputDeviceLights() throws Exception { 137 InputDevice device = mInputManager.getInputDevice(DEVICE_ID); 138 assertNotNull(device); 139 140 Light[] mockedLights = { 141 new Light(1 /* id */, "Light1", 0 /* ordinal */, Light.LIGHT_TYPE_INPUT, 142 Light.LIGHT_CAPABILITY_BRIGHTNESS), 143 new Light(2 /* id */, "Light2", 0 /* ordinal */, Light.LIGHT_TYPE_INPUT, 144 Light.LIGHT_CAPABILITY_COLOR_RGB), 145 new Light(3 /* id */, "Light3", 0 /* ordinal */, Light.LIGHT_TYPE_INPUT, 146 0 /* capabilities */) 147 }; 148 mockLights(mockedLights); 149 150 LightsManager lightsManager = device.getLightsManager(); 151 List<Light> lights = lightsManager.getLights(); 152 verify(mInputManagerRule.getMock()).getLights(eq(DEVICE_ID)); 153 assertEquals(lights, Arrays.asList(mockedLights)); 154 } 155 156 @Test testControlMultipleLights()157 public void testControlMultipleLights() throws Exception { 158 InputDevice device = mInputManager.getInputDevice(DEVICE_ID); 159 assertNotNull(device); 160 161 Light[] mockedLights = { 162 new Light(1 /* id */, "Light1", 0 /* ordinal */, Light.LIGHT_TYPE_INPUT, 163 Light.LIGHT_CAPABILITY_COLOR_RGB), 164 new Light(2 /* id */, "Light2", 0 /* ordinal */, Light.LIGHT_TYPE_INPUT, 165 Light.LIGHT_CAPABILITY_COLOR_RGB), 166 new Light(3 /* id */, "Light3", 0 /* ordinal */, Light.LIGHT_TYPE_INPUT, 167 Light.LIGHT_CAPABILITY_COLOR_RGB), 168 new Light(4 /* id */, "Light4", 0 /* ordinal */, Light.LIGHT_TYPE_INPUT, 169 Light.LIGHT_CAPABILITY_COLOR_RGB) 170 }; 171 mockLights(mockedLights); 172 173 LightsManager lightsManager = device.getLightsManager(); 174 List<Light> lightList = lightsManager.getLights(); 175 LightState[] states = new LightState[]{new LightState(0xf1), new LightState(0xf2), 176 new LightState(0xf3)}; 177 // Open a session to request turn 3/4 lights on: 178 LightsManager.LightsSession session = lightsManager.openSession(); 179 session.requestLights(new Builder() 180 .addLight(lightsManager.getLights().get(0), states[0]) 181 .addLight(lightsManager.getLights().get(1), states[1]) 182 .addLight(lightsManager.getLights().get(2), states[2]) 183 .build()); 184 IBinder token = session.getToken(); 185 186 verify(mInputManagerRule.getMock()).openLightSession(eq(DEVICE_ID), 187 any(String.class), eq(token)); 188 verify(mInputManagerRule.getMock()).setLightStates(eq(DEVICE_ID), eq(new int[]{1, 2, 3}), 189 eq(states), eq(token)); 190 191 // Then all 3 should turn on. 192 assertThat(lightsManager.getLightState(lightsManager.getLights().get(0)).getColor()) 193 .isEqualTo(0xf1); 194 assertThat(lightsManager.getLightState(lightsManager.getLights().get(1)).getColor()) 195 .isEqualTo(0xf2); 196 assertThat(lightsManager.getLightState(lightsManager.getLights().get(2)).getColor()) 197 .isEqualTo(0xf3); 198 199 // And the 4th should remain off. 200 assertThat(lightsManager.getLightState(lightsManager.getLights().get(3)).getColor()) 201 .isEqualTo(0x00); 202 203 // close session 204 session.close(); 205 verify(mInputManagerRule.getMock()).closeLightSession(eq(DEVICE_ID), eq(token)); 206 } 207 208 @Test testControlPlayerIdLight()209 public void testControlPlayerIdLight() throws Exception { 210 InputDevice device = mInputManager.getInputDevice(DEVICE_ID); 211 assertNotNull(device); 212 213 Light[] mockedLights = { 214 new Light(1 /* id */, "Light1", 0 /* ordinal */, Light.LIGHT_TYPE_PLAYER_ID, 215 0 /* capabilities */), 216 new Light(2 /* id */, "Light2", 0 /* ordinal */, Light.LIGHT_TYPE_INPUT, 217 Light.LIGHT_CAPABILITY_COLOR_RGB | Light.LIGHT_CAPABILITY_BRIGHTNESS), 218 new Light(3 /* id */, "Light3", 0 /* ordinal */, Light.LIGHT_TYPE_INPUT, 219 Light.LIGHT_CAPABILITY_BRIGHTNESS) 220 }; 221 mockLights(mockedLights); 222 223 LightsManager lightsManager = device.getLightsManager(); 224 List<Light> lightList = lightsManager.getLights(); 225 LightState[] states = new LightState[]{new LightState(0xf1, PLAYER_ID)}; 226 // Open a session to request set Player ID light: 227 LightsManager.LightsSession session = lightsManager.openSession(); 228 session.requestLights(new Builder() 229 .addLight(lightsManager.getLights().get(0), states[0]) 230 .build()); 231 IBinder token = session.getToken(); 232 233 verify(mInputManagerRule.getMock()).openLightSession(eq(DEVICE_ID), 234 any(String.class), eq(token)); 235 verify(mInputManagerRule.getMock()).setLightStates(eq(DEVICE_ID), eq(new int[]{1}), 236 eq(states), eq(token)); 237 238 // Verify the light state 239 assertThat(lightsManager.getLightState(lightsManager.getLights().get(0)).getColor()) 240 .isEqualTo(0xf1); 241 assertThat(lightsManager.getLightState(lightsManager.getLights().get(0)).getPlayerId()) 242 .isEqualTo(PLAYER_ID); 243 244 // close session 245 session.close(); 246 verify(mInputManagerRule.getMock()).closeLightSession(eq(DEVICE_ID), eq(token)); 247 } 248 249 @Test testLightCapabilities()250 public void testLightCapabilities() throws Exception { 251 Light light = new Light(1 /* id */, "Light1", 0 /* ordinal */, Light.LIGHT_TYPE_INPUT, 252 Light.LIGHT_CAPABILITY_COLOR_RGB | Light.LIGHT_CAPABILITY_BRIGHTNESS); 253 assertThat(light.getType()).isEqualTo(Light.LIGHT_TYPE_INPUT); 254 assertThat(light.getCapabilities()).isEqualTo(Light.LIGHT_CAPABILITY_COLOR_RGB 255 | Light.LIGHT_CAPABILITY_BRIGHTNESS); 256 assertTrue(light.hasBrightnessControl()); 257 assertTrue(light.hasRgbControl()); 258 } 259 260 @Test testLightsRequest()261 public void testLightsRequest() throws Exception { 262 Light light1 = new Light(1 /* id */, "Light1", 0 /* ordinal */, Light.LIGHT_TYPE_INPUT, 263 0 /* capabilities */); 264 Light light2 = new Light(2 /* id */, "Light2", 0 /* ordinal */, Light.LIGHT_TYPE_PLAYER_ID, 265 0 /* capabilities */); 266 LightState state1 = new LightState(0xf1); 267 LightState state2 = new LightState(0xf2, PLAYER_ID); 268 LightsRequest request = new Builder().addLight(light1, state1) 269 .addLight(light2, state2).build(); 270 271 // Covers the LightsRequest.getLights 272 assertThat(request.getLights().size()).isEqualTo(2); 273 assertThat(request.getLights().get(0)).isEqualTo(1); 274 assertThat(request.getLights().get(1)).isEqualTo(2); 275 276 // Covers the LightsRequest.getLightStates 277 assertThat(request.getLightStates().size()).isEqualTo(2); 278 assertThat(request.getLightStates().get(0)).isEqualTo(state1); 279 assertThat(request.getLightStates().get(1)).isEqualTo(state2); 280 281 // Covers the LightsRequest.getLightsAndStates 282 assertThat(request.getLightsAndStates().size()).isEqualTo(2); 283 assertThat(request.getLightsAndStates().containsKey(light1)).isTrue(); 284 assertThat(request.getLightsAndStates().get(light1)).isEqualTo(state1); 285 assertThat(request.getLightsAndStates().get(light2)).isEqualTo(state2); 286 } 287 288 } 289