Adding UserManagerHelper class to SettingsLib.
It's a simple wrapper for adding/removing/switching users.
It provides an interface to register listeners for user changes.
Moving it here to be used in CarSettings and SystemUI for the car.
It's not car-specific, so it could be used by anyone who needs it.
Fixes: 74456332
Bug: 74456744
Test: Unit tests in UserManagerHelperTest.java.
Change-Id: I94b3051ed1e4f96d98e5ab2a7a5a7fa75bc5cade
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/users/UserManagerHelperTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/users/UserManagerHelperTest.java
new file mode 100644
index 0000000..325ef3a
--- /dev/null
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/users/UserManagerHelperTest.java
@@ -0,0 +1,318 @@
+/*
+ * 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.settingslib.users;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.ActivityManager;
+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.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;
+
+@RunWith(AndroidJUnit4.class)
+public class UserManagerHelperTest {
+ @Mock
+ private Context mContext;
+ @Mock
+ private UserManager mUserManager;
+ @Mock
+ private ActivityManager mActivityManager;
+ @Mock
+ private UserManagerHelper.OnUsersUpdateListener mTestListener;
+
+ private UserManagerHelper mHelper;
+ private UserInfo mCurrentUser;
+ private UserInfo mSystemUser;
+
+ @Before
+ public void setUp() 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());
+ mHelper = new UserManagerHelper(mContext);
+
+ mCurrentUser = createUserInfoForId(UserHandle.myUserId());
+ mSystemUser = createUserInfoForId(UserHandle.USER_SYSTEM);
+ when(mUserManager.getUserInfo(UserHandle.myUserId())).thenReturn(mCurrentUser);
+ }
+
+ @Test
+ public void testUserIsSystemUser() {
+ UserInfo testInfo = new UserInfo();
+
+ testInfo.id = UserHandle.USER_SYSTEM;
+ assertThat(mHelper.userIsSystemUser(testInfo)).isTrue();
+
+ testInfo.id = UserHandle.USER_SYSTEM + 2; // Make it different than system id.
+ assertThat(mHelper.userIsSystemUser(testInfo)).isFalse();
+ }
+
+ @Test
+ public void testGetAllUsersExcludesCurrentUser() {
+ int currentUser = UserHandle.myUserId();
+
+ UserInfo otherUser1 = createUserInfoForId(currentUser + 1);
+ UserInfo otherUser2 = createUserInfoForId(currentUser - 1);
+ UserInfo otherUser3 = createUserInfoForId(currentUser + 2);
+
+ List<UserInfo> testUsers = new ArrayList<>();
+ testUsers.add(otherUser1);
+ testUsers.add(otherUser2);
+ testUsers.add(mCurrentUser);
+ testUsers.add(otherUser3);
+
+ when(mUserManager.getUsers(true)).thenReturn(testUsers);
+
+ // Should return 3 users that don't have currentUser id.
+ assertThat(mHelper.getAllUsersExcludesCurrentUser().size()).isEqualTo(3);
+ // Should not contain current user.
+ assertThat(mHelper.getAllUsersExcludesCurrentUser()).doesNotContain(mCurrentUser);
+ // Should contain non-current users.
+ assertThat(mHelper.getAllUsersExcludesCurrentUser()).contains(otherUser1);
+ assertThat(mHelper.getAllUsersExcludesCurrentUser()).contains(otherUser2);
+ assertThat(mHelper.getAllUsersExcludesCurrentUser()).contains(otherUser3);
+ }
+
+ @Test
+ public void testUserCanBeRemoved() {
+ UserInfo testInfo = new UserInfo();
+
+ // System user cannot be removed.
+ testInfo.id = UserHandle.USER_SYSTEM;
+ assertThat(mHelper.userCanBeRemoved(testInfo)).isFalse();
+
+ testInfo.id = UserHandle.USER_SYSTEM + 2; // Make it different than system id.
+ assertThat(mHelper.userCanBeRemoved(testInfo)).isTrue();
+ }
+
+ @Test
+ public void testUserIsCurrentUser() {
+ UserInfo testInfo = new UserInfo();
+
+ // System user cannot be removed.
+ testInfo.id = UserHandle.myUserId();
+ assertThat(mHelper.userIsCurrentUser(testInfo)).isTrue();
+
+ testInfo.id = UserHandle.myUserId() + 2;
+ assertThat(mHelper.userIsCurrentUser(testInfo)).isFalse();
+ }
+
+ @Test
+ public void testCanAddUsers() {
+ when(mUserManager.hasUserRestriction(UserManager.DISALLOW_ADD_USER)).thenReturn(false);
+ assertThat(mHelper.canAddUsers()).isTrue();
+
+ when(mUserManager.hasUserRestriction(UserManager.DISALLOW_ADD_USER)).thenReturn(true);
+ assertThat(mHelper.canAddUsers()).isFalse();
+ }
+
+ @Test
+ public void testCanRemoveUsers() {
+ when(mUserManager.hasUserRestriction(UserManager.DISALLOW_REMOVE_USER)).thenReturn(false);
+ assertThat(mHelper.canRemoveUsers()).isTrue();
+
+ when(mUserManager.hasUserRestriction(UserManager.DISALLOW_REMOVE_USER)).thenReturn(true);
+ assertThat(mHelper.canRemoveUsers()).isFalse();
+ }
+
+ @Test
+ public void testCanSwitchUsers() {
+ when(mUserManager.hasUserRestriction(UserManager.DISALLOW_USER_SWITCH)).thenReturn(false);
+ assertThat(mHelper.canSwitchUsers()).isTrue();
+
+ when(mUserManager.hasUserRestriction(UserManager.DISALLOW_USER_SWITCH)).thenReturn(true);
+ assertThat(mHelper.canSwitchUsers()).isFalse();
+ }
+
+ @Test
+ public void testGuestCannotModifyAccounts() {
+ assertThat(mHelper.canModifyAccounts()).isTrue();
+
+ when(mUserManager.isGuestUser()).thenReturn(true);
+ assertThat(mHelper.canModifyAccounts()).isFalse();
+ }
+
+ @Test
+ public void testDemoUserCannotModifyAccounts() {
+ assertThat(mHelper.canModifyAccounts()).isTrue();
+
+ when(mUserManager.isDemoUser()).thenReturn(true);
+ assertThat(mHelper.canModifyAccounts()).isFalse();
+ }
+
+ @Test
+ public void testUserWithDisallowModifyAccountsRestrictionCannotModifyAccounts() {
+ assertThat(mHelper.canModifyAccounts()).isTrue();
+
+ when(mUserManager.hasUserRestriction(UserManager.DISALLOW_MODIFY_ACCOUNTS))
+ .thenReturn(true);
+ assertThat(mHelper.canModifyAccounts()).isFalse();
+ }
+
+ @Test
+ public void testCreateNewUser() {
+ // Verify createUser on UserManager gets called.
+ mHelper.createNewUser("Test User");
+ verify(mUserManager).createUser("Test User", 0);
+
+ when(mUserManager.createUser("Test User", 0)).thenReturn(null);
+ assertThat(mHelper.createNewUser("Test User")).isNull();
+
+ UserInfo newUser = new UserInfo();
+ newUser.name = "Test User";
+ when(mUserManager.createUser("Test User", 0)).thenReturn(newUser);
+ assertThat(mHelper.createNewUser("Test User")).isEqualTo(newUser);
+ }
+
+ @Test
+ public void testRemoveUser() {
+ // Cannot remove system user.
+ assertThat(mHelper.removeUser(mSystemUser)).isFalse();
+
+ // Removing current user, calls "switch" to system user.
+ mHelper.removeUser(mCurrentUser);
+ verify(mActivityManager).switchUser(UserHandle.USER_SYSTEM);
+ verify(mUserManager).removeUser(mCurrentUser.id);
+
+ // Removing non-current, non-system user, simply calls removeUser.
+ UserInfo userToRemove = createUserInfoForId(mCurrentUser.id + 2);
+ mHelper.removeUser(userToRemove);
+ verify(mUserManager).removeUser(mCurrentUser.id + 2);
+ }
+
+ @Test
+ public void testSwitchToUser() {
+ // Switching to current user doesn't do anything.
+ mHelper.switchToUser(mCurrentUser);
+ verify(mActivityManager, never()).switchUser(mCurrentUser.id);
+
+ // Switching to Guest calls createGuest.
+ UserInfo guestInfo = new UserInfo(mCurrentUser.id + 1, "Test Guest", UserInfo.FLAG_GUEST);
+ mHelper.switchToUser(guestInfo);
+ verify(mUserManager).createGuest(mContext, "Test Guest");
+
+ // Switching to non-current, non-guest user, simply calls switchUser.
+ UserInfo userToSwitchTo = new UserInfo(mCurrentUser.id + 5, "Test User", 0);
+ mHelper.switchToUser(userToSwitchTo);
+ verify(mActivityManager).switchUser(mCurrentUser.id + 5);
+ }
+
+ @Test
+ public void testSwitchToGuest() {
+ mHelper.switchToGuest("Test Guest");
+ verify(mUserManager).createGuest(mContext, "Test Guest");
+
+ UserInfo guestInfo = new UserInfo(mCurrentUser.id + 2, "Test Guest", UserInfo.FLAG_GUEST);
+ when(mUserManager.createGuest(mContext, "Test Guest")).thenReturn(guestInfo);
+ mHelper.switchToGuest("Test Guest");
+ verify(mActivityManager).switchUser(mCurrentUser.id + 2);
+ }
+
+ @Test
+ public void testGetUserIcon() {
+ mHelper.getUserIcon(mCurrentUser);
+ verify(mUserManager).getUserIcon(mCurrentUser.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(mCurrentUser.id + 3);
+ mHelper.setUserName(testInfo, "New Test Name");
+ verify(mUserManager).setUserName(mCurrentUser.id + 3, "New Test Name");
+ }
+
+ @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(3);
+ 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();
+
+ // 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;
+ }
+}