• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 package android.car.hiddenapitest;
17 
18 import static android.car.user.CarUserManager.USER_LIFECYCLE_EVENT_TYPE_STARTING;
19 import static android.car.user.CarUserManager.USER_LIFECYCLE_EVENT_TYPE_STOPPED;
20 import static android.car.user.CarUserManager.USER_LIFECYCLE_EVENT_TYPE_STOPPING;
21 import static android.car.user.CarUserManager.USER_LIFECYCLE_EVENT_TYPE_SWITCHING;
22 import static android.car.user.CarUserManager.USER_LIFECYCLE_EVENT_TYPE_UNLOCKED;
23 import static android.car.user.CarUserManager.USER_LIFECYCLE_EVENT_TYPE_UNLOCKING;
24 
25 import static com.google.common.truth.Truth.assertThat;
26 import static com.google.common.truth.Truth.assertWithMessage;
27 
28 import android.car.testapi.BlockingUserLifecycleListener;
29 import android.car.user.CarUserManager.UserLifecycleEvent;
30 import android.util.Log;
31 
32 import org.junit.AfterClass;
33 import org.junit.BeforeClass;
34 import org.junit.Test;
35 
36 import java.util.List;
37 import java.util.concurrent.Executor;
38 import java.util.concurrent.atomic.AtomicBoolean;
39 
40 // DO NOT ADD ANY TEST TO THIS CLASS
41 // This class will have only one test testLifecycleListener.
42 public final class CarUserManagerLifeCycleTest extends CarMultiUserTestBase {
43 
44     private static final String TAG = CarUserManagerLifeCycleTest.class.getSimpleName();
45 
46     private static final int SWITCH_TIMEOUT_MS = 70_000;
47     // A large stop timeout is required as sometimes stop user broadcast takes a significantly
48     // long time to complete. This happens when there are multiple users starting/stopping in
49     // background which is the case in this test class.
50     private static final int STOP_TIMEOUT_MS = 600_000;
51 
52     /**
53      * Stopping the user takes a while, even when calling force stop - change it to {@code false}
54      * if {@code testLifecycleListener} becomes flaky.
55      */
56     private static final boolean TEST_STOP_EVENTS = true;
57 
58     @BeforeClass
setUp()59     public static void setUp() {
60         setupMaxNumberOfUsers(3); // system user, current user, 1 extra user
61     }
62 
63     @AfterClass
cleanUp()64     public static void cleanUp() {
65         restoreMaxNumberOfUsers();
66     }
67 
68     @Test(timeout = 600_000)
testLifecycleListener()69     public void testLifecycleListener() throws Exception {
70         int initialUserId = getCurrentUserId();
71         int newUserId = createUser().id;
72 
73         BlockingUserLifecycleListener startListener = BlockingUserLifecycleListener
74                 .forSpecificEvents()
75                 .forUser(newUserId)
76                 .setTimeout(SWITCH_TIMEOUT_MS)
77                 .addExpectedEvent(USER_LIFECYCLE_EVENT_TYPE_STARTING)
78                 .addExpectedEvent(USER_LIFECYCLE_EVENT_TYPE_SWITCHING)
79                 .addExpectedEvent(USER_LIFECYCLE_EVENT_TYPE_UNLOCKING)
80                 .addExpectedEvent(USER_LIFECYCLE_EVENT_TYPE_UNLOCKED)
81                 .build();
82 
83         Log.d(TAG, "registering start listener: " + startListener);
84         AtomicBoolean executedRef = new AtomicBoolean();
85 
86         Executor mExecutor = (r) -> {
87             executedRef.set(true);
88             r.run();
89         };
90         mCarUserManager.addListener(mExecutor, startListener);
91 
92         // Switch while listener is registered
93         switchUser(newUserId);
94 
95         List<UserLifecycleEvent> startEvents  = startListener.waitForEvents();
96         Log.d(TAG, "Received start events: " + startEvents);
97 
98         // Make sure listener callback was executed in the proper thread
99         assertWithMessage("executed on executor").that(executedRef.get()).isTrue();
100 
101         // Assert user ids
102         List<UserLifecycleEvent> expectedEvents = startListener.waitForEvents();
103         Log.d(TAG, "Received expected events: " + expectedEvents);
104         for (UserLifecycleEvent event : expectedEvents) {
105             assertWithMessage("userId on event %s", event)
106                 .that(event.getUserId()).isEqualTo(newUserId);
107             assertWithMessage("userHandle on event %s", event)
108                 .that(event.getUserHandle().getIdentifier()).isEqualTo(newUserId);
109             if (event.getEventType() == USER_LIFECYCLE_EVENT_TYPE_SWITCHING) {
110                 assertWithMessage("previousUserId on event %s", event)
111                     .that(event.getPreviousUserId()).isEqualTo(initialUserId);
112                 assertWithMessage("previousUserHandle on event %s", event)
113                     .that(event.getPreviousUserHandle().getIdentifier()).isEqualTo(initialUserId);
114             }
115         }
116 
117         Log.d(TAG, "unregistering start listener: " + startListener);
118         mCarUserManager.removeListener(startListener);
119 
120         BlockingUserLifecycleListener stopListener = BlockingUserLifecycleListener
121                 .forSpecificEvents()
122                 .forUser(newUserId)
123                 .setTimeout(STOP_TIMEOUT_MS)
124                 .addExpectedEvent(USER_LIFECYCLE_EVENT_TYPE_STOPPING)
125                 .addExpectedEvent(USER_LIFECYCLE_EVENT_TYPE_STOPPED)
126                 .build();
127 
128         Log.d(TAG, "registering stop listener: " + stopListener);
129         mCarUserManager.addListener(mExecutor, stopListener);
130 
131         // Switch back to the initial user
132         switchUser(initialUserId);
133 
134         if (TEST_STOP_EVENTS) {
135             // Must force stop the user, otherwise it can take minutes for its process to finish
136             forceStopUser(newUserId);
137 
138             List<UserLifecycleEvent> stopEvents = stopListener.waitForEvents();
139             Log.d(TAG, "stopEvents: " + stopEvents + "; all events on stop listener: "
140                     + stopListener.getAllReceivedEvents());
141 
142             // Assert user ids
143             for (UserLifecycleEvent event : stopEvents) {
144                 assertWithMessage("userId on %s", event)
145                     .that(event.getUserId()).isEqualTo(newUserId);
146                 assertWithMessage("wrong userHandle on %s", event)
147                     .that(event.getUserHandle().getIdentifier()).isEqualTo(newUserId);
148             }
149         } else {
150             Log.w(TAG, "NOT testing user stop events");
151         }
152 
153         // Make sure unregistered listener didn't receive any more events
154         List<UserLifecycleEvent> allStartEvents = startListener.getAllReceivedEvents();
155         Log.d(TAG, "All start events: " + startEvents);
156         assertThat(allStartEvents).containsAtLeastElementsIn(startEvents).inOrder();
157 
158         Log.d(TAG, "unregistering stop listener: " + stopListener);
159         mCarUserManager.removeListener(stopListener);
160     }
161 }
162