1 /*
2  * Copyright (C) 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 com.android.car.testapi;
18 
19 import static android.car.test.mocks.JavaMockitoHelper.await;
20 import static android.car.user.CarUserManager.USER_LIFECYCLE_EVENT_TYPE_STARTING;
21 import static android.car.user.CarUserManager.USER_LIFECYCLE_EVENT_TYPE_STOPPED;
22 import static android.car.user.CarUserManager.USER_LIFECYCLE_EVENT_TYPE_STOPPING;
23 import static android.car.user.CarUserManager.USER_LIFECYCLE_EVENT_TYPE_SWITCHING;
24 import static android.car.user.CarUserManager.USER_LIFECYCLE_EVENT_TYPE_UNLOCKED;
25 import static android.car.user.CarUserManager.USER_LIFECYCLE_EVENT_TYPE_UNLOCKING;
26 
27 import static com.google.common.truth.Truth.assertThat;
28 import static com.google.common.truth.Truth.assertWithMessage;
29 
30 import static org.junit.Assert.assertThrows;
31 
32 import android.annotation.NonNull;
33 import android.annotation.UserIdInt;
34 import android.car.testapi.BlockingUserLifecycleListener;
35 import android.car.user.CarUserManager;
36 import android.car.user.CarUserManager.UserLifecycleEvent;
37 import android.os.UserHandle;
38 import android.util.Log;
39 
40 import com.android.car.internal.common.CommonConstants.UserLifecycleEventType;
41 
42 import org.junit.Test;
43 
44 import java.util.Arrays;
45 import java.util.List;
46 import java.util.concurrent.CountDownLatch;
47 import java.util.stream.Collectors;
48 
49 public final class BlockingUserLifecycleListenerTest {
50 
51     private static final String TAG = BlockingUserLifecycleListenerTest.class.getSimpleName();
52     private static final long TIMEOUT_MS = 500;
53 
54     @Test
testListener_forAnyEvent_invalidBuilderMethods()55     public void testListener_forAnyEvent_invalidBuilderMethods() throws Exception {
56         BlockingUserLifecycleListener.Builder builder = BlockingUserLifecycleListener.forAnyEvent()
57                 .setTimeout(666);
58 
59         assertThrows(IllegalStateException.class, () -> builder.forUser(10));
60         assertThrows(IllegalStateException.class, () -> builder.forPreviousUser(10));
61         assertThrows(IllegalStateException.class,
62                 () -> builder.addExpectedEvent(USER_LIFECYCLE_EVENT_TYPE_STOPPED));
63     }
64 
65     @Test
testForAnyEvent_invalidMethods()66     public void testForAnyEvent_invalidMethods() throws Exception {
67         BlockingUserLifecycleListener listener =  BlockingUserLifecycleListener.forAnyEvent()
68                 .build();
69 
70         assertThrows(IllegalStateException.class, () -> listener.waitForEvents());
71         assertThrows(IllegalStateException.class, () -> listener.getAllReceivedEvents());
72     }
73 
74     @Test
testForAnyEvent_timesout()75     public void testForAnyEvent_timesout() throws Exception {
76         BlockingUserLifecycleListener listener =  BlockingUserLifecycleListener.forAnyEvent()
77                 .build();
78 
79         assertThrows(IllegalStateException.class, () -> listener.waitForAnyEvent());
80     }
81 
82     @Test
testForAnyEvent_ok()83     public void testForAnyEvent_ok() throws Exception {
84         BlockingUserLifecycleListener listener =  BlockingUserLifecycleListener.forAnyEvent()
85                 .build();
86         sendAsyncEvents(listener, 10, USER_LIFECYCLE_EVENT_TYPE_UNLOCKED);
87 
88         UserLifecycleEvent event = listener.waitForAnyEvent();
89         assertEvent(event, 10, USER_LIFECYCLE_EVENT_TYPE_UNLOCKED);
90     }
91 
92     @Test
testForSpecificEvents_invalidMethods()93     public void testForSpecificEvents_invalidMethods() throws Exception {
94         BlockingUserLifecycleListener listener =  BlockingUserLifecycleListener.forSpecificEvents()
95                 .addExpectedEvent(USER_LIFECYCLE_EVENT_TYPE_STARTING).build();
96 
97         assertThrows(IllegalStateException.class, () -> listener.waitForAnyEvent());
98     }
99 
100     @Test
testForSpecificEvents_receivedOnlyExpected()101     public void testForSpecificEvents_receivedOnlyExpected() throws Exception {
102         BlockingUserLifecycleListener listener =  BlockingUserLifecycleListener.forSpecificEvents()
103                 .addExpectedEvent(USER_LIFECYCLE_EVENT_TYPE_STARTING)
104                 .addExpectedEvent(USER_LIFECYCLE_EVENT_TYPE_UNLOCKED)
105                 .build();
106 
107         sendAsyncEvents(listener, 10,
108                 USER_LIFECYCLE_EVENT_TYPE_STARTING,
109                 USER_LIFECYCLE_EVENT_TYPE_UNLOCKED);
110 
111         List<UserLifecycleEvent> events = listener.waitForEvents();
112         assertEvents(events, 10,
113                 USER_LIFECYCLE_EVENT_TYPE_STARTING,
114                 USER_LIFECYCLE_EVENT_TYPE_UNLOCKED);
115 
116         List<UserLifecycleEvent> allReceivedEvents = listener.getAllReceivedEvents();
117         assertThat(allReceivedEvents).containsAtLeastElementsIn(events).inOrder();
118     }
119 
120     @Test
testForSpecificEvents_receivedExtraEvents()121     public void testForSpecificEvents_receivedExtraEvents() throws Exception {
122         BlockingUserLifecycleListener listener =  BlockingUserLifecycleListener.forSpecificEvents()
123                 .addExpectedEvent(USER_LIFECYCLE_EVENT_TYPE_STARTING)
124                 .addExpectedEvent(USER_LIFECYCLE_EVENT_TYPE_UNLOCKING)
125                 .build();
126 
127         CountDownLatch latch = sendAsyncEvents(listener, 10,
128                 USER_LIFECYCLE_EVENT_TYPE_STARTING,
129                 USER_LIFECYCLE_EVENT_TYPE_SWITCHING,
130                 USER_LIFECYCLE_EVENT_TYPE_UNLOCKING,
131                 USER_LIFECYCLE_EVENT_TYPE_UNLOCKED);
132 
133         List<UserLifecycleEvent> events = listener.waitForEvents();
134         assertEvents(events, 10,
135                 USER_LIFECYCLE_EVENT_TYPE_STARTING,
136                 USER_LIFECYCLE_EVENT_TYPE_UNLOCKING);
137 
138         await(latch, TIMEOUT_MS);
139         List<UserLifecycleEvent> allReceivedEvents = listener.getAllReceivedEvents();
140         assertEvents(allReceivedEvents, 10,
141                 USER_LIFECYCLE_EVENT_TYPE_STARTING,
142                 USER_LIFECYCLE_EVENT_TYPE_SWITCHING,
143                 USER_LIFECYCLE_EVENT_TYPE_UNLOCKING,
144                 USER_LIFECYCLE_EVENT_TYPE_UNLOCKED);
145     }
146 
147     @Test
testForSpecificEvents_filterByUser()148     public void testForSpecificEvents_filterByUser() throws Exception {
149         BlockingUserLifecycleListener listener =  BlockingUserLifecycleListener.forSpecificEvents()
150                 .forUser(10)
151                 .addExpectedEvent(USER_LIFECYCLE_EVENT_TYPE_STARTING)
152                 .addExpectedEvent(USER_LIFECYCLE_EVENT_TYPE_UNLOCKED)
153                 .build();
154         UserLifecycleEvent wrong1 = new UserLifecycleEvent(USER_LIFECYCLE_EVENT_TYPE_STOPPING, 11);
155         UserLifecycleEvent wrong2 = new UserLifecycleEvent(USER_LIFECYCLE_EVENT_TYPE_STOPPED, 11);
156         UserLifecycleEvent right1 = new UserLifecycleEvent(USER_LIFECYCLE_EVENT_TYPE_STARTING, 10);
157         UserLifecycleEvent right2 = new UserLifecycleEvent(USER_LIFECYCLE_EVENT_TYPE_UNLOCKED, 10);
158 
159         CountDownLatch latch = sendAsyncEvents(listener,
160                 Arrays.asList(wrong1, right1, right2, wrong2));
161 
162         List<UserLifecycleEvent> events = listener.waitForEvents();
163         assertThat(events).containsExactly(right1, right2).inOrder();
164 
165         await(latch, TIMEOUT_MS);
166         List<UserLifecycleEvent> allReceivedEvents = listener.getAllReceivedEvents();
167         assertThat(allReceivedEvents)
168                 .containsExactly(wrong1, right1, right2, wrong2)
169                 .inOrder();
170     }
171 
172     @Test
testForSpecificEvents_filterByUserDuplicatedEventTypes()173     public void testForSpecificEvents_filterByUserDuplicatedEventTypes() throws Exception {
174         BlockingUserLifecycleListener listener =  BlockingUserLifecycleListener.forSpecificEvents()
175                 .forUser(10)
176                 .addExpectedEvent(USER_LIFECYCLE_EVENT_TYPE_STARTING)
177                 .addExpectedEvent(USER_LIFECYCLE_EVENT_TYPE_UNLOCKED)
178                 .addExpectedEvent(USER_LIFECYCLE_EVENT_TYPE_STARTING)
179                 .build();
180         UserLifecycleEvent wrong1 = new UserLifecycleEvent(USER_LIFECYCLE_EVENT_TYPE_STOPPING, 11);
181         UserLifecycleEvent wrong2 = new UserLifecycleEvent(USER_LIFECYCLE_EVENT_TYPE_STOPPED, 11);
182         UserLifecycleEvent wrong3 = new UserLifecycleEvent(USER_LIFECYCLE_EVENT_TYPE_STARTING, 11);
183         UserLifecycleEvent right1 = new UserLifecycleEvent(USER_LIFECYCLE_EVENT_TYPE_STARTING, 10);
184         UserLifecycleEvent right2 = new UserLifecycleEvent(USER_LIFECYCLE_EVENT_TYPE_UNLOCKED, 10);
185         UserLifecycleEvent right3 = new UserLifecycleEvent(USER_LIFECYCLE_EVENT_TYPE_STARTING, 10);
186 
187         CountDownLatch latch = sendAsyncEvents(listener,
188                 Arrays.asList(wrong1, right1, wrong2, right2, right3, wrong3));
189 
190         List<UserLifecycleEvent> events = listener.waitForEvents();
191         assertThat(events).containsExactly(right1, right2, right3).inOrder();
192 
193         await(latch, TIMEOUT_MS);
194         List<UserLifecycleEvent> allReceivedEvents = listener.getAllReceivedEvents();
195         assertThat(allReceivedEvents)
196                 .containsExactly(wrong1, right1, wrong2, right2, right3, wrong3)
197                 .inOrder();
198     }
199 
200     @Test
testForSpecificEvents_filterByPreviousUser()201     public void testForSpecificEvents_filterByPreviousUser() throws Exception {
202         BlockingUserLifecycleListener listener = BlockingUserLifecycleListener.forSpecificEvents()
203                 .forPreviousUser(10)
204                 .addExpectedEvent(USER_LIFECYCLE_EVENT_TYPE_SWITCHING)
205                 .addExpectedEvent(USER_LIFECYCLE_EVENT_TYPE_UNLOCKED)
206                 .build();
207         UserLifecycleEvent wrong1 =
208                 new UserLifecycleEvent(USER_LIFECYCLE_EVENT_TYPE_STOPPING, 11);
209         UserLifecycleEvent wrong2 =
210                 new UserLifecycleEvent(USER_LIFECYCLE_EVENT_TYPE_STOPPED, 10);
211         UserLifecycleEvent wrong3 =
212                 new UserLifecycleEvent(USER_LIFECYCLE_EVENT_TYPE_SWITCHING, 11, 10);
213         UserLifecycleEvent right1 =
214                 new UserLifecycleEvent(USER_LIFECYCLE_EVENT_TYPE_SWITCHING, 10, 11);
215         UserLifecycleEvent right2 =
216                 new UserLifecycleEvent(USER_LIFECYCLE_EVENT_TYPE_UNLOCKED, 10, 12);
217 
218         CountDownLatch latch = sendAsyncEvents(listener,
219                 Arrays.asList(wrong1, right1, wrong2, right2, wrong3));
220 
221         List<UserLifecycleEvent> events = listener.waitForEvents();
222         assertThat(events).containsExactly(right1, right2).inOrder();
223 
224         await(latch, TIMEOUT_MS);
225         List<UserLifecycleEvent> allReceivedEvents = listener.getAllReceivedEvents();
226         assertThat(allReceivedEvents)
227                 .containsExactly(wrong1, right1, wrong2, right2, wrong3)
228                 .inOrder();
229     }
230 
231     @Test
testForSpecificEvents_filterByPreviousAndTargetUsers()232     public void testForSpecificEvents_filterByPreviousAndTargetUsers() throws Exception {
233         BlockingUserLifecycleListener listener = BlockingUserLifecycleListener.forSpecificEvents()
234                 .forPreviousUser(10)
235                 .forUser(11)
236                 .addExpectedEvent(USER_LIFECYCLE_EVENT_TYPE_SWITCHING)
237                 .addExpectedEvent(USER_LIFECYCLE_EVENT_TYPE_UNLOCKED)
238                 .build();
239         UserLifecycleEvent wrong1 =
240                 new UserLifecycleEvent(USER_LIFECYCLE_EVENT_TYPE_STOPPING, 11);
241         UserLifecycleEvent wrong2 =
242                 new UserLifecycleEvent(USER_LIFECYCLE_EVENT_TYPE_STOPPED, 10);
243         UserLifecycleEvent wrong3 =
244                 new UserLifecycleEvent(USER_LIFECYCLE_EVENT_TYPE_SWITCHING, 10, 12);
245         UserLifecycleEvent right1 =
246                 new UserLifecycleEvent(USER_LIFECYCLE_EVENT_TYPE_SWITCHING, 10, 11);
247         UserLifecycleEvent right2 =
248                 new UserLifecycleEvent(USER_LIFECYCLE_EVENT_TYPE_UNLOCKED, 10, 11);
249 
250         CountDownLatch latch = sendAsyncEvents(listener,
251                 Arrays.asList(wrong1, right1, wrong2, right2, wrong3));
252 
253         List<UserLifecycleEvent> events = listener.waitForEvents();
254         assertThat(events).containsExactly(right1, right2).inOrder();
255 
256         await(latch, TIMEOUT_MS);
257         List<UserLifecycleEvent> allReceivedEvents = listener.getAllReceivedEvents();
258         assertThat(allReceivedEvents)
259                 .containsExactly(wrong1, right1, wrong2, right2, wrong3)
260                 .inOrder();
261     }
262 
263     @Test
testForNoExpectedEvent_noEventsReceived()264     public void testForNoExpectedEvent_noEventsReceived() throws Exception {
265         BlockingUserLifecycleListener listener =  BlockingUserLifecycleListener.forNoExpectedEvent()
266                 .addExpectedEvent(USER_LIFECYCLE_EVENT_TYPE_STARTING)
267                 .addExpectedEvent(USER_LIFECYCLE_EVENT_TYPE_UNLOCKED)
268                 .build();
269 
270         List<UserLifecycleEvent> events = listener.waitForEvents();
271 
272         sendAsyncEvents(listener, /* userId= */ 10,
273                 USER_LIFECYCLE_EVENT_TYPE_SWITCHING,
274                 USER_LIFECYCLE_EVENT_TYPE_UNLOCKING);
275 
276         assertThat(events).isEmpty();
277     }
278 
279     @NonNull
sendAsyncEvents(@onNull BlockingUserLifecycleListener listener, @UserIdInt int userId, @UserLifecycleEventType int... eventTypes)280     private static CountDownLatch sendAsyncEvents(@NonNull BlockingUserLifecycleListener listener,
281             @UserIdInt int userId, @UserLifecycleEventType int... eventTypes) {
282         List<UserLifecycleEvent> events = Arrays.stream(eventTypes)
283                 .mapToObj((type) -> new UserLifecycleEvent(type, userId))
284                 .collect(Collectors.toList());
285         return sendAsyncEvents(listener, events);
286     }
287 
288     @NonNull
sendAsyncEvents(@onNull BlockingUserLifecycleListener listener, @NonNull List<UserLifecycleEvent> events)289     private static CountDownLatch sendAsyncEvents(@NonNull BlockingUserLifecycleListener listener,
290             @NonNull List<UserLifecycleEvent> events) {
291         Log.d(TAG, "sendAsyncEvents(" + events + "): called on thread " + Thread.currentThread());
292         CountDownLatch latch = new CountDownLatch(1);
293         new Thread(() -> {
294             Log.d(TAG, "sending " + events.size() + " on thread " + Thread.currentThread());
295             events.forEach((e) -> listener.onEvent(e));
296             Log.d(TAG, "sent");
297             latch.countDown();
298         }, "AsyncEventsThread").start();
299         return latch;
300     }
301 
assertEvent(UserLifecycleEvent event, @UserIdInt int expectedUserId, @UserLifecycleEventType int expectedType)302     private static void assertEvent(UserLifecycleEvent event, @UserIdInt int expectedUserId,
303             @UserLifecycleEventType int expectedType) {
304         assertThat(event).isNotNull();
305         assertWithMessage("wrong type on %s; expected %s", event,
306                 CarUserManager.lifecycleEventTypeToString(expectedType)).that(event.getEventType())
307                         .isEqualTo(expectedType);
308         assertThat(event.getUserId()).isEqualTo(expectedUserId);
309         assertThat(event.getUserHandle().getIdentifier()).isEqualTo(expectedUserId);
310         assertThat(event.getPreviousUserId()).isEqualTo(UserHandle.USER_NULL);
311         assertThat(event.getPreviousUserHandle()).isNull();
312     }
313 
assertEvents(List<UserLifecycleEvent> events, @UserIdInt int expectedUserId, @UserLifecycleEventType int... expectedTypes)314     private static void assertEvents(List<UserLifecycleEvent> events, @UserIdInt int expectedUserId,
315             @UserLifecycleEventType int... expectedTypes) {
316         assertThat(events).isNotNull();
317         assertThat(events).hasSize(expectedTypes.length);
318         for (int i = 0; i < expectedTypes.length; i++) {
319             int expectedType = expectedTypes[i];
320             UserLifecycleEvent event = events.get(i);
321             assertEvent(event, expectedUserId, expectedType);
322         }
323     }
324 }
325