Home | History | Annotate | Download | only in users
      1 /*
      2  * Copyright (C) 2012 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.settings.users;
     18 
     19 import android.accounts.Account;
     20 import android.accounts.AccountManager;
     21 import android.app.Activity;
     22 import android.app.ActivityManagerNative;
     23 import android.app.AlertDialog;
     24 import android.app.Dialog;
     25 import android.app.Fragment;
     26 import android.app.admin.DevicePolicyManager;
     27 import android.content.BroadcastReceiver;
     28 import android.content.Context;
     29 import android.content.DialogInterface;
     30 import android.content.Intent;
     31 import android.content.IntentFilter;
     32 import android.content.SharedPreferences;
     33 import android.content.pm.UserInfo;
     34 import android.content.res.Resources;
     35 import android.graphics.Bitmap;
     36 import android.graphics.drawable.Drawable;
     37 import android.os.AsyncTask;
     38 import android.os.Bundle;
     39 import android.os.Handler;
     40 import android.os.Message;
     41 import android.os.RemoteException;
     42 import android.os.UserHandle;
     43 import android.os.UserManager;
     44 import android.preference.Preference;
     45 import android.preference.Preference.OnPreferenceClickListener;
     46 import android.preference.PreferenceGroup;
     47 import android.provider.Settings;
     48 import android.provider.Settings.Secure;
     49 import android.util.Log;
     50 import android.util.SparseArray;
     51 import android.view.Menu;
     52 import android.view.MenuInflater;
     53 import android.view.MenuItem;
     54 import android.view.View;
     55 import android.view.View.OnClickListener;
     56 import android.widget.SimpleAdapter;
     57 
     58 import com.android.internal.util.UserIcons;
     59 import com.android.internal.widget.LockPatternUtils;
     60 import com.android.settings.ChooseLockGeneric;
     61 import com.android.settings.OwnerInfoSettings;
     62 import com.android.settings.R;
     63 import com.android.settings.SelectableEditTextPreference;
     64 import com.android.settings.SettingsActivity;
     65 import com.android.settings.SettingsPreferenceFragment;
     66 import com.android.settings.Utils;
     67 import com.android.settings.drawable.CircleFramedDrawable;
     68 
     69 import java.util.ArrayList;
     70 import java.util.HashMap;
     71 import java.util.List;
     72 
     73 /**
     74  * Screen that manages the list of users on the device.
     75  * Guest user is an always visible entry, even if the guest is not currently
     76  * active/created. It is meant for controlling properties of a guest user.
     77  *
     78  * The first one is always the current user.
     79  * Owner is the primary user.
     80  */
     81 public class UserSettings extends SettingsPreferenceFragment
     82         implements OnPreferenceClickListener, OnClickListener, DialogInterface.OnDismissListener,
     83         Preference.OnPreferenceChangeListener,
     84         EditUserInfoController.OnContentChangedCallback {
     85 
     86     private static final String TAG = "UserSettings";
     87 
     88     /** UserId of the user being removed */
     89     private static final String SAVE_REMOVING_USER = "removing_user";
     90     /** UserId of the user that was just added */
     91     private static final String SAVE_ADDING_USER = "adding_user";
     92 
     93     private static final String KEY_USER_LIST = "user_list";
     94     private static final String KEY_USER_ME = "user_me";
     95     private static final String KEY_ADD_USER = "user_add";
     96 
     97     private static final int MENU_REMOVE_USER = Menu.FIRST;
     98     private static final int MENU_ADD_ON_LOCKSCREEN = Menu.FIRST + 1;
     99 
    100     private static final int DIALOG_CONFIRM_REMOVE = 1;
    101     private static final int DIALOG_ADD_USER = 2;
    102     private static final int DIALOG_SETUP_USER = 3;
    103     private static final int DIALOG_SETUP_PROFILE = 4;
    104     private static final int DIALOG_USER_CANNOT_MANAGE = 5;
    105     private static final int DIALOG_CHOOSE_USER_TYPE = 6;
    106     private static final int DIALOG_NEED_LOCKSCREEN = 7;
    107     private static final int DIALOG_CONFIRM_EXIT_GUEST = 8;
    108     private static final int DIALOG_USER_PROFILE_EDITOR = 9;
    109 
    110     private static final int MESSAGE_UPDATE_LIST = 1;
    111     private static final int MESSAGE_SETUP_USER = 2;
    112     private static final int MESSAGE_CONFIG_USER = 3;
    113 
    114     private static final int USER_TYPE_USER = 1;
    115     private static final int USER_TYPE_RESTRICTED_PROFILE = 2;
    116 
    117     private static final int REQUEST_CHOOSE_LOCK = 10;
    118 
    119     private static final String KEY_ADD_USER_LONG_MESSAGE_DISPLAYED =
    120             "key_add_user_long_message_displayed";
    121 
    122     private static final String KEY_TITLE = "title";
    123     private static final String KEY_SUMMARY = "summary";
    124 
    125     private PreferenceGroup mUserListCategory;
    126     private Preference mMePreference;
    127     private SelectableEditTextPreference mNicknamePreference;
    128     private Preference mAddUser;
    129     private int mRemovingUserId = -1;
    130     private int mAddedUserId = 0;
    131     private boolean mAddingUser;
    132     private boolean mEnabled = true;
    133     private boolean mCanAddRestrictedProfile = true;
    134 
    135     private final Object mUserLock = new Object();
    136     private UserManager mUserManager;
    137     private SparseArray<Bitmap> mUserIcons = new SparseArray<Bitmap>();
    138     private boolean mIsOwner = UserHandle.myUserId() == UserHandle.USER_OWNER;
    139     private boolean mIsGuest;
    140 
    141     private EditUserInfoController mEditUserInfoController =
    142             new EditUserInfoController();
    143 
    144     // A place to cache the generated default avatar
    145     private Drawable mDefaultIconDrawable;
    146 
    147     private Handler mHandler = new Handler() {
    148         @Override
    149         public void handleMessage(Message msg) {
    150             switch (msg.what) {
    151             case MESSAGE_UPDATE_LIST:
    152                 updateUserList();
    153                 break;
    154             case MESSAGE_SETUP_USER:
    155                 onUserCreated(msg.arg1);
    156                 break;
    157             case MESSAGE_CONFIG_USER:
    158                 onManageUserClicked(msg.arg1, true);
    159                 break;
    160             }
    161         }
    162     };
    163 
    164     private BroadcastReceiver mUserChangeReceiver = new BroadcastReceiver() {
    165         @Override
    166         public void onReceive(Context context, Intent intent) {
    167             if (intent.getAction().equals(Intent.ACTION_USER_REMOVED)) {
    168                 mRemovingUserId = -1;
    169             } else if (intent.getAction().equals(Intent.ACTION_USER_INFO_CHANGED)) {
    170                 int userHandle = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
    171                 if (userHandle != -1) {
    172                     mUserIcons.remove(userHandle);
    173                 }
    174             }
    175             mHandler.sendEmptyMessage(MESSAGE_UPDATE_LIST);
    176         }
    177     };
    178 
    179     @Override
    180     public void onCreate(Bundle icicle) {
    181         super.onCreate(icicle);
    182 
    183         if (icicle != null) {
    184             if (icicle.containsKey(SAVE_ADDING_USER)) {
    185                 mAddedUserId = icicle.getInt(SAVE_ADDING_USER);
    186             }
    187             if (icicle.containsKey(SAVE_REMOVING_USER)) {
    188                 mRemovingUserId = icicle.getInt(SAVE_REMOVING_USER);
    189             }
    190             mEditUserInfoController.onRestoreInstanceState(icicle);
    191         }
    192         final Context context = getActivity();
    193         mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
    194         boolean hasMultipleUsers = mUserManager.getUserCount() > 1;
    195         if ((!UserManager.supportsMultipleUsers() && !hasMultipleUsers)
    196                 || Utils.isMonkeyRunning()) {
    197             mEnabled = false;
    198             return;
    199         }
    200 
    201         final int myUserId = UserHandle.myUserId();
    202         mIsGuest = mUserManager.getUserInfo(myUserId).isGuest();
    203 
    204         addPreferencesFromResource(R.xml.user_settings);
    205         mUserListCategory = (PreferenceGroup) findPreference(KEY_USER_LIST);
    206         mMePreference = new UserPreference(context, null /* attrs */, myUserId,
    207                 null /* settings icon handler */,
    208                 null /* delete icon handler */);
    209         mMePreference.setKey(KEY_USER_ME);
    210         mMePreference.setOnPreferenceClickListener(this);
    211         if (mIsOwner) {
    212             mMePreference.setSummary(R.string.user_owner);
    213         }
    214         mAddUser = findPreference(KEY_ADD_USER);
    215         if (!mIsOwner || UserManager.getMaxSupportedUsers() < 2
    216                 || !UserManager.supportsMultipleUsers()
    217                 || mUserManager.hasUserRestriction(UserManager.DISALLOW_ADD_USER)) {
    218             removePreference(KEY_ADD_USER);
    219         } else {
    220             mAddUser.setOnPreferenceClickListener(this);
    221             DevicePolicyManager dpm = (DevicePolicyManager) context.getSystemService(
    222                     Context.DEVICE_POLICY_SERVICE);
    223             // No restricted profiles for tablets with a device owner, or phones.
    224             if (dpm.getDeviceOwner() != null || Utils.isVoiceCapable(context)) {
    225                 mCanAddRestrictedProfile = false;
    226                 mAddUser.setTitle(R.string.user_add_user_menu);
    227             }
    228         }
    229         loadProfile();
    230         setHasOptionsMenu(true);
    231         IntentFilter filter = new IntentFilter(Intent.ACTION_USER_REMOVED);
    232         filter.addAction(Intent.ACTION_USER_INFO_CHANGED);
    233         context.registerReceiverAsUser(mUserChangeReceiver, UserHandle.ALL, filter, null,
    234                 mHandler);
    235     }
    236 
    237     @Override
    238     public void onResume() {
    239         super.onResume();
    240 
    241         if (!mEnabled) return;
    242 
    243         loadProfile();
    244         updateUserList();
    245     }
    246 
    247     @Override
    248     public void onDestroy() {
    249         super.onDestroy();
    250 
    251         if (!mEnabled) return;
    252 
    253         getActivity().unregisterReceiver(mUserChangeReceiver);
    254     }
    255 
    256     @Override
    257     public void onSaveInstanceState(Bundle outState) {
    258         super.onSaveInstanceState(outState);
    259         mEditUserInfoController.onSaveInstanceState(outState);
    260         outState.putInt(SAVE_ADDING_USER, mAddedUserId);
    261         outState.putInt(SAVE_REMOVING_USER, mRemovingUserId);
    262     }
    263 
    264     @Override
    265     public void startActivityForResult(Intent intent, int requestCode) {
    266         mEditUserInfoController.startingActivityForResult();
    267         super.startActivityForResult(intent, requestCode);
    268     }
    269 
    270     @Override
    271     public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    272         int pos = 0;
    273         UserManager um = (UserManager) getActivity().getSystemService(Context.USER_SERVICE);
    274         if (!mIsOwner && !um.hasUserRestriction(UserManager.DISALLOW_REMOVE_USER)) {
    275             String nickname = mUserManager.getUserName();
    276             MenuItem removeThisUser = menu.add(0, MENU_REMOVE_USER, pos++,
    277                     getResources().getString(R.string.user_remove_user_menu, nickname));
    278             removeThisUser.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
    279         }
    280         if (mIsOwner && !um.hasUserRestriction(UserManager.DISALLOW_ADD_USER)) {
    281             MenuItem allowAddOnLockscreen = menu.add(0, MENU_ADD_ON_LOCKSCREEN, pos++,
    282                     R.string.user_add_on_lockscreen_menu);
    283             allowAddOnLockscreen.setCheckable(true);
    284             allowAddOnLockscreen.setChecked(Settings.Global.getInt(getContentResolver(),
    285                     Settings.Global.ADD_USERS_WHEN_LOCKED, 0) == 1);
    286         }
    287         super.onCreateOptionsMenu(menu, inflater);
    288     }
    289 
    290     @Override
    291     public boolean onOptionsItemSelected(MenuItem item) {
    292         final int itemId = item.getItemId();
    293         if (itemId == MENU_REMOVE_USER) {
    294             onRemoveUserClicked(UserHandle.myUserId());
    295             return true;
    296         } else if (itemId == MENU_ADD_ON_LOCKSCREEN) {
    297             final boolean isChecked = item.isChecked();
    298             Settings.Global.putInt(getContentResolver(), Settings.Global.ADD_USERS_WHEN_LOCKED,
    299                     isChecked ? 0 : 1);
    300             item.setChecked(!isChecked);
    301             return true;
    302         } else {
    303             return super.onOptionsItemSelected(item);
    304         }
    305     }
    306 
    307     /**
    308      * Loads profile information for the current user.
    309      */
    310     private void loadProfile() {
    311         if (mIsGuest) {
    312             // No need to load profile information
    313             mMePreference.setIcon(getEncircledDefaultIcon());
    314             mMePreference.setTitle(R.string.user_exit_guest_title);
    315             return;
    316         }
    317 
    318         new AsyncTask<Void, Void, String>() {
    319             @Override
    320             protected void onPostExecute(String result) {
    321                 finishLoadProfile(result);
    322             }
    323 
    324             @Override
    325             protected String doInBackground(Void... values) {
    326                 UserInfo user = mUserManager.getUserInfo(UserHandle.myUserId());
    327                 if (user.iconPath == null || user.iconPath.equals("")) {
    328                     assignProfilePhoto(user);
    329                 }
    330                 return user.name;
    331             }
    332         }.execute();
    333     }
    334 
    335     private void finishLoadProfile(String profileName) {
    336         if (getActivity() == null) return;
    337         mMePreference.setTitle(getString(R.string.user_you, profileName));
    338         int myUserId = UserHandle.myUserId();
    339         Bitmap b = mUserManager.getUserIcon(myUserId);
    340         if (b != null) {
    341             mMePreference.setIcon(encircle(b));
    342             mUserIcons.put(myUserId, b);
    343         }
    344     }
    345 
    346     private boolean hasLockscreenSecurity() {
    347         LockPatternUtils lpu = new LockPatternUtils(getActivity());
    348         return lpu.isLockPasswordEnabled() || lpu.isLockPatternEnabled();
    349     }
    350 
    351     private void launchChooseLockscreen() {
    352         Intent chooseLockIntent = new Intent(DevicePolicyManager.ACTION_SET_NEW_PASSWORD);
    353         chooseLockIntent.putExtra(ChooseLockGeneric.ChooseLockGenericFragment.MINIMUM_QUALITY_KEY,
    354                 DevicePolicyManager.PASSWORD_QUALITY_SOMETHING);
    355         startActivityForResult(chooseLockIntent, REQUEST_CHOOSE_LOCK);
    356     }
    357 
    358     @Override
    359     public void onActivityResult(int requestCode, int resultCode, Intent data) {
    360         super.onActivityResult(requestCode, resultCode, data);
    361 
    362         if (requestCode == REQUEST_CHOOSE_LOCK) {
    363             if (resultCode != Activity.RESULT_CANCELED && hasLockscreenSecurity()) {
    364                 addUserNow(USER_TYPE_RESTRICTED_PROFILE);
    365             }
    366         } else {
    367             mEditUserInfoController.onActivityResult(requestCode, resultCode, data);
    368         }
    369     }
    370 
    371     private void onAddUserClicked(int userType) {
    372         synchronized (mUserLock) {
    373             if (mRemovingUserId == -1 && !mAddingUser) {
    374                 switch (userType) {
    375                 case USER_TYPE_USER:
    376                     showDialog(DIALOG_ADD_USER);
    377                     break;
    378                 case USER_TYPE_RESTRICTED_PROFILE:
    379                     if (hasLockscreenSecurity()) {
    380                         addUserNow(USER_TYPE_RESTRICTED_PROFILE);
    381                     } else {
    382                         showDialog(DIALOG_NEED_LOCKSCREEN);
    383                     }
    384                     break;
    385                 }
    386             }
    387         }
    388     }
    389 
    390     private void onRemoveUserClicked(int userId) {
    391         synchronized (mUserLock) {
    392             if (mRemovingUserId == -1 && !mAddingUser) {
    393                 mRemovingUserId = userId;
    394                 showDialog(DIALOG_CONFIRM_REMOVE);
    395             }
    396         }
    397     }
    398 
    399     private UserInfo createLimitedUser() {
    400         UserInfo newUserInfo = mUserManager.createSecondaryUser(
    401                 getResources().getString(R.string.user_new_profile_name),
    402                 UserInfo.FLAG_RESTRICTED);
    403         int userId = newUserInfo.id;
    404         UserHandle user = new UserHandle(userId);
    405         mUserManager.setUserRestriction(UserManager.DISALLOW_MODIFY_ACCOUNTS, true, user);
    406         // Change the setting before applying the DISALLOW_SHARE_LOCATION restriction, otherwise
    407         // the putIntForUser() will fail.
    408         Secure.putIntForUser(getContentResolver(),
    409                 Secure.LOCATION_MODE, Secure.LOCATION_MODE_OFF, userId);
    410         mUserManager.setUserRestriction(UserManager.DISALLOW_SHARE_LOCATION, true, user);
    411         assignDefaultPhoto(newUserInfo);
    412         // Add shared accounts
    413         AccountManager am = AccountManager.get(getActivity());
    414         Account [] accounts = am.getAccounts();
    415         if (accounts != null) {
    416             for (Account account : accounts) {
    417                 am.addSharedAccount(account, user);
    418             }
    419         }
    420         return newUserInfo;
    421     }
    422 
    423     private UserInfo createTrustedUser() {
    424         UserInfo newUserInfo = mUserManager.createSecondaryUser(
    425                 getResources().getString(R.string.user_new_user_name), 0);
    426         if (newUserInfo != null) {
    427             assignDefaultPhoto(newUserInfo);
    428         }
    429         return newUserInfo;
    430     }
    431 
    432     private void onManageUserClicked(int userId, boolean newUser) {
    433         if (userId == UserPreference.USERID_GUEST_DEFAULTS) {
    434             Bundle extras = new Bundle();
    435             extras.putBoolean(UserDetailsSettings.EXTRA_USER_GUEST, true);
    436             ((SettingsActivity) getActivity()).startPreferencePanel(
    437                     UserDetailsSettings.class.getName(),
    438                     extras, R.string.user_guest, null, null, 0);
    439             return;
    440         }
    441         UserInfo info = mUserManager.getUserInfo(userId);
    442         if (info.isRestricted() && mIsOwner) {
    443             Bundle extras = new Bundle();
    444             extras.putInt(RestrictedProfileSettings.EXTRA_USER_ID, userId);
    445             extras.putBoolean(RestrictedProfileSettings.EXTRA_NEW_USER, newUser);
    446             ((SettingsActivity) getActivity()).startPreferencePanel(
    447                     RestrictedProfileSettings.class.getName(),
    448                     extras, R.string.user_restrictions_title, null,
    449                     null, 0);
    450         } else if (info.id == UserHandle.myUserId()) {
    451             // Jump to owner info panel
    452             Bundle extras = new Bundle();
    453             if (!info.isRestricted()) {
    454                 extras.putBoolean(OwnerInfoSettings.EXTRA_SHOW_NICKNAME, true);
    455             }
    456             int titleResId = info.id == UserHandle.USER_OWNER ? R.string.owner_info_settings_title
    457                     : (info.isRestricted() ? R.string.profile_info_settings_title
    458                             : R.string.user_info_settings_title);
    459             ((SettingsActivity) getActivity()).startPreferencePanel(
    460                     OwnerInfoSettings.class.getName(),
    461                     extras, titleResId, null, null, 0);
    462         } else if (mIsOwner) {
    463             Bundle extras = new Bundle();
    464             extras.putInt(UserDetailsSettings.EXTRA_USER_ID, userId);
    465             ((SettingsActivity) getActivity()).startPreferencePanel(
    466                     UserDetailsSettings.class.getName(),
    467                     extras,
    468                     -1, /* No title res id */
    469                     info.name, /* title */
    470                     null, /* resultTo */
    471                     0 /* resultRequestCode */);
    472         }
    473     }
    474 
    475     private void onUserCreated(int userId) {
    476         mAddedUserId = userId;
    477         if (mUserManager.getUserInfo(userId).isRestricted()) {
    478             showDialog(DIALOG_SETUP_PROFILE);
    479         } else {
    480             showDialog(DIALOG_SETUP_USER);
    481         }
    482     }
    483 
    484     @Override
    485     public void onDialogShowing() {
    486         super.onDialogShowing();
    487 
    488         setOnDismissListener(this);
    489     }
    490 
    491     @Override
    492     public Dialog onCreateDialog(int dialogId) {
    493         Context context = getActivity();
    494         if (context == null) return null;
    495         switch (dialogId) {
    496             case DIALOG_CONFIRM_REMOVE: {
    497                 Dialog dlg =
    498                         Utils.createRemoveConfirmationDialog(getActivity(), mRemovingUserId,
    499                                 new DialogInterface.OnClickListener() {
    500                                     public void onClick(DialogInterface dialog, int which) {
    501                                         removeUserNow();
    502                                     }
    503                                 }
    504                         );
    505                 return dlg;
    506             }
    507             case DIALOG_USER_CANNOT_MANAGE:
    508                 return new AlertDialog.Builder(context)
    509                     .setMessage(R.string.user_cannot_manage_message)
    510                     .setPositiveButton(android.R.string.ok, null)
    511                     .create();
    512             case DIALOG_ADD_USER: {
    513                 final SharedPreferences preferences = getActivity().getPreferences(
    514                         Context.MODE_PRIVATE);
    515                 final boolean longMessageDisplayed = preferences.getBoolean(
    516                         KEY_ADD_USER_LONG_MESSAGE_DISPLAYED, false);
    517                 final int messageResId = longMessageDisplayed
    518                         ? R.string.user_add_user_message_short
    519                         : R.string.user_add_user_message_long;
    520                 final int userType = dialogId == DIALOG_ADD_USER
    521                         ? USER_TYPE_USER : USER_TYPE_RESTRICTED_PROFILE;
    522                 Dialog dlg = new AlertDialog.Builder(context)
    523                     .setTitle(R.string.user_add_user_title)
    524                     .setMessage(messageResId)
    525                     .setPositiveButton(android.R.string.ok,
    526                         new DialogInterface.OnClickListener() {
    527                             public void onClick(DialogInterface dialog, int which) {
    528                                 addUserNow(userType);
    529                                 if (!longMessageDisplayed) {
    530                                     preferences.edit().putBoolean(
    531                                             KEY_ADD_USER_LONG_MESSAGE_DISPLAYED, true).apply();
    532                                 }
    533                             }
    534                     })
    535                     .setNegativeButton(android.R.string.cancel, null)
    536                     .create();
    537                 return dlg;
    538             }
    539             case DIALOG_SETUP_USER: {
    540                 Dialog dlg = new AlertDialog.Builder(context)
    541                     .setTitle(R.string.user_setup_dialog_title)
    542                     .setMessage(R.string.user_setup_dialog_message)
    543                     .setPositiveButton(R.string.user_setup_button_setup_now,
    544                         new DialogInterface.OnClickListener() {
    545                             public void onClick(DialogInterface dialog, int which) {
    546                                 switchUserNow(mAddedUserId);
    547                             }
    548                     })
    549                     .setNegativeButton(R.string.user_setup_button_setup_later, null)
    550                     .create();
    551                 return dlg;
    552             }
    553             case DIALOG_SETUP_PROFILE: {
    554                 Dialog dlg = new AlertDialog.Builder(context)
    555                     .setMessage(R.string.user_setup_profile_dialog_message)
    556                     .setPositiveButton(android.R.string.ok,
    557                         new DialogInterface.OnClickListener() {
    558                             public void onClick(DialogInterface dialog, int which) {
    559                                 switchUserNow(mAddedUserId);
    560                             }
    561                     })
    562                     .setNegativeButton(android.R.string.cancel, null)
    563                     .create();
    564                 return dlg;
    565             }
    566             case DIALOG_CHOOSE_USER_TYPE: {
    567                 List<HashMap<String, String>> data = new ArrayList<HashMap<String,String>>();
    568                 HashMap<String,String> addUserItem = new HashMap<String,String>();
    569                 addUserItem.put(KEY_TITLE, getString(R.string.user_add_user_item_title));
    570                 addUserItem.put(KEY_SUMMARY, getString(R.string.user_add_user_item_summary));
    571                 HashMap<String,String> addProfileItem = new HashMap<String,String>();
    572                 addProfileItem.put(KEY_TITLE, getString(R.string.user_add_profile_item_title));
    573                 addProfileItem.put(KEY_SUMMARY, getString(R.string.user_add_profile_item_summary));
    574                 data.add(addUserItem);
    575                 data.add(addProfileItem);
    576                 Dialog dlg = new AlertDialog.Builder(context)
    577                         .setTitle(R.string.user_add_user_type_title)
    578                         .setAdapter(new SimpleAdapter(context, data, R.layout.two_line_list_item,
    579                                 new String[] {KEY_TITLE, KEY_SUMMARY},
    580                                 new int[] {R.id.title, R.id.summary}),
    581                                 new DialogInterface.OnClickListener() {
    582                                     public void onClick(DialogInterface dialog, int which) {
    583                                         onAddUserClicked(which == 0
    584                                                 ? USER_TYPE_USER
    585                                                 : USER_TYPE_RESTRICTED_PROFILE);
    586                                     }
    587                                 })
    588                         .create();
    589                 return dlg;
    590             }
    591             case DIALOG_NEED_LOCKSCREEN: {
    592                 Dialog dlg = new AlertDialog.Builder(context)
    593                         .setMessage(R.string.user_need_lock_message)
    594                         .setPositiveButton(R.string.user_set_lock_button,
    595                                 new DialogInterface.OnClickListener() {
    596                                     @Override
    597                                     public void onClick(DialogInterface dialog, int which) {
    598                                         launchChooseLockscreen();
    599                                     }
    600                                 })
    601                         .setNegativeButton(android.R.string.cancel, null)
    602                         .create();
    603                 return dlg;
    604             }
    605             case DIALOG_CONFIRM_EXIT_GUEST: {
    606                 Dialog dlg = new AlertDialog.Builder(context)
    607                         .setTitle(R.string.user_exit_guest_confirm_title)
    608                         .setMessage(R.string.user_exit_guest_confirm_message)
    609                         .setPositiveButton(R.string.user_exit_guest_dialog_remove,
    610                                 new DialogInterface.OnClickListener() {
    611                                     @Override
    612                                     public void onClick(DialogInterface dialog, int which) {
    613                                         exitGuest();
    614                                     }
    615                                 })
    616                         .setNegativeButton(android.R.string.cancel, null)
    617                         .create();
    618                 return dlg;
    619             }
    620             case DIALOG_USER_PROFILE_EDITOR: {
    621                 Dialog dlg = mEditUserInfoController.createDialog(
    622                         (Fragment) this,
    623                         mMePreference.getIcon(),
    624                         mMePreference.getTitle(),
    625                         R.string.profile_info_settings_title,
    626                         this /* callback */,
    627                         android.os.Process.myUserHandle());
    628                 return dlg;
    629             }
    630             default:
    631                 return null;
    632         }
    633     }
    634 
    635     private void removeUserNow() {
    636         if (mRemovingUserId == UserHandle.myUserId()) {
    637             removeThisUser();
    638         } else {
    639             new Thread() {
    640                 public void run() {
    641                     synchronized (mUserLock) {
    642                         mUserManager.removeUser(mRemovingUserId);
    643                         mHandler.sendEmptyMessage(MESSAGE_UPDATE_LIST);
    644                     }
    645                 }
    646             }.start();
    647         }
    648     }
    649 
    650     private void removeThisUser() {
    651         try {
    652             ActivityManagerNative.getDefault().switchUser(UserHandle.USER_OWNER);
    653             ((UserManager) getActivity().getSystemService(Context.USER_SERVICE))
    654                     .removeUser(UserHandle.myUserId());
    655         } catch (RemoteException re) {
    656             Log.e(TAG, "Unable to remove self user");
    657         }
    658     }
    659 
    660     private void addUserNow(final int userType) {
    661         synchronized (mUserLock) {
    662             mAddingUser = true;
    663             //updateUserList();
    664             new Thread() {
    665                 public void run() {
    666                     UserInfo user = null;
    667                     // Could take a few seconds
    668                     if (userType == USER_TYPE_USER) {
    669                         user = createTrustedUser();
    670                     } else {
    671                         user = createLimitedUser();
    672                     }
    673                     synchronized (mUserLock) {
    674                         mAddingUser = false;
    675                         if (userType == USER_TYPE_USER) {
    676                             mHandler.sendEmptyMessage(MESSAGE_UPDATE_LIST);
    677                             mHandler.sendMessage(mHandler.obtainMessage(
    678                                     MESSAGE_SETUP_USER, user.id, user.serialNumber));
    679                         } else {
    680                             mHandler.sendMessage(mHandler.obtainMessage(
    681                                     MESSAGE_CONFIG_USER, user.id, user.serialNumber));
    682                         }
    683                     }
    684                 }
    685             }.start();
    686         }
    687     }
    688 
    689     private void switchUserNow(int userId) {
    690         try {
    691             ActivityManagerNative.getDefault().switchUser(userId);
    692         } catch (RemoteException re) {
    693             // Nothing to do
    694         }
    695     }
    696 
    697     /**
    698      * Erase the current user (guest) and switch to another user.
    699      */
    700     private void exitGuest() {
    701         // Just to be safe
    702         if (!mIsGuest) {
    703             return;
    704         }
    705         removeThisUser();
    706     }
    707 
    708     private void updateUserList() {
    709         if (getActivity() == null) return;
    710         List<UserInfo> users = mUserManager.getUsers(true);
    711         final Context context = getActivity();
    712 
    713         mUserListCategory.removeAll();
    714         mUserListCategory.setOrderingAsAdded(false);
    715         mUserListCategory.addPreference(mMePreference);
    716 
    717         final boolean voiceCapable = Utils.isVoiceCapable(context);
    718         final ArrayList<Integer> missingIcons = new ArrayList<Integer>();
    719         for (UserInfo user : users) {
    720             if (user.isManagedProfile()) {
    721                 // Managed profiles appear under Accounts Settings instead
    722                 continue;
    723             }
    724             Preference pref;
    725             if (user.id == UserHandle.myUserId()) {
    726                 pref = mMePreference;
    727             } else if (user.isGuest()) {
    728                 // Skip over Guest. We add generic Guest settings after this loop
    729                 continue;
    730             } else {
    731                 // With Telephony:
    732                 //   Secondary user: Settings
    733                 //   Guest: Settings
    734                 //   Restricted Profile: There is no Restricted Profile
    735                 // Without Telephony:
    736                 //   Secondary user: Delete
    737                 //   Guest: Nothing
    738                 //   Restricted Profile: Settings
    739                 final boolean showSettings = mIsOwner && (voiceCapable || user.isRestricted());
    740                 final boolean showDelete = mIsOwner
    741                         && (!voiceCapable && !user.isRestricted() && !user.isGuest());
    742                 pref = new UserPreference(context, null, user.id,
    743                         showSettings ? this : null,
    744                         showDelete ? this : null);
    745                 pref.setOnPreferenceClickListener(this);
    746                 pref.setKey("id=" + user.id);
    747                 mUserListCategory.addPreference(pref);
    748                 if (user.id == UserHandle.USER_OWNER) {
    749                     pref.setSummary(R.string.user_owner);
    750                 }
    751                 pref.setTitle(user.name);
    752             }
    753             if (!isInitialized(user)) {
    754                 if (user.isRestricted()) {
    755                     pref.setSummary(R.string.user_summary_restricted_not_set_up);
    756                 } else {
    757                     pref.setSummary(R.string.user_summary_not_set_up);
    758                 }
    759             } else if (user.isRestricted()) {
    760                 pref.setSummary(R.string.user_summary_restricted_profile);
    761             }
    762             if (user.iconPath != null) {
    763                 if (mUserIcons.get(user.id) == null) {
    764                     // Icon not loaded yet, print a placeholder
    765                     missingIcons.add(user.id);
    766                     pref.setIcon(getEncircledDefaultIcon());
    767                 } else {
    768                     setPhotoId(pref, user);
    769                 }
    770             } else {
    771                 // Icon not available yet, print a placeholder
    772                 pref.setIcon(getEncircledDefaultIcon());
    773             }
    774         }
    775 
    776         // Add a temporary entry for the user being created
    777         if (mAddingUser) {
    778             Preference pref = new UserPreference(getActivity(), null, UserPreference.USERID_UNKNOWN,
    779                     null, null);
    780             pref.setEnabled(false);
    781             pref.setTitle(R.string.user_new_user_name);
    782             pref.setIcon(getEncircledDefaultIcon());
    783             mUserListCategory.addPreference(pref);
    784         }
    785 
    786         boolean showGuestPreference = !mIsGuest;
    787         // If user has DISALLOW_ADD_USER don't allow creating a guest either.
    788         if (showGuestPreference && mUserManager.hasUserRestriction(UserManager.DISALLOW_ADD_USER)) {
    789             showGuestPreference = false;
    790             // If guest already exists, no user creation needed.
    791             for (UserInfo user : users) {
    792                 if (user.isGuest()) {
    793                     showGuestPreference = true;
    794                     break;
    795                 }
    796             }
    797         }
    798         if (showGuestPreference) {
    799             // Add a virtual Guest user for guest defaults
    800             Preference pref = new UserPreference(getActivity(), null,
    801                     UserPreference.USERID_GUEST_DEFAULTS,
    802                     mIsOwner && voiceCapable? this : null /* settings icon handler */,
    803                     null /* delete icon handler */);
    804             pref.setTitle(R.string.user_guest);
    805             pref.setIcon(getEncircledDefaultIcon());
    806             pref.setOnPreferenceClickListener(this);
    807             mUserListCategory.addPreference(pref);
    808         }
    809 
    810         getActivity().invalidateOptionsMenu();
    811 
    812         // Load the icons
    813         if (missingIcons.size() > 0) {
    814             loadIconsAsync(missingIcons);
    815         }
    816         boolean moreUsers = mUserManager.canAddMoreUsers();
    817         mAddUser.setEnabled(moreUsers);
    818     }
    819 
    820     private void loadIconsAsync(List<Integer> missingIcons) {
    821         final Resources resources = getResources();
    822         new AsyncTask<List<Integer>, Void, Void>() {
    823             @Override
    824             protected void onPostExecute(Void result) {
    825                 updateUserList();
    826             }
    827 
    828             @Override
    829             protected Void doInBackground(List<Integer>... values) {
    830                 for (int userId : values[0]) {
    831                     Bitmap bitmap = mUserManager.getUserIcon(userId);
    832                     if (bitmap == null) {
    833                         bitmap = UserIcons.convertToBitmap(UserIcons.getDefaultUserIcon(userId,
    834                                 /* light= */ false));
    835                     }
    836                     mUserIcons.append(userId, bitmap);
    837                 }
    838                 return null;
    839             }
    840         }.execute(missingIcons);
    841     }
    842 
    843     private void assignProfilePhoto(final UserInfo user) {
    844         if (!Utils.copyMeProfilePhoto(getActivity(), user)) {
    845             assignDefaultPhoto(user);
    846         }
    847     }
    848 
    849     private void assignDefaultPhoto(UserInfo user) {
    850         Bitmap bitmap = UserIcons.convertToBitmap(UserIcons.getDefaultUserIcon(user.id,
    851                 /* light= */ false));
    852         mUserManager.setUserIcon(user.id, bitmap);
    853     }
    854 
    855     private Drawable getEncircledDefaultIcon() {
    856         if (mDefaultIconDrawable == null) {
    857             mDefaultIconDrawable = encircle(UserIcons.convertToBitmap(
    858                     UserIcons.getDefaultUserIcon(UserHandle.USER_NULL, /* light= */ false)));
    859         }
    860         return mDefaultIconDrawable;
    861     }
    862 
    863     private void setPhotoId(Preference pref, UserInfo user) {
    864         Bitmap bitmap = mUserIcons.get(user.id);
    865         if (bitmap != null) {
    866             pref.setIcon(encircle(bitmap));
    867         }
    868     }
    869 
    870     private void setUserName(String name) {
    871         mUserManager.setUserName(UserHandle.myUserId(), name);
    872         mNicknamePreference.setSummary(name);
    873         getActivity().invalidateOptionsMenu();
    874     }
    875 
    876     @Override
    877     public boolean onPreferenceClick(Preference pref) {
    878         if (pref == mMePreference) {
    879             if (mIsGuest) {
    880                 showDialog(DIALOG_CONFIRM_EXIT_GUEST);
    881                 return true;
    882             }
    883             // If this is a limited user, launch the user info settings instead of profile editor
    884             if (mUserManager.isLinkedUser()) {
    885                 onManageUserClicked(UserHandle.myUserId(), false);
    886             } else {
    887                 showDialog(DIALOG_USER_PROFILE_EDITOR);
    888             }
    889         } else if (pref instanceof UserPreference) {
    890             int userId = ((UserPreference) pref).getUserId();
    891             if (userId == UserPreference.USERID_GUEST_DEFAULTS) {
    892                 createAndSwitchToGuestUser();
    893             } else {
    894                 // Get the latest status of the user
    895                 UserInfo user = mUserManager.getUserInfo(userId);
    896                 if (!isInitialized(user)) {
    897                     mHandler.sendMessage(mHandler.obtainMessage(
    898                             MESSAGE_SETUP_USER, user.id, user.serialNumber));
    899                 } else {
    900                     switchUserNow(userId);
    901                 }
    902             }
    903         } else if (pref == mAddUser) {
    904             // If we allow both types, show a picker, otherwise directly go to
    905             // flow for full user.
    906             if (mCanAddRestrictedProfile) {
    907                 showDialog(DIALOG_CHOOSE_USER_TYPE);
    908             } else {
    909                 onAddUserClicked(USER_TYPE_USER);
    910             }
    911         }
    912         return false;
    913     }
    914 
    915     private void createAndSwitchToGuestUser() {
    916         List<UserInfo> users = mUserManager.getUsers();
    917         for (UserInfo user : users) {
    918             if (user.isGuest()) {
    919                 switchUserNow(user.id);
    920                 return;
    921             }
    922         }
    923         // No guest user. Create one, if there's no restriction.
    924         // If it is not the primary user, then adding users from lockscreen must be enabled
    925         if (mUserManager.hasUserRestriction(UserManager.DISALLOW_ADD_USER)
    926                 || (!mIsOwner && Settings.Global.getInt(getContentResolver(),
    927                         Settings.Global.ADD_USERS_WHEN_LOCKED, 0) != 1)) {
    928             Log.i(TAG, "Blocking guest creation because it is restricted");
    929             return;
    930         }
    931         UserInfo guestUser = mUserManager.createGuest(getActivity(),
    932                     getResources().getString(R.string.user_guest));
    933         if (guestUser != null) {
    934             switchUserNow(guestUser.id);
    935         }
    936     }
    937 
    938     private boolean isInitialized(UserInfo user) {
    939         return (user.flags & UserInfo.FLAG_INITIALIZED) != 0;
    940     }
    941 
    942     private Drawable encircle(Bitmap icon) {
    943         Drawable circled = CircleFramedDrawable.getInstance(getActivity(), icon);
    944         return circled;
    945     }
    946 
    947     @Override
    948     public void onClick(View v) {
    949         if (v.getTag() instanceof UserPreference) {
    950             int userId = ((UserPreference) v.getTag()).getUserId();
    951             switch (v.getId()) {
    952             case UserPreference.DELETE_ID:
    953                 onRemoveUserClicked(userId);
    954                 break;
    955             case UserPreference.SETTINGS_ID:
    956                 onManageUserClicked(userId, false);
    957                 break;
    958             }
    959         }
    960     }
    961 
    962     @Override
    963     public void onDismiss(DialogInterface dialog) {
    964         synchronized (mUserLock) {
    965             mAddingUser = false;
    966             mRemovingUserId = -1;
    967             updateUserList();
    968         }
    969     }
    970 
    971     @Override
    972     public boolean onPreferenceChange(Preference preference, Object newValue) {
    973         if (preference == mNicknamePreference) {
    974             String value = (String) newValue;
    975             if (preference == mNicknamePreference && value != null
    976                     && value.length() > 0) {
    977                 setUserName(value);
    978             }
    979             return true;
    980         }
    981         return false;
    982     }
    983 
    984     @Override
    985     public int getHelpResource() {
    986         return R.string.help_url_users;
    987     }
    988 
    989     @Override
    990     public void onPhotoChanged(Drawable photo) {
    991         mMePreference.setIcon(photo);
    992     }
    993 
    994     @Override
    995     public void onLabelChanged(CharSequence label) {
    996         mMePreference.setTitle(label);
    997     }
    998 }
    999