blob: 44cc0d6ae5b9140685de4095feecfa445ce3588f [file] [log] [blame]
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.car;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.app.ActivityManager;
import android.car.user.CarUserManagerHelper;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.UserInfo;
import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.os.SystemProperties;
import android.os.UserHandle;
import android.os.UserManager;
import android.support.test.InstrumentationRegistry;
import android.support.test.runner.AndroidJUnit4;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import java.util.ArrayList;
import java.util.List;
/**
* This class contains unit tests for the {@link CarUserManagerHelper}.
* It tests that {@link CarUserManagerHelper} does the right thing for user management flows.
*
* The following mocks are used:
* 1. {@link Context} provides system services and resources.
* 2. {@link UserManager} provides dummy users and user info.
* 3. {@link ActivityManager} provides dummy current process user.
* 4. {@link CarUserManagerHelper.OnUsersUpdateListener} registers a listener for user updates.
*/
@RunWith(AndroidJUnit4.class)
public class CarUserManagerHelperTest {
@Mock
private Context mContext;
@Mock
private UserManager mUserManager;
@Mock
private ActivityManager mActivityManager;
@Mock
private CarUserManagerHelper.OnUsersUpdateListener mTestListener;
private CarUserManagerHelper mHelper;
private UserInfo mCurrentProcessUser;
private UserInfo mSystemUser;
private String mGuestUserName = "testGuest";
private String mTestUserName = "testUser";
@Before
public void setUpMocksAndVariables() throws Exception {
MockitoAnnotations.initMocks(this);
when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
when(mContext.getSystemService(Context.ACTIVITY_SERVICE)).thenReturn(mActivityManager);
when(mContext.getResources())
.thenReturn(InstrumentationRegistry.getTargetContext().getResources());
when(mContext.getApplicationContext()).thenReturn(mContext);
mHelper = new CarUserManagerHelper(mContext);
mCurrentProcessUser = createUserInfoForId(UserHandle.myUserId());
mSystemUser = createUserInfoForId(UserHandle.USER_SYSTEM);
when(mUserManager.getUserInfo(UserHandle.myUserId())).thenReturn(mCurrentProcessUser);
}
@Test
public void checkIsSystemUser() {
UserInfo testInfo = new UserInfo();
testInfo.id = UserHandle.USER_SYSTEM;
assertThat(mHelper.isSystemUser(testInfo)).isTrue();
testInfo.id = UserHandle.USER_SYSTEM + 2; // Make it different than system id.
assertThat(mHelper.isSystemUser(testInfo)).isFalse();
}
// System user will not be returned when calling get all users.
@Test
public void testHeadlessUser0GetAllUsers_NotReturnSystemUser() {
SystemProperties.set("android.car.systemuser.headless", "true");
UserInfo otherUser1 = createUserInfoForId(10);
UserInfo otherUser2 = createUserInfoForId(11);
UserInfo otherUser3 = createUserInfoForId(12);
List<UserInfo> testUsers = new ArrayList<>();
testUsers.add(mSystemUser);
testUsers.add(otherUser1);
testUsers.add(otherUser2);
testUsers.add(otherUser3);
when(mUserManager.getUsers(true)).thenReturn(testUsers);
// Should return 3 users that don't have SYSTEM USER id.
assertThat(mHelper.getAllUsers()).hasSize(3);
assertThat(mHelper.getAllUsers())
.containsExactly(otherUser1, otherUser2, otherUser3);
}
@Test
public void testHeadlessUser0GetAllUsersWithActiveForegroundUser_NotReturnSystemUser() {
SystemProperties.set("android.car.systemuser.headless", "true");
mCurrentProcessUser = createUserInfoForId(10);
UserInfo otherUser1 = createUserInfoForId(11);
UserInfo otherUser2 = createUserInfoForId(12);
UserInfo otherUser3 = createUserInfoForId(13);
List<UserInfo> testUsers = new ArrayList<>();
testUsers.add(mSystemUser);
testUsers.add(mCurrentProcessUser);
testUsers.add(otherUser1);
testUsers.add(otherUser2);
testUsers.add(otherUser3);
when(mUserManager.getUsers(true)).thenReturn(testUsers);
assertThat(mHelper.getAllUsers().size()).isEqualTo(4);
assertThat(mHelper.getAllUsers())
.containsExactly(mCurrentProcessUser, otherUser1, otherUser2, otherUser3);
}
@Test
public void testGetAllSwitchableUsers() {
UserInfo user1 = createUserInfoForId(10);
UserInfo user2 = createUserInfoForId(11);
UserInfo user3 = createUserInfoForId(12);
List<UserInfo> testUsers = new ArrayList<>();
testUsers.add(mSystemUser);
testUsers.add(user1);
testUsers.add(user2);
testUsers.add(user3);
when(mUserManager.getUsers(true)).thenReturn(new ArrayList<>(testUsers));
// Should return all 3 non-system users.
assertThat(mHelper.getAllUsers().size())
.isEqualTo(3);
when(mUserManager.getUserInfo(UserHandle.myUserId())).thenReturn(user1);
// Should return user 10, 11 and 12.
assertThat(mHelper.getAllSwitchableUsers().size())
.isEqualTo(3);
assertThat(mHelper.getAllSwitchableUsers()).contains(user1);
assertThat(mHelper.getAllSwitchableUsers()).contains(user2);
assertThat(mHelper.getAllSwitchableUsers()).contains(user3);
}
// Get all users for headless user 0 model should exclude system user by default.
@Test
public void testHeadlessUser0GetAllSwitchableUsers() {
SystemProperties.set("android.car.systemuser.headless", "true");
UserInfo user1 = createUserInfoForId(10);
UserInfo user2 = createUserInfoForId(11);
UserInfo user3 = createUserInfoForId(12);
List<UserInfo> testUsers = new ArrayList<>();
testUsers.add(mSystemUser);
testUsers.add(user1);
testUsers.add(user2);
testUsers.add(user3);
when(mUserManager.getUsers(true)).thenReturn(new ArrayList<>(testUsers));
// Should return all 3 non-system users.
assertThat(mHelper.getAllUsers()).hasSize(3);
when(mUserManager.getUserInfo(UserHandle.myUserId())).thenReturn(user1);
// Should return user 10, 11 and 12.
assertThat(mHelper.getAllSwitchableUsers()).containsExactly(user1, user2, user3);
}
@Test
public void testUserCanBeRemoved() {
UserInfo testInfo = new UserInfo();
// System user cannot be removed.
testInfo.id = UserHandle.USER_SYSTEM;
assertThat(mHelper.canUserBeRemoved(testInfo)).isFalse();
testInfo.id = UserHandle.USER_SYSTEM + 2; // Make it different than system id.
assertThat(mHelper.canUserBeRemoved(testInfo)).isTrue();
}
@Test
public void testCurrentProcessCanAddUsers() {
when(mUserManager.hasUserRestriction(UserManager.DISALLOW_ADD_USER)).thenReturn(false);
assertThat(mHelper.canCurrentProcessAddUsers()).isTrue();
when(mUserManager.hasUserRestriction(UserManager.DISALLOW_ADD_USER)).thenReturn(true);
assertThat(mHelper.canCurrentProcessAddUsers()).isFalse();
}
@Test
public void testCurrentProcessCanRemoveUsers() {
when(mUserManager.hasUserRestriction(UserManager.DISALLOW_REMOVE_USER)).thenReturn(false);
assertThat(mHelper.canCurrentProcessRemoveUsers()).isTrue();
when(mUserManager.hasUserRestriction(UserManager.DISALLOW_REMOVE_USER)).thenReturn(true);
assertThat(mHelper.canCurrentProcessRemoveUsers()).isFalse();
}
@Test
public void testCurrentProcessCanSwitchUsers() {
when(mUserManager.hasUserRestriction(UserManager.DISALLOW_USER_SWITCH)).thenReturn(false);
assertThat(mHelper.canCurrentProcessSwitchUsers()).isTrue();
when(mUserManager.hasUserRestriction(UserManager.DISALLOW_USER_SWITCH)).thenReturn(true);
assertThat(mHelper.canCurrentProcessSwitchUsers()).isFalse();
}
@Test
public void testCurrentGuestProcessCannotModifyAccounts() {
assertThat(mHelper.canCurrentProcessModifyAccounts()).isTrue();
when(mUserManager.isGuestUser()).thenReturn(true);
assertThat(mHelper.canCurrentProcessModifyAccounts()).isFalse();
}
@Test
public void testCurrentDemoProcessCannotModifyAccounts() {
assertThat(mHelper.canCurrentProcessModifyAccounts()).isTrue();
when(mUserManager.isDemoUser()).thenReturn(true);
assertThat(mHelper.canCurrentProcessModifyAccounts()).isFalse();
}
@Test
public void testCurrentDisallowModifyAccountsProcessIsEnforced() {
assertThat(mHelper.canCurrentProcessModifyAccounts()).isTrue();
when(mUserManager.hasUserRestriction(UserManager.DISALLOW_MODIFY_ACCOUNTS))
.thenReturn(true);
assertThat(mHelper.canCurrentProcessModifyAccounts()).isFalse();
}
@Test
public void testCreateNewAdminUser() {
// Verify createUser on UserManager gets called.
mHelper.createNewAdminUser(mTestUserName);
verify(mUserManager).createUser(mTestUserName, UserInfo.FLAG_ADMIN);
when(mUserManager.createUser(mTestUserName, UserInfo.FLAG_ADMIN)).thenReturn(null);
assertThat(mHelper.createNewAdminUser(mTestUserName)).isNull();
UserInfo newUser = new UserInfo();
newUser.name = mTestUserName;
when(mUserManager.createUser(mTestUserName, UserInfo.FLAG_ADMIN)).thenReturn(newUser);
assertThat(mHelper.createNewAdminUser(mTestUserName)).isEqualTo(newUser);
}
@Test
public void testCreateNewNonAdminUser() {
// Verify createUser on UserManager gets called.
mHelper.createNewNonAdminUser(mTestUserName);
verify(mUserManager).createUser(mTestUserName, 0);
when(mUserManager.createUser(mTestUserName, 0)).thenReturn(null);
assertThat(mHelper.createNewNonAdminUser(mTestUserName)).isNull();
UserInfo newUser = new UserInfo();
newUser.name = mTestUserName;
when(mUserManager.createUser(mTestUserName, 0)).thenReturn(newUser);
assertThat(mHelper.createNewNonAdminUser(mTestUserName)).isEqualTo(newUser);
}
@Test
public void testRemoveUser() {
// Cannot remove system user.
assertThat(mHelper.removeUser(mSystemUser, mGuestUserName)).isFalse();
// Removing non-current, non-system user, simply calls removeUser.
UserInfo userToRemove = createUserInfoForId(mCurrentProcessUser.id + 2);
mHelper.removeUser(userToRemove, mGuestUserName);
verify(mUserManager).removeUser(mCurrentProcessUser.id + 2);
}
@Test
public void testSwitchToGuest() {
mHelper.startNewGuestSession(mGuestUserName);
verify(mUserManager).createGuest(mContext, mGuestUserName);
UserInfo guestInfo = new UserInfo(21, mGuestUserName, UserInfo.FLAG_GUEST);
when(mUserManager.createGuest(mContext, mGuestUserName)).thenReturn(guestInfo);
mHelper.startNewGuestSession(mGuestUserName);
verify(mActivityManager).switchUser(21);
}
@Test
public void testGetUserIcon() {
mHelper.getUserIcon(mCurrentProcessUser);
verify(mUserManager).getUserIcon(mCurrentProcessUser.id);
}
@Test
public void testScaleUserIcon() {
Bitmap fakeIcon = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);
Drawable scaledIcon = mHelper.scaleUserIcon(fakeIcon, 300);
assertThat(scaledIcon.getIntrinsicWidth()).isEqualTo(300);
assertThat(scaledIcon.getIntrinsicHeight()).isEqualTo(300);
}
@Test
public void testSetUserName() {
UserInfo testInfo = createUserInfoForId(mCurrentProcessUser.id + 3);
String newName = "New Test Name";
mHelper.setUserName(testInfo, newName);
verify(mUserManager).setUserName(mCurrentProcessUser.id + 3, newName);
}
@Test
public void testRegisterUserChangeReceiver() {
mHelper.registerOnUsersUpdateListener(mTestListener);
ArgumentCaptor<BroadcastReceiver> receiverCaptor =
ArgumentCaptor.forClass(BroadcastReceiver.class);
ArgumentCaptor<UserHandle> handleCaptor = ArgumentCaptor.forClass(UserHandle.class);
ArgumentCaptor<IntentFilter> filterCaptor = ArgumentCaptor.forClass(IntentFilter.class);
ArgumentCaptor<String> permissionCaptor = ArgumentCaptor.forClass(String.class);
ArgumentCaptor<Handler> handlerCaptor = ArgumentCaptor.forClass(Handler.class);
verify(mContext).registerReceiverAsUser(
receiverCaptor.capture(),
handleCaptor.capture(),
filterCaptor.capture(),
permissionCaptor.capture(),
handlerCaptor.capture());
// Verify we're listening to Intents from ALL users.
assertThat(handleCaptor.getValue()).isEqualTo(UserHandle.ALL);
// Verify the presence of each intent in the filter.
// Verify the exact number of filters. Every time a new intent is added, this test should
// get updated.
assertThat(filterCaptor.getValue().countActions()).isEqualTo(6);
assertThat(filterCaptor.getValue().hasAction(Intent.ACTION_USER_REMOVED)).isTrue();
assertThat(filterCaptor.getValue().hasAction(Intent.ACTION_USER_ADDED)).isTrue();
assertThat(filterCaptor.getValue().hasAction(Intent.ACTION_USER_INFO_CHANGED)).isTrue();
assertThat(filterCaptor.getValue().hasAction(Intent.ACTION_USER_SWITCHED)).isTrue();
assertThat(filterCaptor.getValue().hasAction(Intent.ACTION_USER_STOPPED)).isTrue();
assertThat(filterCaptor.getValue().hasAction(Intent.ACTION_USER_UNLOCKED)).isTrue();
// Verify that calling the receiver calls the listener.
receiverCaptor.getValue().onReceive(mContext, new Intent());
verify(mTestListener).onUsersUpdate();
assertThat(permissionCaptor.getValue()).isNull();
assertThat(handlerCaptor.getValue()).isNull();
// Unregister the receiver.
mHelper.unregisterOnUsersUpdateListener();
verify(mContext).unregisterReceiver(receiverCaptor.getValue());
}
private UserInfo createUserInfoForId(int id) {
UserInfo userInfo = new UserInfo();
userInfo.id = id;
return userInfo;
}
}