1/*
2 * Copyright (C) 2018 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
17package com.android.settingslib.users;
18
19import static com.google.common.truth.Truth.assertThat;
20
21import static org.mockito.Mockito.verify;
22import static org.mockito.Mockito.when;
23
24import android.app.ActivityManager;
25
26import android.content.Context;
27import android.content.pm.UserInfo;
28import android.os.UserHandle;
29import android.os.UserManager;
30
31import com.android.settingslib.testutils.shadow.ShadowActivityManager;
32import com.android.settingslib.SettingsLibRobolectricTestRunner;
33
34import org.junit.After;
35import org.junit.Before;
36import org.junit.Test;
37import org.junit.runner.RunWith;
38import org.mockito.Mock;
39import org.mockito.MockitoAnnotations;
40import org.robolectric.RuntimeEnvironment;
41import org.robolectric.annotation.Config;
42import org.robolectric.annotation.Implementation;
43import org.robolectric.annotation.Implements;
44import org.robolectric.annotation.Resetter;
45
46import java.util.ArrayList;
47import java.util.List;
48
49@RunWith(SettingsLibRobolectricTestRunner.class)
50@Config(shadows = { ShadowActivityManager.class, UserManagerHelperRoboTest.ShadowUserHandle.class})
51public class UserManagerHelperRoboTest {
52    @Mock
53    private Context mContext;
54    @Mock
55    private UserManager mUserManager;
56
57    private UserManagerHelper mHelper;
58
59    @Before
60    public void setUpMocksAndUserManagerHelper() {
61        MockitoAnnotations.initMocks(this);
62        when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
63        when(mContext.getSystemService(Context.ACTIVITY_SERVICE)).thenReturn(
64                RuntimeEnvironment.application.getSystemService(ActivityManager.class));
65        mHelper = new UserManagerHelper(mContext);
66    }
67
68    @After
69    public void tearDown() {
70        ShadowActivityManager.getShadow().reset();
71    }
72
73    @Test
74    public void getForegroundUserId() {
75        ShadowActivityManager.setCurrentUser(15);
76        assertThat(mHelper.getForegroundUserId()).isEqualTo(15);
77    }
78
79    @Test
80    public void getForegroundUserInfo() {
81        ShadowActivityManager.setCurrentUser(17);
82        when(mUserManager.getUserInfo(ShadowActivityManager.getCurrentUser()))
83                .thenReturn(createUserInfoForId(ShadowActivityManager.getCurrentUser()));
84        assertThat(mHelper.getForegroundUserInfo().id).isEqualTo(17);
85    }
86
87    @Test
88    public void getCurrentProcessUserId() {
89        ShadowUserHandle.setUid(11);
90        assertThat(mHelper.getCurrentProcessUserId()).isEqualTo(11);
91    }
92
93    @Test
94    public void getCurrentProcessUserInfo() {
95        ShadowUserHandle.setUid(12);
96        when(mUserManager.getUserInfo(UserHandle.myUserId()))
97                .thenReturn(createUserInfoForId(UserHandle.myUserId()));
98        assertThat(mHelper.getCurrentProcessUserInfo().id).isEqualTo(12);
99    }
100
101    @Test
102    public void getAllUsersExcludesCurrentProcessUser() {
103        ShadowUserHandle.setUid(12);
104        UserInfo currentProcessUser = createUserInfoForId(12);
105
106        UserInfo otherUser1 = createUserInfoForId(13);
107        UserInfo otherUser2 = createUserInfoForId(11);
108        UserInfo otherUser3 = createUserInfoForId(14);
109
110        List<UserInfo> testUsers = new ArrayList<>();
111        testUsers.add(otherUser1);
112        testUsers.add(otherUser2);
113        testUsers.add(currentProcessUser);
114        testUsers.add(otherUser3);
115
116        when(mUserManager.getUsers(true)).thenReturn(testUsers);
117
118        // Should return 3 users that don't have currentProcessUser id.
119        assertThat(mHelper.getAllUsersExcludesCurrentProcessUser()).hasSize(3);
120        assertThat(mHelper.getAllUsersExcludesCurrentProcessUser())
121                .containsExactly(otherUser1, otherUser2, otherUser3);
122    }
123
124    @Test
125    public void getAllUsersExcludesForegroundUser() {
126        ShadowActivityManager.setCurrentUser(17);
127        UserInfo foregroundUser = createUserInfoForId(17);
128
129        UserInfo otherUser1 = createUserInfoForId(11);
130        UserInfo otherUser2 = createUserInfoForId(18);
131        UserInfo otherUser3 = createUserInfoForId(16);
132
133        List<UserInfo> testUsers = new ArrayList<>();
134        testUsers.add(otherUser1);
135        testUsers.add(otherUser2);
136        testUsers.add(foregroundUser);
137        testUsers.add(otherUser3);
138
139        when(mUserManager.getUsers(true)).thenReturn(testUsers);
140
141        // Should return 3 users that don't have foregroundUser id.
142        assertThat(mHelper.getAllUsersExcludesForegroundUser()).hasSize(3);
143        assertThat(mHelper.getAllUsersExcludesForegroundUser())
144                .containsExactly(otherUser1, otherUser2, otherUser3);
145    }
146
147    @Test
148    public void userIsForegroundUser() {
149        ShadowActivityManager.setCurrentUser(10);
150        assertThat(mHelper.userIsForegroundUser(createUserInfoForId(10))).isTrue();
151        assertThat(mHelper.userIsForegroundUser(createUserInfoForId(11))).isFalse();
152
153        ShadowActivityManager.setCurrentUser(11);
154        assertThat(mHelper.userIsForegroundUser(createUserInfoForId(11))).isTrue();
155    }
156
157    @Test
158    public void userIsRunningCurrentProcess() {
159        ShadowUserHandle.setUid(10);
160        assertThat(mHelper.userIsRunningCurrentProcess(createUserInfoForId(10))).isTrue();
161        assertThat(mHelper.userIsRunningCurrentProcess(createUserInfoForId(11))).isFalse();
162
163        ShadowUserHandle.setUid(11);
164        assertThat(mHelper.userIsRunningCurrentProcess(createUserInfoForId(11))).isTrue();
165    }
166
167    @Test
168    public void removingCurrentProcessUserSwitchesToSystemUser() {
169        // Set currentProcess user to be user 10.
170        ShadowUserHandle.setUid(10);
171
172        // Removing a currentProcess user, calls "switch" to system user
173        mHelper.removeUser(createUserInfoForId(10));
174        assertThat(ShadowActivityManager.getShadow().getSwitchUserCalled()).isTrue();
175        assertThat(ShadowActivityManager.getShadow().getUserSwitchedTo()).isEqualTo(0);
176
177        verify(mUserManager).removeUser(10);
178    }
179
180    @Test
181    public void switchToUser() {
182        ShadowActivityManager.setCurrentUser(20);
183
184        // Switching to foreground user doesn't do anything.
185        mHelper.switchToUser(createUserInfoForId(20));
186        assertThat(ShadowActivityManager.getShadow().getSwitchUserCalled()).isFalse();
187
188        // Switching to non-foreground user, simply calls switchUser.
189        UserInfo userToSwitchTo = new UserInfo(22, "Test User", 0);
190        mHelper.switchToUser(userToSwitchTo);
191        assertThat(ShadowActivityManager.getShadow().getSwitchUserCalled()).isTrue();
192        assertThat(ShadowActivityManager.getShadow().getUserSwitchedTo()).isEqualTo(22);
193    }
194
195    private UserInfo createUserInfoForId(int id) {
196        UserInfo userInfo = new UserInfo();
197        userInfo.id = id;
198        return userInfo;
199    }
200
201    @Implements(UserHandle.class)
202    public static class ShadowUserHandle {
203        private static int sUid = 0; // SYSTEM by default
204
205        public static void setUid(int uid) {
206            sUid = uid;
207        }
208
209        @Implementation
210        public static int myUserId() {
211            return sUid;
212        }
213
214        @Resetter
215        public static void reset() {
216            sUid = 0;
217        }
218    }
219}
220