/* * 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 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 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 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 getAllUsersExceptUser(int userId) { List others = mUserManager.getUsers(/* excludeDying= */true); for (Iterator 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 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(); } }