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 
17 package com.android.settingslib.users;
18 
19 import android.app.ActivityManager;
20 import android.content.BroadcastReceiver;
21 import android.content.Context;
22 import android.content.Intent;
23 import android.content.IntentFilter;
24 import android.content.pm.UserInfo;
25 import android.graphics.Bitmap;
26 import android.graphics.drawable.BitmapDrawable;
27 import android.graphics.drawable.Drawable;
28 import android.os.SystemProperties;
29 import android.os.UserHandle;
30 import android.os.UserManager;
31 import android.util.Log;
32 
33 import com.android.internal.util.UserIcons;
34 
35 import java.util.Iterator;
36 import java.util.List;
37 
38 /**
39  * Helper class for managing users, providing methods for removing, adding and switching users.
40  *
41  * @deprecated - Do not use
42  */
43 @Deprecated
44 public final class UserManagerHelper {
45     private static final String TAG = "UserManagerHelper";
46     private static final String HEADLESS_SYSTEM_USER = "android.car.systemuser.headless";
47     private final Context mContext;
48     private final UserManager mUserManager;
49     private final ActivityManager mActivityManager;
50     private OnUsersUpdateListener mUpdateListener;
51     private final BroadcastReceiver mUserChangeReceiver = new BroadcastReceiver() {
52         @Override
53         public void onReceive(Context context, Intent intent) {
54             mUpdateListener.onUsersUpdate();
55         }
56     };
57 
UserManagerHelper(Context context)58     public UserManagerHelper(Context context) {
59         mContext = context;
60         mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
61         mActivityManager = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
62     }
63 
64     /**
65      * Registers a listener for updates to all users - removing, adding users or changing user info.
66      *
67      * @param listener Instance of {@link OnUsersUpdateListener}.
68      */
registerOnUsersUpdateListener(OnUsersUpdateListener listener)69     public void registerOnUsersUpdateListener(OnUsersUpdateListener listener) {
70         mUpdateListener = listener;
71         registerReceiver();
72     }
73 
74     /**
75      * Unregisters listener by unregistering {@code BroadcastReceiver}.
76      */
unregisterOnUsersUpdateListener()77     public void unregisterOnUsersUpdateListener() {
78         unregisterReceiver();
79     }
80 
81     /**
82      * Returns {@code true} if the system is in the headless user 0 model.
83      *
84      * @return {@boolean true} if headless system user.
85      */
isHeadlessSystemUser()86     public boolean isHeadlessSystemUser() {
87         return SystemProperties.getBoolean(HEADLESS_SYSTEM_USER, false);
88     }
89 
90     /**
91      * Gets UserInfo for the foreground user.
92      *
93      * Concept of foreground user is relevant for the multi-user deployment. Foreground user
94      * corresponds to the currently "logged in" user.
95      *
96      * @return {@link UserInfo} for the foreground user.
97      */
getForegroundUserInfo()98     public UserInfo getForegroundUserInfo() {
99         return mUserManager.getUserInfo(getForegroundUserId());
100     }
101 
102     /**
103      * @return Id of the foreground user.
104      */
getForegroundUserId()105     public int getForegroundUserId() {
106         return mActivityManager.getCurrentUser();
107     }
108 
109     /**
110      * Gets UserInfo for the user running the caller process.
111      *
112      * Differentiation between foreground user and current process user is relevant for multi-user
113      * deployments.
114      *
115      * Some multi-user aware components (like SystemUI) might run as a singleton - one component
116      * for all users. Current process user is then always the same for that component, even when
117      * the foreground user changes.
118      *
119      * @return {@link UserInfo} for the user running the current process.
120      */
getCurrentProcessUserInfo()121     public UserInfo getCurrentProcessUserInfo() {
122         return mUserManager.getUserInfo(getCurrentProcessUserId());
123     }
124 
125     /**
126      * @return Id for the user running the current process.
127      */
getCurrentProcessUserId()128     public int getCurrentProcessUserId() {
129         return UserHandle.myUserId();
130     }
131 
132     /**
133      * Gets all the other users on the system that are not the user running the current process.
134      *
135      * @return List of {@code UserInfo} for each user that is not the user running the process.
136      */
getAllUsersExcludesCurrentProcessUser()137     public List<UserInfo> getAllUsersExcludesCurrentProcessUser() {
138         return getAllUsersExceptUser(getCurrentProcessUserId());
139     }
140 
141     /**
142      * Gets all the existing users on the system that are not the currently running as the
143      * foreground user.
144      *
145      * @return List of {@code UserInfo} for each user that is not the foreground user.
146      */
getAllUsersExcludesForegroundUser()147     public List<UserInfo> getAllUsersExcludesForegroundUser() {
148         return getAllUsersExceptUser(getForegroundUserId());
149     }
150 
151     /**
152      * Gets all the other users on the system that are not the system user.
153      *
154      * @return List of {@code UserInfo} for each user that is not the system user.
155      */
getAllUsersExcludesSystemUser()156     public List<UserInfo> getAllUsersExcludesSystemUser() {
157         return getAllUsersExceptUser(UserHandle.USER_SYSTEM);
158     }
159 
160     /**
161      * Get all the users except the one with userId passed in.
162      *
163      * @param userId of the user not to be returned.
164      * @return All users other than user with userId.
165      */
getAllUsersExceptUser(int userId)166     public List<UserInfo> getAllUsersExceptUser(int userId) {
167         List<UserInfo> others = mUserManager.getUsers(/* excludeDying= */true);
168 
169         for (Iterator<UserInfo> iterator = others.iterator(); iterator.hasNext(); ) {
170             UserInfo userInfo = iterator.next();
171             if (userInfo.id == userId) {
172                 // Remove user with userId from the list.
173                 iterator.remove();
174             }
175         }
176         return others;
177     }
178 
179     /**
180      * Gets all the users on the system that are not currently being removed.
181      */
getAllUsers()182     public List<UserInfo> getAllUsers() {
183         if (isHeadlessSystemUser()) {
184             return getAllUsersExcludesSystemUser();
185         }
186         return mUserManager.getUsers(/* excludeDying= */true);
187     }
188 
189     // User information accessors
190 
191     /**
192      * Checks whether the user is system user (admin).
193      *
194      * @param userInfo User to check against system user.
195      * @return {@code true} if system user, {@code false} otherwise.
196      */
userIsSystemUser(UserInfo userInfo)197     public boolean userIsSystemUser(UserInfo userInfo) {
198         return userInfo.id == UserHandle.USER_SYSTEM;
199     }
200 
201     /**
202      * Returns whether this user can be removed from the system.
203      *
204      * @param userInfo User to be removed
205      * @return {@code true} if they can be removed, {@code false} otherwise.
206      */
userCanBeRemoved(UserInfo userInfo)207     public boolean userCanBeRemoved(UserInfo userInfo) {
208         return !userIsSystemUser(userInfo);
209     }
210 
211     /**
212      * Checks whether passed in user is the foreground user.
213      *
214      * @param userInfo User to check.
215      * @return {@code true} if foreground user, {@code false} otherwise.
216      */
userIsForegroundUser(UserInfo userInfo)217     public boolean userIsForegroundUser(UserInfo userInfo) {
218         return getForegroundUserId() == userInfo.id;
219     }
220 
221     /**
222      * Checks whether passed in user is the user that's running the current process.
223      *
224      * @param userInfo User to check.
225      * @return {@code true} if user running the process, {@code false} otherwise.
226      */
userIsRunningCurrentProcess(UserInfo userInfo)227     public boolean userIsRunningCurrentProcess(UserInfo userInfo) {
228         return getCurrentProcessUserId() == userInfo.id;
229     }
230 
231     // Foreground user information accessors.
232 
233     /**
234      * Checks if the foreground user is a guest user.
235      */
foregroundUserIsGuestUser()236     public boolean foregroundUserIsGuestUser() {
237       return getForegroundUserInfo().isGuest();
238     }
239 
240     /**
241      * Return whether the foreground user has a restriction.
242      *
243      * @param restriction Restriction to check. Should be a UserManager.* restriction.
244      * @return Whether that restriction exists for the foreground user.
245      */
foregroundUserHasUserRestriction(String restriction)246     public boolean foregroundUserHasUserRestriction(String restriction) {
247         return mUserManager.hasUserRestriction(restriction, getForegroundUserInfo().getUserHandle());
248     }
249 
250     /**
251      * Checks if the foreground user can add new users.
252      */
foregroundUserCanAddUsers()253     public boolean foregroundUserCanAddUsers() {
254         return !foregroundUserHasUserRestriction(UserManager.DISALLOW_ADD_USER);
255     }
256 
257     // Current process user information accessors
258 
259     /**
260      * Checks if the calling app is running in a demo user.
261      */
currentProcessRunningAsDemoUser()262     public boolean currentProcessRunningAsDemoUser() {
263         return mUserManager.isDemoUser();
264     }
265 
266     /**
267      * Checks if the calling app is running as a guest user.
268      */
currentProcessRunningAsGuestUser()269     public boolean currentProcessRunningAsGuestUser() {
270         return mUserManager.isGuestUser();
271     }
272 
273     /**
274      * Checks whether this process is running under the system user.
275      */
currentProcessRunningAsSystemUser()276     public boolean currentProcessRunningAsSystemUser() {
277         return mUserManager.isSystemUser();
278     }
279 
280     // Current process user restriction accessors
281 
282     /**
283      * Return whether the user running the current process has a restriction.
284      *
285      * @param restriction Restriction to check. Should be a UserManager.* restriction.
286      * @return Whether that restriction exists for the user running the process.
287      */
currentProcessHasUserRestriction(String restriction)288     public boolean currentProcessHasUserRestriction(String restriction) {
289         return mUserManager.hasUserRestriction(restriction);
290     }
291 
292     /**
293      * Checks if the user running the current process can add new users.
294      */
currentProcessCanAddUsers()295     public boolean currentProcessCanAddUsers() {
296         return !currentProcessHasUserRestriction(UserManager.DISALLOW_ADD_USER);
297     }
298 
299     /**
300      * Checks if the user running the current process can remove users.
301      */
currentProcessCanRemoveUsers()302     public boolean currentProcessCanRemoveUsers() {
303         return !currentProcessHasUserRestriction(UserManager.DISALLOW_REMOVE_USER);
304     }
305 
306     /**
307      * Checks if the user running the current process is allowed to switch to another user.
308      */
currentProcessCanSwitchUsers()309     public boolean currentProcessCanSwitchUsers() {
310         return !currentProcessHasUserRestriction(UserManager.DISALLOW_USER_SWITCH);
311     }
312 
313     /**
314      * Checks if the current process user can modify accounts. Demo and Guest users cannot modify
315      * accounts even if the DISALLOW_MODIFY_ACCOUNTS restriction is not applied.
316      */
currentProcessCanModifyAccounts()317     public boolean currentProcessCanModifyAccounts() {
318         return !currentProcessHasUserRestriction(UserManager.DISALLOW_MODIFY_ACCOUNTS)
319                 && !currentProcessRunningAsDemoUser()
320                 && !currentProcessRunningAsGuestUser();
321     }
322 
323     // User actions
324 
325     /**
326      * Creates a new user on the system.
327      *
328      * @param userName Name to give to the newly created user.
329      * @return Newly created user.
330      */
createNewUser(String userName)331     public UserInfo createNewUser(String userName) {
332         UserInfo user = mUserManager.createUser(userName, 0 /* flags */);
333         if (user == null) {
334             // Couldn't create user, most likely because there are too many, but we haven't
335             // been able to reload the list yet.
336             Log.w(TAG, "can't create user.");
337             return null;
338         }
339         assignDefaultIcon(user);
340         return user;
341     }
342 
343     /**
344      * Tries to remove the user that's passed in. System user cannot be removed.
345      * If the user to be removed is user currently running the process,
346      * it switches to the system user first, and then removes the user.
347      *
348      * @param userInfo User to be removed
349      * @return {@code true} if user is successfully removed, {@code false} otherwise.
350      */
removeUser(UserInfo userInfo)351     public boolean removeUser(UserInfo userInfo) {
352         if (userIsSystemUser(userInfo)) {
353             Log.w(TAG, "User " + userInfo.id + " is system user, could not be removed.");
354             return false;
355         }
356 
357         if (userInfo.id == getCurrentProcessUserId()) {
358             switchToUserId(UserHandle.USER_SYSTEM);
359         }
360 
361         return mUserManager.removeUser(userInfo.id);
362     }
363 
364     /**
365      * Switches (logs in) to another user.
366      *
367      * @param userInfo User to switch to.
368      */
switchToUser(UserInfo userInfo)369     public void switchToUser(UserInfo userInfo) {
370         if (userInfo.id == getForegroundUserId()) {
371             return;
372         }
373 
374         switchToUserId(userInfo.id);
375     }
376 
377     /**
378      * Creates a new guest session and switches into the guest session.
379      *
380      * @param guestName Username for the guest user.
381      */
startNewGuestSession(String guestName)382     public void startNewGuestSession(String guestName) {
383         UserInfo guest = mUserManager.createGuest(mContext, guestName);
384         if (guest == null) {
385             // Couldn't create user, most likely because there are too many, but we haven't
386             // been able to reload the list yet.
387             Log.w(TAG, "can't create user.");
388             return;
389         }
390         assignDefaultIcon(guest);
391         switchToUserId(guest.id);
392     }
393 
394     /**
395      * Gets an icon for the user.
396      *
397      * @param userInfo User for which we want to get the icon.
398      * @return a Bitmap for the icon
399      */
getUserIcon(UserInfo userInfo)400     public Bitmap getUserIcon(UserInfo userInfo) {
401         Bitmap picture = mUserManager.getUserIcon(userInfo.id);
402 
403         if (picture == null) {
404             return assignDefaultIcon(userInfo);
405         }
406 
407         return picture;
408     }
409 
410     /**
411      * Method for scaling a Bitmap icon to a desirable size.
412      *
413      * @param icon Bitmap to scale.
414      * @param desiredSize Wanted size for the icon.
415      * @return Drawable for the icon, scaled to the new size.
416      */
scaleUserIcon(Bitmap icon, int desiredSize)417     public Drawable scaleUserIcon(Bitmap icon, int desiredSize) {
418         Bitmap scaledIcon = Bitmap.createScaledBitmap(
419                 icon, desiredSize, desiredSize, true /* filter */);
420         return new BitmapDrawable(mContext.getResources(), scaledIcon);
421     }
422 
423     /**
424      * Sets new Username for the user.
425      *
426      * @param user User whose name should be changed.
427      * @param name New username.
428      */
setUserName(UserInfo user, String name)429     public void setUserName(UserInfo user, String name) {
430         mUserManager.setUserName(user.id, name);
431     }
432 
433     /**
434      * Gets a bitmap representing the user's default avatar.
435      *
436      * @param userInfo User whose avatar should be returned.
437      * @return Default user icon
438      */
getUserDefaultIcon(UserInfo userInfo)439     public Bitmap getUserDefaultIcon(UserInfo userInfo) {
440         return UserIcons.convertToBitmap(
441                 UserIcons.getDefaultUserIcon(mContext.getResources(), userInfo.id, false));
442     }
443 
444     /**
445      * Gets a bitmap representing the default icon for a Guest user.
446      *
447      * @return Degault guest icon
448      */
getGuestDefaultIcon()449     public Bitmap getGuestDefaultIcon() {
450         return UserIcons.convertToBitmap(UserIcons.getDefaultUserIcon(
451                 mContext.getResources(), UserHandle.USER_NULL, false));
452     }
453 
registerReceiver()454     private void registerReceiver() {
455         IntentFilter filter = new IntentFilter();
456         filter.addAction(Intent.ACTION_USER_REMOVED);
457         filter.addAction(Intent.ACTION_USER_ADDED);
458         filter.addAction(Intent.ACTION_USER_INFO_CHANGED);
459         filter.addAction(Intent.ACTION_USER_SWITCHED);
460         filter.addAction(Intent.ACTION_USER_STOPPED);
461         filter.addAction(Intent.ACTION_USER_UNLOCKED);
462         mContext.registerReceiverAsUser(mUserChangeReceiver, UserHandle.ALL, filter, null, null);
463     }
464 
465     /**
466      * Assigns a default icon to a user according to the user's id.
467      *
468      * @param userInfo User to assign a default icon to.
469      * @return Bitmap that has been assigned to the user.
470      */
assignDefaultIcon(UserInfo userInfo)471     private Bitmap assignDefaultIcon(UserInfo userInfo) {
472         Bitmap bitmap = userInfo.isGuest() ? getGuestDefaultIcon() : getUserDefaultIcon(userInfo);
473         mUserManager.setUserIcon(userInfo.id, bitmap);
474         return bitmap;
475     }
476 
switchToUserId(int id)477     private void switchToUserId(int id) {
478         try {
479             mActivityManager.switchUser(id);
480         } catch (Exception e) {
481             Log.e(TAG, "Couldn't switch user.", e);
482         }
483     }
484 
unregisterReceiver()485     private void unregisterReceiver() {
486         mContext.unregisterReceiver(mUserChangeReceiver);
487     }
488 
489     /**
490      * Interface for listeners that want to register for receiving updates to changes to the users
491      * on the system including removing and adding users, and changing user info.
492      */
493     public interface OnUsersUpdateListener {
494         /**
495          * Method that will get called when users list has been changed.
496          */
onUsersUpdate()497         void onUsersUpdate();
498     }
499 }
500