1 /* 2 * Copyright (C) 2023 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 com.android.systemui.car.userpicker; 17 18 import static android.car.CarOccupantZoneManager.INVALID_USER_ID; 19 import static android.view.Display.INVALID_DISPLAY; 20 21 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; 22 import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock; 23 import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession; 24 import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; 25 import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify; 26 27 import static org.mockito.ArgumentMatchers.any; 28 import static org.mockito.ArgumentMatchers.anyBoolean; 29 import static org.mockito.ArgumentMatchers.anyInt; 30 import static org.mockito.ArgumentMatchers.anyString; 31 import static org.mockito.ArgumentMatchers.eq; 32 import static org.mockito.Mockito.after; 33 34 import android.app.ActivityManager; 35 import android.car.test.mocks.AndroidMockitoHelper; 36 import android.car.user.UserCreationResult; 37 import android.content.pm.UserInfo; 38 import android.test.suitebuilder.annotation.SmallTest; 39 import android.testing.AndroidTestingRunner; 40 import android.testing.TestableLooper; 41 import android.view.View; 42 43 import com.android.systemui.R; 44 import com.android.systemui.car.CarSystemUiTest; 45 import com.android.systemui.car.userpicker.UserPickerController.Callbacks; 46 import com.android.systemui.settings.DisplayTracker; 47 48 import com.google.android.material.snackbar.Snackbar; 49 50 import org.junit.After; 51 import org.junit.Before; 52 import org.junit.Test; 53 import org.junit.runner.RunWith; 54 import org.mockito.Mock; 55 import org.mockito.MockitoSession; 56 import org.mockito.quality.Strictness; 57 58 import java.util.ArrayList; 59 import java.util.List; 60 61 @CarSystemUiTest 62 @RunWith(AndroidTestingRunner.class) 63 @TestableLooper.RunWithLooper 64 @SmallTest 65 public class UserPickerControllerTest extends UserPickerTestCase { 66 private UserPickerController mUserPickerController; 67 private SnackbarManager mSnackbarManager; 68 private UserPickerSharedState mUserPickerSharedState; 69 70 @Mock 71 private DialogManager mMockDialogManager; 72 @Mock 73 private CarServiceMediator mMockCarServiceMediator; 74 @Mock 75 private UserEventManager mMockUserEventManager; 76 @Mock 77 private DisplayTracker mMockDisplayTracker; 78 @Mock 79 private Callbacks mMockCallbacks; 80 @Mock 81 private UserCreationResult mCreateResult; 82 83 private List<UserInfo> mAliveUsers = new ArrayList<UserInfo>(); 84 private List<UserRecord> mUserRecords = null; 85 private MockitoSession mMockingSession; 86 87 @Before setUp()88 public void setUp() { 89 mMockingSession = mockitoSession() 90 .initMocks(this) 91 .spyStatic(ActivityManager.class) 92 .spyStatic(Snackbar.class) 93 .strictness(Strictness.WARN) 94 .startMocking(); 95 96 mAliveUsers.clear(); 97 doReturn(mAliveUsers).when(mMockUserEventManager).getAliveUsers(); 98 doReturn(mDriverUserInfo).when(mMockUserEventManager).getCurrentForegroundUserInfo(); 99 } 100 101 @After tearDown()102 public void tearDown() { 103 if (mMockingSession != null) { 104 mMockingSession.finishMocking(); 105 } 106 } 107 displaySetup(boolean isLogoutState, int displayId)108 void displaySetup(boolean isLogoutState, int displayId) { 109 mAliveUsers.add(mDriverUserInfo); 110 doReturn(true).when(mMockUserEventManager).isUserRunning(USER_ID_DRIVER); 111 doReturn(MAIN_DISPLAY_ID).when(mMockCarServiceMediator).getDisplayIdForUser(USER_ID_DRIVER); 112 doReturn(USER_ID_DRIVER).when(mMockCarServiceMediator).getUserForDisplay(MAIN_DISPLAY_ID); 113 114 mAliveUsers.add(mFrontUserInfo); 115 if (isLogoutState) { 116 doReturn(INVALID_DISPLAY).when(mMockCarServiceMediator) 117 .getDisplayIdForUser(USER_ID_FRONT); 118 doReturn(INVALID_USER_ID).when(mMockCarServiceMediator) 119 .getUserForDisplay(FRONT_PASSENGER_DISPLAY_ID); 120 } else { 121 doReturn(true).when(mMockUserEventManager).isUserRunning(USER_ID_FRONT); 122 doReturn(FRONT_PASSENGER_DISPLAY_ID).when(mMockCarServiceMediator) 123 .getDisplayIdForUser(USER_ID_FRONT); 124 doReturn(USER_ID_FRONT).when(mMockCarServiceMediator) 125 .getUserForDisplay(FRONT_PASSENGER_DISPLAY_ID); 126 } 127 128 mAliveUsers.add(mRearUserInfo); 129 doReturn(INVALID_DISPLAY).when(mMockCarServiceMediator).getDisplayIdForUser(USER_ID_REAR); 130 doReturn(INVALID_USER_ID).when(mMockCarServiceMediator) 131 .getUserForDisplay(REAR_PASSENGER_DISPLAY_ID); 132 133 doReturn(displayId).when(mContext).getDisplayId(); 134 doReturn(MAIN_DISPLAY_ID).when(mMockDisplayTracker).getDefaultDisplayId(); 135 136 mSnackbarManager = new SnackbarManager(); 137 mUserPickerSharedState = new UserPickerSharedState(); 138 View rootView = mInflater.inflate(R.layout.test_empty_layout, null); 139 mSnackbarManager.setRootView(rootView, R.id.test_empty_layout_frame); 140 141 mUserPickerController = new UserPickerController(mContext, mMockUserEventManager, 142 mMockCarServiceMediator, mMockDialogManager, mSnackbarManager, 143 mMockDisplayTracker, mUserPickerSharedState); 144 mUserPickerController.init(mMockCallbacks, displayId); 145 mUserPickerController.onConfigurationChanged(); 146 AndroidMockitoHelper.mockAmGetCurrentUser(USER_ID_DRIVER); 147 mUserPickerController.updateUsers(); 148 mUserRecords = mUserPickerController.createUserRecords(); 149 } 150 getUserRecord(String name)151 UserRecord getUserRecord(String name) { 152 if (name != null) { 153 for (int i = 0; i < mUserRecords.size(); i++) { 154 if (name.equals(mUserRecords.get(i).mName)) { 155 return mUserRecords.get(i); 156 } 157 } 158 } 159 return null; 160 } 161 162 @Test loginItself_changeUserState_finishUserPicker()163 public void loginItself_changeUserState_finishUserPicker() { 164 displaySetup(/* isLogoutState= */ false, /* displayId= */ FRONT_PASSENGER_DISPLAY_ID); 165 166 mUserPickerController.handleUserSelected(getUserRecord(USER_NAME_FRONT)); 167 168 verify(mMockUserEventManager, after(IDLE_TIMEOUT).never()) 169 .startUserForDisplay(anyInt(), anyInt(), anyInt(), anyBoolean()); 170 verify(mMockCallbacks, after(IDLE_TIMEOUT)).onFinishRequested(); 171 } 172 173 @Test checkSnackbar_loginDriverUser_showSnackbar()174 public void checkSnackbar_loginDriverUser_showSnackbar() { 175 Snackbar snackbar = mock(Snackbar.class); 176 doReturn(snackbar).when(() -> Snackbar.make(any(View.class), any(String.class), anyInt())); 177 displaySetup(/* isLogoutState= */ false, /* displayId= */ FRONT_PASSENGER_DISPLAY_ID); 178 spyOn(mSnackbarManager); 179 180 mUserPickerController.handleUserSelected(getUserRecord(USER_NAME_DRIVER)); 181 182 verify(mMockUserEventManager, after(IDLE_TIMEOUT).never()) 183 .startUserForDisplay(anyInt(), anyInt(), anyInt(), anyBoolean()); 184 verify(mSnackbarManager, after(IDLE_TIMEOUT)).showSnackbar(anyString()); 185 } 186 187 @Test checkSwitchUser_changeUserState_switchUser()188 public void checkSwitchUser_changeUserState_switchUser() { 189 displaySetup(/* isLogoutState= */ false, /* displayId= */ MAIN_DISPLAY_ID); 190 191 mUserPickerController.handleUserSelected((getUserRecord(USER_NAME_REAR))); 192 193 verify(mMockUserEventManager, after(IDLE_TIMEOUT).never()).createNewUser(); 194 verify(mMockUserEventManager, after(IDLE_TIMEOUT)) 195 .startUserForDisplay(anyInt(), eq(USER_ID_REAR), anyInt(), anyBoolean()); 196 } 197 198 @Test checkChangeUser_changeUserState_changeUser()199 public void checkChangeUser_changeUserState_changeUser() { 200 doReturn(true).when(mMockUserEventManager).stopUserUnchecked(anyInt(), anyInt()); 201 displaySetup(/* isLogoutState= */ false, /* displayId= */ FRONT_PASSENGER_DISPLAY_ID); 202 203 mUserPickerController.handleUserSelected(getUserRecord(USER_NAME_REAR)); 204 205 verify(mMockUserEventManager, after(IDLE_TIMEOUT).atLeastOnce()) 206 .stopUserUnchecked(USER_ID_FRONT, FRONT_PASSENGER_DISPLAY_ID); 207 verify(mMockUserEventManager, after(IDLE_TIMEOUT)) 208 .startUserForDisplay(anyInt(), eq(USER_ID_REAR), anyInt(), anyBoolean()); 209 } 210 211 @Test checkLoginUser_logoutState_startUser()212 public void checkLoginUser_logoutState_startUser() { 213 doReturn(true).when(mMockUserEventManager).stopUserUnchecked(anyInt(), anyInt()); 214 displaySetup(/* isLogoutState= */ true, /* displayId= */ FRONT_PASSENGER_DISPLAY_ID); 215 216 mUserPickerController.handleUserSelected(getUserRecord(USER_NAME_REAR)); 217 218 verify(mMockUserEventManager, after(IDLE_TIMEOUT).never()) 219 .stopUserUnchecked(anyInt(), anyInt()); 220 verify(mMockUserEventManager, after(IDLE_TIMEOUT)) 221 .startUserForDisplay(anyInt(), eq(USER_ID_REAR), anyInt(), anyBoolean()); 222 } 223 224 @Test checkCreateGuest_pressGuestIcon_createdGuestUser()225 public void checkCreateGuest_pressGuestIcon_createdGuestUser() { 226 UserInfo guestInfo = new UserInfo(USER_ID_GUEST, "G", UserInfo.FLAG_GUEST); 227 doReturn(true).when(mCreateResult).isSuccess(); 228 doReturn(mCreateResult).when(mMockUserEventManager).createGuest(); 229 doReturn(guestInfo.getUserHandle()).when(mCreateResult).getUser(); 230 doReturn(guestInfo).when(mMockUserEventManager).getUserInfo(USER_ID_GUEST); 231 doReturn(true).when(mMockUserEventManager).stopUserUnchecked(anyInt(), anyInt()); 232 displaySetup(/* isLogoutState= */ false, /* displayId= */ FRONT_PASSENGER_DISPLAY_ID); 233 234 mUserPickerController.handleUserSelected(getUserRecord(mGuestLabel)); 235 236 verify(mMockUserEventManager, after(IDLE_TIMEOUT)).createGuest(); 237 verify(mMockUserEventManager, after(IDLE_TIMEOUT).atLeastOnce()) 238 .stopUserUnchecked(USER_ID_FRONT, FRONT_PASSENGER_DISPLAY_ID); 239 verify(mMockUserEventManager, after(IDLE_TIMEOUT)) 240 .startUserForDisplay(anyInt(), eq(USER_ID_GUEST), anyInt(), anyBoolean()); 241 } 242 243 @Test checkAddNewUser_pressAddUserIcon_createdUser()244 public void checkAddNewUser_pressAddUserIcon_createdUser() { 245 UserInfo newUserInfo = new UserInfo(USER_ID_REAR + 1, "New", UserInfo.FLAG_FULL); 246 doReturn(true).when(mCreateResult).isSuccess(); 247 doReturn(mCreateResult).when(mMockUserEventManager).createNewUser(); 248 doReturn(true).when(mMockUserEventManager).stopUserUnchecked(anyInt(), anyInt()); 249 doReturn(newUserInfo.getUserHandle()).when(mCreateResult).getUser(); 250 doReturn(newUserInfo).when(mMockUserEventManager) 251 .getUserInfo(newUserInfo.getUserHandle().getIdentifier()); 252 displaySetup(/* isLogoutState= */ false, /* displayId= */ FRONT_PASSENGER_DISPLAY_ID); 253 254 mUserPickerController.startAddNewUser(); 255 256 verify(mMockUserEventManager, after(IDLE_TIMEOUT)).createNewUser(); 257 verify(mMockUserEventManager, after(IDLE_TIMEOUT).atLeastOnce()) 258 .stopUserUnchecked(USER_ID_FRONT, FRONT_PASSENGER_DISPLAY_ID); 259 verify(mMockUserEventManager, after(IDLE_TIMEOUT)) 260 .startUserForDisplay(anyInt(), eq(USER_ID_REAR + 1), anyInt(), anyBoolean()); 261 } 262 263 @Test checkDestroyController_callOnDestroy_destroyAll()264 public void checkDestroyController_callOnDestroy_destroyAll() { 265 displaySetup(/* isLogoutState= */ false, /* displayId= */ FRONT_PASSENGER_DISPLAY_ID); 266 spyOn(mUserPickerSharedState); 267 268 mUserPickerController.onDestroy(); 269 270 verify(mUserPickerSharedState).resetUserLoginStarted(eq(FRONT_PASSENGER_DISPLAY_ID)); 271 verify(mMockUserEventManager) 272 .unregisterOnUpdateUsersListener(eq(FRONT_PASSENGER_DISPLAY_ID)); 273 } 274 } 275