1 /*
2  * Copyright 2020 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.lights.cts.tests;
18 
19 import static android.hardware.lights.LightsRequest.Builder;
20 
21 import static com.google.common.truth.Truth.assertThat;
22 
23 import static org.junit.Assert.fail;
24 import static org.junit.Assume.assumeTrue;
25 
26 import android.content.Context;
27 import android.hardware.lights.Light;
28 import android.hardware.lights.LightState;
29 import android.hardware.lights.LightsManager;
30 
31 import androidx.test.InstrumentationRegistry;
32 import androidx.test.ext.junit.runners.AndroidJUnit4;
33 import androidx.test.filters.SmallTest;
34 
35 import org.junit.After;
36 import org.junit.Before;
37 import org.junit.Test;
38 import org.junit.runner.RunWith;
39 
40 import java.util.List;
41 
42 @RunWith(AndroidJUnit4.class)
43 @SmallTest
44 public class LightsManagerTest {
45 
46     private static final int ON_TAN = 0xffd2b48c;
47     private static final int ON_RED = 0xffff0000;
48     private static final LightState STATE_TAN = new LightState(ON_TAN);
49     private static final LightState STATE_RED = new LightState(ON_RED);
50     private static final int HIGH_PRIORITY = Integer.MAX_VALUE;
51 
52     private LightsManager mManager;
53     private List<Light> mLights;
54 
55     @Before
setUp()56     public void setUp() {
57         InstrumentationRegistry.getInstrumentation().getUiAutomation()
58                 .adoptShellPermissionIdentity(
59                         android.Manifest.permission.CONTROL_DEVICE_LIGHTS);
60 
61         final Context context = InstrumentationRegistry.getTargetContext();
62         mManager = context.getSystemService(LightsManager.class);
63         mLights = mManager.getLights();
64     }
65 
66     @After
tearDown()67     public void tearDown() {
68         InstrumentationRegistry.getInstrumentation().getUiAutomation()
69                 .dropShellPermissionIdentity();
70     }
71 
72     @Test
testControlLightsPermissionIsRequiredToUseLights()73     public void testControlLightsPermissionIsRequiredToUseLights() {
74         InstrumentationRegistry.getInstrumentation().getUiAutomation()
75                 .dropShellPermissionIdentity();
76         try {
77             mManager.getLights();
78             fail("Expected SecurityException to be thrown for getLights()");
79         } catch (SecurityException expected) {
80         }
81 
82         try (LightsManager.LightsSession session = mManager.openSession()) {
83             fail("Expected SecurityException to be thrown for openSession()");
84         } catch (SecurityException expected) {
85         }
86     }
87 
88     @Test
testControlSingleLight()89     public void testControlSingleLight() {
90         assumeTrue(mLights.size() >= 1);
91 
92         try (LightsManager.LightsSession session = mManager.openSession(HIGH_PRIORITY)) {
93             // When the session requests to turn a single light on:
94             session.requestLights(new Builder()
95                     .addLight(mLights.get(0), STATE_RED)
96                     .build());
97 
98             // Then the light should turn on.
99             assertThat(mManager.getLightState(mLights.get(0)).getColor()).isEqualTo(ON_RED);
100         }
101     }
102 
103     @Test
testControlMultipleLights()104     public void testControlMultipleLights() {
105         assumeTrue(mLights.size() >= 2);
106 
107         int[] initialColors = new int[mLights.size()];
108         for (int i = 0; i < mLights.size(); i++) {
109             initialColors[i] = mManager.getLightState(mLights.get(i)).getColor();
110         }
111 
112         try (LightsManager.LightsSession session = mManager.openSession(HIGH_PRIORITY)) {
113             // When the session requests to turn two of the lights on:
114             session.requestLights(new Builder()
115                     .addLight(mLights.get(0), new LightState(0xffaaaaff))
116                     .addLight(mLights.get(1), new LightState(0xffbbbbff))
117                     .build());
118 
119             // Then both should turn on.
120             assertThat(mManager.getLightState(mLights.get(0)).getColor()).isEqualTo(0xffaaaaff);
121             assertThat(mManager.getLightState(mLights.get(1)).getColor()).isEqualTo(0xffbbbbff);
122 
123             // Any others should remain in their initial state.
124             for (int i = 2; i < mLights.size(); i++) {
125                 assertThat(mManager.getLightState(mLights.get(i)).getColor()).isEqualTo(
126                         initialColors[i]);
127             }
128         }
129     }
130 
131     @Test
testControlLights_onlyEffectiveForLifetimeOfClient()132     public void testControlLights_onlyEffectiveForLifetimeOfClient() {
133         assumeTrue(mLights.size() >= 1);
134 
135         int initialColor = mManager.getLightState(mLights.get(0)).getColor();
136 
137         try (LightsManager.LightsSession session = mManager.openSession(HIGH_PRIORITY)) {
138             // When a session commits changes:
139             session.requestLights(new Builder().addLight(mLights.get(0), STATE_TAN).build());
140             // Then the light should turn on.
141             assertThat(mManager.getLightState(mLights.get(0)).getColor()).isEqualTo(ON_TAN);
142 
143             // When the session goes away:
144             session.close();
145             // Then the light should return to its initial state.
146             assertThat(mManager.getLightState(mLights.get(0)).getColor()).isEqualTo(initialColor);
147         }
148     }
149 
150     @Test
testControlLights_firstCallerWinsContention()151     public void testControlLights_firstCallerWinsContention() {
152         assumeTrue(mLights.size() >= 1);
153 
154         int initialColor = mManager.getLightState(mLights.get(0)).getColor();
155 
156         try (LightsManager.LightsSession session1 = mManager.openSession(HIGH_PRIORITY);
157                 LightsManager.LightsSession session2 = mManager.openSession(HIGH_PRIORITY)) {
158 
159             // When session1 and session2 both request the same light:
160             session1.requestLights(new Builder().addLight(mLights.get(0), STATE_TAN).build());
161             session2.requestLights(new Builder().addLight(mLights.get(0), STATE_RED).build());
162             // Then session1 should win because it was created first.
163             assertThat(mManager.getLightState(mLights.get(0)).getColor()).isEqualTo(ON_TAN);
164 
165             // When session1 goes away:
166             session1.close();
167             // Then session2 should have its request go into effect.
168             assertThat(mManager.getLightState(mLights.get(0)).getColor()).isEqualTo(ON_RED);
169 
170             // When session2 goes away:
171             session2.close();
172             // Then the light should return to its initial state because there are no more sessions.
173             assertThat(mManager.getLightState(mLights.get(0)).getColor()).isEqualTo(initialColor);
174         }
175     }
176 
177     @Test
testClearLight()178     public void testClearLight() {
179         assumeTrue(mLights.size() >= 1);
180 
181         int initialColor = mManager.getLightState(mLights.get(0)).getColor();
182 
183         try (LightsManager.LightsSession session = mManager.openSession(HIGH_PRIORITY)) {
184             // When the session turns a light on:
185             session.requestLights(new Builder().addLight(mLights.get(0), STATE_RED).build());
186             // And then the session clears it again:
187             session.requestLights(new Builder().clearLight(mLights.get(0)).build());
188             // Then the light should return to its initial state.
189             assertThat(mManager.getLightState(mLights.get(0)).getColor()).isEqualTo(initialColor);
190         }
191     }
192 }
193