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