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