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.InstrumentationRegistry; 47 48 import org.junit.After; 49 import org.junit.Before; 50 import org.junit.Rule; 51 import org.junit.Test; 52 import org.junit.runner.RunWith; 53 import org.mockito.Mock; 54 import org.mockito.junit.MockitoJUnit; 55 import org.mockito.junit.MockitoJUnitRunner; 56 import org.mockito.junit.MockitoRule; 57 58 import java.util.ArrayList; 59 import java.util.Arrays; 60 import java.util.List; 61 62 /** 63 * Tests for {@link InputDeviceLightsManager}. 64 * 65 * Build/Install/Run: 66 * atest FrameworksCoreTests:InputDeviceLightsManagerTest 67 */ 68 @Presubmit 69 @RunWith(MockitoJUnitRunner.class) 70 public class InputDeviceLightsManagerTest { 71 private static final String TAG = "InputDeviceLightsManagerTest"; 72 73 private static final int DEVICE_ID = 1000; 74 private static final int PLAYER_ID = 3; 75 76 @Rule public final MockitoRule mockito = MockitoJUnit.rule(); 77 78 private InputManager mInputManager; 79 80 @Mock private IInputManager mIInputManagerMock; 81 82 @Before setUp()83 public void setUp() throws Exception { 84 final Context context = spy(new ContextWrapper(InstrumentationRegistry.getContext())); 85 when(mIInputManagerMock.getInputDeviceIds()).thenReturn(new int[]{DEVICE_ID}); 86 87 when(mIInputManagerMock.getInputDevice(eq(DEVICE_ID))).thenReturn( 88 createInputDevice(DEVICE_ID)); 89 90 InputManagerGlobal.resetInstance(mIInputManagerMock); 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(mIInputManagerMock).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(mIInputManagerMock).getLightState(eq(DEVICE_ID), anyInt()); 113 } 114 115 @After tearDown()116 public void tearDown() { 117 InputManagerGlobal.clearInstance(); 118 } 119 createInputDevice(int id)120 private InputDevice createInputDevice(int id) { 121 return new InputDevice.Builder() 122 .setId(id) 123 .setName("Test Device " + id) 124 .build(); 125 } 126 mockLights(Light[] lights)127 private void mockLights(Light[] lights) throws Exception { 128 // Mock the Lights returned form InputManagerService 129 when(mIInputManagerMock.getLights(eq(DEVICE_ID))).thenReturn( 130 new ArrayList(Arrays.asList(lights))); 131 } 132 133 @Test testGetInputDeviceLights()134 public void testGetInputDeviceLights() throws Exception { 135 InputDevice device = mInputManager.getInputDevice(DEVICE_ID); 136 assertNotNull(device); 137 138 Light[] mockedLights = { 139 new Light(1 /* id */, "Light1", 0 /* ordinal */, Light.LIGHT_TYPE_INPUT, 140 Light.LIGHT_CAPABILITY_BRIGHTNESS), 141 new Light(2 /* id */, "Light2", 0 /* ordinal */, Light.LIGHT_TYPE_INPUT, 142 Light.LIGHT_CAPABILITY_COLOR_RGB), 143 new Light(3 /* id */, "Light3", 0 /* ordinal */, Light.LIGHT_TYPE_INPUT, 144 0 /* capabilities */) 145 }; 146 mockLights(mockedLights); 147 148 LightsManager lightsManager = device.getLightsManager(); 149 List<Light> lights = lightsManager.getLights(); 150 verify(mIInputManagerMock).getLights(eq(DEVICE_ID)); 151 assertEquals(lights, Arrays.asList(mockedLights)); 152 } 153 154 @Test testControlMultipleLights()155 public void testControlMultipleLights() throws Exception { 156 InputDevice device = mInputManager.getInputDevice(DEVICE_ID); 157 assertNotNull(device); 158 159 Light[] mockedLights = { 160 new Light(1 /* id */, "Light1", 0 /* ordinal */, Light.LIGHT_TYPE_INPUT, 161 Light.LIGHT_CAPABILITY_COLOR_RGB), 162 new Light(2 /* id */, "Light2", 0 /* ordinal */, Light.LIGHT_TYPE_INPUT, 163 Light.LIGHT_CAPABILITY_COLOR_RGB), 164 new Light(3 /* id */, "Light3", 0 /* ordinal */, Light.LIGHT_TYPE_INPUT, 165 Light.LIGHT_CAPABILITY_COLOR_RGB), 166 new Light(4 /* id */, "Light4", 0 /* ordinal */, Light.LIGHT_TYPE_INPUT, 167 Light.LIGHT_CAPABILITY_COLOR_RGB) 168 }; 169 mockLights(mockedLights); 170 171 LightsManager lightsManager = device.getLightsManager(); 172 List<Light> lightList = lightsManager.getLights(); 173 LightState[] states = new LightState[]{new LightState(0xf1), new LightState(0xf2), 174 new LightState(0xf3)}; 175 // Open a session to request turn 3/4 lights on: 176 LightsManager.LightsSession session = lightsManager.openSession(); 177 session.requestLights(new Builder() 178 .addLight(lightsManager.getLights().get(0), states[0]) 179 .addLight(lightsManager.getLights().get(1), states[1]) 180 .addLight(lightsManager.getLights().get(2), states[2]) 181 .build()); 182 IBinder token = session.getToken(); 183 184 verify(mIInputManagerMock).openLightSession(eq(DEVICE_ID), 185 any(String.class), eq(token)); 186 verify(mIInputManagerMock).setLightStates(eq(DEVICE_ID), eq(new int[]{1, 2, 3}), 187 eq(states), eq(token)); 188 189 // Then all 3 should turn on. 190 assertThat(lightsManager.getLightState(lightsManager.getLights().get(0)).getColor()) 191 .isEqualTo(0xf1); 192 assertThat(lightsManager.getLightState(lightsManager.getLights().get(1)).getColor()) 193 .isEqualTo(0xf2); 194 assertThat(lightsManager.getLightState(lightsManager.getLights().get(2)).getColor()) 195 .isEqualTo(0xf3); 196 197 // And the 4th should remain off. 198 assertThat(lightsManager.getLightState(lightsManager.getLights().get(3)).getColor()) 199 .isEqualTo(0x00); 200 201 // close session 202 session.close(); 203 verify(mIInputManagerMock).closeLightSession(eq(DEVICE_ID), eq(token)); 204 } 205 206 @Test testControlPlayerIdLight()207 public void testControlPlayerIdLight() throws Exception { 208 InputDevice device = mInputManager.getInputDevice(DEVICE_ID); 209 assertNotNull(device); 210 211 Light[] mockedLights = { 212 new Light(1 /* id */, "Light1", 0 /* ordinal */, Light.LIGHT_TYPE_PLAYER_ID, 213 0 /* capabilities */), 214 new Light(2 /* id */, "Light2", 0 /* ordinal */, Light.LIGHT_TYPE_INPUT, 215 Light.LIGHT_CAPABILITY_COLOR_RGB | Light.LIGHT_CAPABILITY_BRIGHTNESS), 216 new Light(3 /* id */, "Light3", 0 /* ordinal */, Light.LIGHT_TYPE_INPUT, 217 Light.LIGHT_CAPABILITY_BRIGHTNESS) 218 }; 219 mockLights(mockedLights); 220 221 LightsManager lightsManager = device.getLightsManager(); 222 List<Light> lightList = lightsManager.getLights(); 223 LightState[] states = new LightState[]{new LightState(0xf1, PLAYER_ID)}; 224 // Open a session to request set Player ID light: 225 LightsManager.LightsSession session = lightsManager.openSession(); 226 session.requestLights(new Builder() 227 .addLight(lightsManager.getLights().get(0), states[0]) 228 .build()); 229 IBinder token = session.getToken(); 230 231 verify(mIInputManagerMock).openLightSession(eq(DEVICE_ID), 232 any(String.class), eq(token)); 233 verify(mIInputManagerMock).setLightStates(eq(DEVICE_ID), eq(new int[]{1}), 234 eq(states), eq(token)); 235 236 // Verify the light state 237 assertThat(lightsManager.getLightState(lightsManager.getLights().get(0)).getColor()) 238 .isEqualTo(0xf1); 239 assertThat(lightsManager.getLightState(lightsManager.getLights().get(0)).getPlayerId()) 240 .isEqualTo(PLAYER_ID); 241 242 // close session 243 session.close(); 244 verify(mIInputManagerMock).closeLightSession(eq(DEVICE_ID), eq(token)); 245 } 246 247 @Test testLightCapabilities()248 public void testLightCapabilities() throws Exception { 249 Light light = new Light(1 /* id */, "Light1", 0 /* ordinal */, Light.LIGHT_TYPE_INPUT, 250 Light.LIGHT_CAPABILITY_COLOR_RGB | Light.LIGHT_CAPABILITY_BRIGHTNESS); 251 assertThat(light.getType()).isEqualTo(Light.LIGHT_TYPE_INPUT); 252 assertThat(light.getCapabilities()).isEqualTo(Light.LIGHT_CAPABILITY_COLOR_RGB 253 | Light.LIGHT_CAPABILITY_BRIGHTNESS); 254 assertTrue(light.hasBrightnessControl()); 255 assertTrue(light.hasRgbControl()); 256 } 257 258 @Test testLightsRequest()259 public void testLightsRequest() throws Exception { 260 Light light1 = new Light(1 /* id */, "Light1", 0 /* ordinal */, Light.LIGHT_TYPE_INPUT, 261 0 /* capabilities */); 262 Light light2 = new Light(2 /* id */, "Light2", 0 /* ordinal */, Light.LIGHT_TYPE_PLAYER_ID, 263 0 /* capabilities */); 264 LightState state1 = new LightState(0xf1); 265 LightState state2 = new LightState(0xf2, PLAYER_ID); 266 LightsRequest request = new Builder().addLight(light1, state1) 267 .addLight(light2, state2).build(); 268 269 // Covers the LightsRequest.getLights 270 assertThat(request.getLights().size()).isEqualTo(2); 271 assertThat(request.getLights().get(0)).isEqualTo(1); 272 assertThat(request.getLights().get(1)).isEqualTo(2); 273 274 // Covers the LightsRequest.getLightStates 275 assertThat(request.getLightStates().size()).isEqualTo(2); 276 assertThat(request.getLightStates().get(0)).isEqualTo(state1); 277 assertThat(request.getLightStates().get(1)).isEqualTo(state2); 278 279 // Covers the LightsRequest.getLightsAndStates 280 assertThat(request.getLightsAndStates().size()).isEqualTo(2); 281 assertThat(request.getLightsAndStates().containsKey(light1)).isTrue(); 282 assertThat(request.getLightsAndStates().get(light1)).isEqualTo(state1); 283 assertThat(request.getLightsAndStates().get(light2)).isEqualTo(state2); 284 } 285 286 } 287