| /* |
| * 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 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.BitmapDrawable; |
| import android.graphics.drawable.Drawable; |
| import android.os.SystemProperties; |
| import android.os.UserHandle; |
| import android.os.UserManager; |
| import android.util.Log; |
| |
| import com.android.internal.util.UserIcons; |
| |
| import java.util.Iterator; |
| import java.util.List; |
| |
| /** |
| * Helper class for managing users, providing methods for removing, adding and switching users. |
| * |
| * @deprecated - Do not use |
| */ |
| @Deprecated |
| public final class UserManagerHelper { |
| private static final String TAG = "UserManagerHelper"; |
| private static final String HEADLESS_SYSTEM_USER = "android.car.systemuser.headless"; |
| private final Context mContext; |
| private final UserManager mUserManager; |
| private final ActivityManager mActivityManager; |
| private OnUsersUpdateListener mUpdateListener; |
| private final BroadcastReceiver mUserChangeReceiver = new BroadcastReceiver() { |
| @Override |
| public void onReceive(Context context, Intent intent) { |
| mUpdateListener.onUsersUpdate(); |
| } |
| }; |
| |
| public UserManagerHelper(Context context) { |
| mContext = context; |
| mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE); |
| mActivityManager = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE); |
| } |
| |
| /** |
| * Registers a listener for updates to all users - removing, adding users or changing user info. |
| * |
| * @param listener Instance of {@link OnUsersUpdateListener}. |
| */ |
| public void registerOnUsersUpdateListener(OnUsersUpdateListener listener) { |
| mUpdateListener = listener; |
| registerReceiver(); |
| } |
| |
| /** |
| * Unregisters listener by unregistering {@code BroadcastReceiver}. |
| */ |
| public void unregisterOnUsersUpdateListener() { |
| unregisterReceiver(); |
| } |
| |
| /** |
| * Returns {@code true} if the system is in the headless user 0 model. |
| * |
| * @return {@boolean true} if headless system user. |
| */ |
| public boolean isHeadlessSystemUser() { |
| return SystemProperties.getBoolean(HEADLESS_SYSTEM_USER, false); |
| } |
| |
| /** |
| * Gets UserInfo for the foreground user. |
| * |
| * Concept of foreground user is relevant for the multi-user deployment. Foreground user |
| * corresponds to the currently "logged in" user. |
| * |
| * @return {@link UserInfo} for the foreground user. |
| */ |
| public UserInfo getForegroundUserInfo() { |
| return mUserManager.getUserInfo(getForegroundUserId()); |
| } |
| |
| /** |
| * @return Id of the foreground user. |
| */ |
| public int getForegroundUserId() { |
| return mActivityManager.getCurrentUser(); |
| } |
| |
| /** |
| * Gets UserInfo for the user running the caller process. |
| * |
| * Differentiation between foreground user and current process user is relevant for multi-user |
| * deployments. |
| * |
| * Some multi-user aware components (like SystemUI) might run as a singleton - one component |
| * for all users. Current process user is then always the same for that component, even when |
| * the foreground user changes. |
| * |
| * @return {@link UserInfo} for the user running the current process. |
| */ |
| public UserInfo getCurrentProcessUserInfo() { |
| return mUserManager.getUserInfo(getCurrentProcessUserId()); |
| } |
| |
| /** |
| * @return Id for the user running the current process. |
| */ |
| public int getCurrentProcessUserId() { |
| return UserHandle.myUserId(); |
| } |
| |
| /** |
| * Gets all the other users on the system that are not the user running the current process. |
| * |
| * @return List of {@code UserInfo} for each user that is not the user running the process. |
| */ |
| public List<UserInfo> getAllUsersExcludesCurrentProcessUser() { |
| return getAllUsersExceptUser(getCurrentProcessUserId()); |
| } |
| |
| /** |
| * Gets all the existing users on the system that are not the currently running as the |
| * foreground user. |
| * |
| * @return List of {@code UserInfo} for each user that is not the foreground user. |
| */ |
| public List<UserInfo> getAllUsersExcludesForegroundUser() { |
| return getAllUsersExceptUser(getForegroundUserId()); |
| } |
| |
| /** |
| * Gets all the other users on the system that are not the system user. |
| * |
| * @return List of {@code UserInfo} for each user that is not the system user. |
| */ |
| public List<UserInfo> getAllUsersExcludesSystemUser() { |
| return getAllUsersExceptUser(UserHandle.USER_SYSTEM); |
| } |
| |
| /** |
| * Get all the users except the one with userId passed in. |
| * |
| * @param userId of the user not to be returned. |
| * @return All users other than user with userId. |
| */ |
| public List<UserInfo> getAllUsersExceptUser(int userId) { |
| List<UserInfo> others = mUserManager.getUsers(/* excludeDying= */true); |
| |
| for (Iterator<UserInfo> iterator = others.iterator(); iterator.hasNext(); ) { |
| UserInfo userInfo = iterator.next(); |
| if (userInfo.id == userId) { |
| // Remove user with userId from the list. |
| iterator.remove(); |
| } |
| } |
| return others; |
| } |
| |
| /** |
| * Gets all the users on the system that are not currently being removed. |
| */ |
| public List<UserInfo> getAllUsers() { |
| if (isHeadlessSystemUser()) { |
| return getAllUsersExcludesSystemUser(); |
| } |
| return mUserManager.getUsers(/* excludeDying= */true); |
| } |
| |
| // User information accessors |
| |
| /** |
| * Checks whether the user is system user (admin). |
| * |
| * @param userInfo User to check against system user. |
| * @return {@code true} if system user, {@code false} otherwise. |
| */ |
| public boolean userIsSystemUser(UserInfo userInfo) { |
| return userInfo.id == UserHandle.USER_SYSTEM; |
| } |
| |
| /** |
| * Returns whether this user can be removed from the system. |
| * |
| * @param userInfo User to be removed |
| * @return {@code true} if they can be removed, {@code false} otherwise. |
| */ |
| public boolean userCanBeRemoved(UserInfo userInfo) { |
| return !userIsSystemUser(userInfo); |
| } |
| |
| /** |
| * Checks whether passed in user is the foreground user. |
| * |
| * @param userInfo User to check. |
| * @return {@code true} if foreground user, {@code false} otherwise. |
| */ |
| public boolean userIsForegroundUser(UserInfo userInfo) { |
| return getForegroundUserId() == userInfo.id; |
| } |
| |
| /** |
| * Checks whether passed in user is the user that's running the current process. |
| * |
| * @param userInfo User to check. |
| * @return {@code true} if user running the process, {@code false} otherwise. |
| */ |
| public boolean userIsRunningCurrentProcess(UserInfo userInfo) { |
| return getCurrentProcessUserId() == userInfo.id; |
| } |
| |
| // Foreground user information accessors. |
| |
| /** |
| * Checks if the foreground user is a guest user. |
| */ |
| public boolean foregroundUserIsGuestUser() { |
| return getForegroundUserInfo().isGuest(); |
| } |
| |
| /** |
| * Return whether the foreground user has a restriction. |
| * |
| * @param restriction Restriction to check. Should be a UserManager.* restriction. |
| * @return Whether that restriction exists for the foreground user. |
| */ |
| public boolean foregroundUserHasUserRestriction(String restriction) { |
| return mUserManager.hasUserRestriction(restriction, getForegroundUserInfo().getUserHandle()); |
| } |
| |
| /** |
| * Checks if the foreground user can add new users. |
| */ |
| public boolean foregroundUserCanAddUsers() { |
| return !foregroundUserHasUserRestriction(UserManager.DISALLOW_ADD_USER); |
| } |
| |
| // Current process user information accessors |
| |
| /** |
| * Checks if the calling app is running in a demo user. |
| */ |
| public boolean currentProcessRunningAsDemoUser() { |
| return mUserManager.isDemoUser(); |
| } |
| |
| /** |
| * Checks if the calling app is running as a guest user. |
| */ |
| public boolean currentProcessRunningAsGuestUser() { |
| return mUserManager.isGuestUser(); |
| } |
| |
| /** |
| * Checks whether this process is running under the system user. |
| */ |
| public boolean currentProcessRunningAsSystemUser() { |
| return mUserManager.isSystemUser(); |
| } |
| |
| // Current process user restriction accessors |
| |
| /** |
| * Return whether the user running the current process has a restriction. |
| * |
| * @param restriction Restriction to check. Should be a UserManager.* restriction. |
| * @return Whether that restriction exists for the user running the process. |
| */ |
| public boolean currentProcessHasUserRestriction(String restriction) { |
| return mUserManager.hasUserRestriction(restriction); |
| } |
| |
| /** |
| * Checks if the user running the current process can add new users. |
| */ |
| public boolean currentProcessCanAddUsers() { |
| return !currentProcessHasUserRestriction(UserManager.DISALLOW_ADD_USER); |
| } |
| |
| /** |
| * Checks if the user running the current process can remove users. |
| */ |
| public boolean currentProcessCanRemoveUsers() { |
| return !currentProcessHasUserRestriction(UserManager.DISALLOW_REMOVE_USER); |
| } |
| |
| /** |
| * Checks if the user running the current process is allowed to switch to another user. |
| */ |
| public boolean currentProcessCanSwitchUsers() { |
| return !currentProcessHasUserRestriction(UserManager.DISALLOW_USER_SWITCH); |
| } |
| |
| /** |
| * Checks if the current process user can modify accounts. Demo and Guest users cannot modify |
| * accounts even if the DISALLOW_MODIFY_ACCOUNTS restriction is not applied. |
| */ |
| public boolean currentProcessCanModifyAccounts() { |
| return !currentProcessHasUserRestriction(UserManager.DISALLOW_MODIFY_ACCOUNTS) |
| && !currentProcessRunningAsDemoUser() |
| && !currentProcessRunningAsGuestUser(); |
| } |
| |
| // User actions |
| |
| /** |
| * Creates a new user on the system. |
| * |
| * @param userName Name to give to the newly created user. |
| * @return Newly created user. |
| */ |
| public UserInfo createNewUser(String userName) { |
| UserInfo user = mUserManager.createUser(userName, 0 /* flags */); |
| if (user == null) { |
| // Couldn't create user, most likely because there are too many, but we haven't |
| // been able to reload the list yet. |
| Log.w(TAG, "can't create user."); |
| return null; |
| } |
| assignDefaultIcon(user); |
| return user; |
| } |
| |
| /** |
| * Tries to remove the user that's passed in. System user cannot be removed. |
| * If the user to be removed is user currently running the process, |
| * it switches to the system user first, and then removes the user. |
| * |
| * @param userInfo User to be removed |
| * @return {@code true} if user is successfully removed, {@code false} otherwise. |
| */ |
| public boolean removeUser(UserInfo userInfo) { |
| if (userIsSystemUser(userInfo)) { |
| Log.w(TAG, "User " + userInfo.id + " is system user, could not be removed."); |
| return false; |
| } |
| |
| if (userInfo.id == getCurrentProcessUserId()) { |
| switchToUserId(UserHandle.USER_SYSTEM); |
| } |
| |
| return mUserManager.removeUser(userInfo.id); |
| } |
| |
| /** |
| * Switches (logs in) to another user. |
| * |
| * @param userInfo User to switch to. |
| */ |
| public void switchToUser(UserInfo userInfo) { |
| if (userInfo.id == getForegroundUserId()) { |
| return; |
| } |
| |
| switchToUserId(userInfo.id); |
| } |
| |
| /** |
| * Creates a new guest session and switches into the guest session. |
| * |
| * @param guestName Username for the guest user. |
| */ |
| public void startNewGuestSession(String guestName) { |
| UserInfo guest = mUserManager.createGuest(mContext, guestName); |
| if (guest == null) { |
| // Couldn't create user, most likely because there are too many, but we haven't |
| // been able to reload the list yet. |
| Log.w(TAG, "can't create user."); |
| return; |
| } |
| assignDefaultIcon(guest); |
| switchToUserId(guest.id); |
| } |
| |
| /** |
| * Gets an icon for the user. |
| * |
| * @param userInfo User for which we want to get the icon. |
| * @return a Bitmap for the icon |
| */ |
| public Bitmap getUserIcon(UserInfo userInfo) { |
| Bitmap picture = mUserManager.getUserIcon(userInfo.id); |
| |
| if (picture == null) { |
| return assignDefaultIcon(userInfo); |
| } |
| |
| return picture; |
| } |
| |
| /** |
| * Method for scaling a Bitmap icon to a desirable size. |
| * |
| * @param icon Bitmap to scale. |
| * @param desiredSize Wanted size for the icon. |
| * @return Drawable for the icon, scaled to the new size. |
| */ |
| public Drawable scaleUserIcon(Bitmap icon, int desiredSize) { |
| Bitmap scaledIcon = Bitmap.createScaledBitmap( |
| icon, desiredSize, desiredSize, true /* filter */); |
| return new BitmapDrawable(mContext.getResources(), scaledIcon); |
| } |
| |
| /** |
| * Sets new Username for the user. |
| * |
| * @param user User whose name should be changed. |
| * @param name New username. |
| */ |
| public void setUserName(UserInfo user, String name) { |
| mUserManager.setUserName(user.id, name); |
| } |
| |
| /** |
| * Gets a bitmap representing the user's default avatar. |
| * |
| * @param userInfo User whose avatar should be returned. |
| * @return Default user icon |
| */ |
| public Bitmap getUserDefaultIcon(UserInfo userInfo) { |
| return UserIcons.convertToBitmap( |
| UserIcons.getDefaultUserIcon(mContext.getResources(), userInfo.id, false)); |
| } |
| |
| /** |
| * Gets a bitmap representing the default icon for a Guest user. |
| * |
| * @return Degault guest icon |
| */ |
| public Bitmap getGuestDefaultIcon() { |
| return UserIcons.convertToBitmap(UserIcons.getDefaultUserIcon( |
| mContext.getResources(), UserHandle.USER_NULL, false)); |
| } |
| |
| private void registerReceiver() { |
| IntentFilter filter = new IntentFilter(); |
| filter.addAction(Intent.ACTION_USER_REMOVED); |
| filter.addAction(Intent.ACTION_USER_ADDED); |
| filter.addAction(Intent.ACTION_USER_INFO_CHANGED); |
| filter.addAction(Intent.ACTION_USER_SWITCHED); |
| filter.addAction(Intent.ACTION_USER_STOPPED); |
| filter.addAction(Intent.ACTION_USER_UNLOCKED); |
| mContext.registerReceiverAsUser(mUserChangeReceiver, UserHandle.ALL, filter, null, null); |
| } |
| |
| /** |
| * Assigns a default icon to a user according to the user's id. |
| * |
| * @param userInfo User to assign a default icon to. |
| * @return Bitmap that has been assigned to the user. |
| */ |
| private Bitmap assignDefaultIcon(UserInfo userInfo) { |
| Bitmap bitmap = userInfo.isGuest() ? getGuestDefaultIcon() : getUserDefaultIcon(userInfo); |
| mUserManager.setUserIcon(userInfo.id, bitmap); |
| return bitmap; |
| } |
| |
| private void switchToUserId(int id) { |
| try { |
| mActivityManager.switchUser(id); |
| } catch (Exception e) { |
| Log.e(TAG, "Couldn't switch user.", e); |
| } |
| } |
| |
| private void unregisterReceiver() { |
| mContext.unregisterReceiver(mUserChangeReceiver); |
| } |
| |
| /** |
| * Interface for listeners that want to register for receiving updates to changes to the users |
| * on the system including removing and adding users, and changing user info. |
| */ |
| public interface OnUsersUpdateListener { |
| /** |
| * Method that will get called when users list has been changed. |
| */ |
| void onUsersUpdate(); |
| } |
| } |