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                 AlertDialog.Builder builder = new AlertDialog.Builder(context);
    577                 SimpleAdapter adapter = new SimpleAdapter(builder.getContext(),
    578                         data, R.layout.two_line_list_item,
    579                         new String[] {KEY_TITLE, KEY_SUMMARY},
    580                         new int[] {R.id.title, R.id.summary});
    581                 builder.setTitle(R.string.user_add_user_type_title);
    582                 builder.setAdapter(adapter,
    583                         new DialogInterface.OnClickListener() {
    584                             @Override
    585                             public void onClick(DialogInterface dialog, int which) {
    586                                 onAddUserClicked(which == 0
    587                                         ? USER_TYPE_USER
    588                                         : USER_TYPE_RESTRICTED_PROFILE);
    589                             }
    590                         });
    591                 return builder.create();
    592             }
    593             case DIALOG_NEED_LOCKSCREEN: {
    594                 Dialog dlg = new AlertDialog.Builder(context)
    595                         .setMessage(R.string.user_need_lock_message)
    596                         .setPositiveButton(R.string.user_set_lock_button,
    597                                 new DialogInterface.OnClickListener() {
    598                                     @Override
    599                                     public void onClick(DialogInterface dialog, int which) {
    600                                         launchChooseLockscreen();
    601                                     }
    602                                 })
    603                         .setNegativeButton(android.R.string.cancel, null)
    604                         .create();
    605                 return dlg;
    606             }
    607             case DIALOG_CONFIRM_EXIT_GUEST: {
    608                 Dialog dlg = new AlertDialog.Builder(context)
    609                         .setTitle(R.string.user_exit_guest_confirm_title)
    610                         .setMessage(R.string.user_exit_guest_confirm_message)
    611                         .setPositiveButton(R.string.user_exit_guest_dialog_remove,
    612                                 new DialogInterface.OnClickListener() {
    613                                     @Override
    614                                     public void onClick(DialogInterface dialog, int which) {
    615                                         exitGuest();
    616                                     }
    617                                 })
    618                         .setNegativeButton(android.R.string.cancel, null)
    619                         .create();
    620                 return dlg;
    621             }
    622             case DIALOG_USER_PROFILE_EDITOR: {
    623                 Dialog dlg = mEditUserInfoController.createDialog(
    624                         (Fragment) this,
    625                         mMePreference.getIcon(),
    626                         mMePreference.getTitle(),
    627                         R.string.profile_info_settings_title,
    628                         this /* callback */,
    629                         android.os.Process.myUserHandle());
    630                 return dlg;
    631             }
    632             default:
    633                 return null;
    634         }
    635     }
    636 
    637     private void removeUserNow() {
    638         if (mRemovingUserId == UserHandle.myUserId()) {
    639             removeThisUser();
    640         } else {
    641             new Thread() {
    642                 public void run() {
    643                     synchronized (mUserLock) {
    644                         mUserManager.removeUser(mRemovingUserId);
    645                         mHandler.sendEmptyMessage(MESSAGE_UPDATE_LIST);
    646                     }
    647                 }
    648             }.start();
    649         }
    650     }
    651 
    652     private void removeThisUser() {
    653         try {
    654             ActivityManagerNative.getDefault().switchUser(UserHandle.USER_OWNER);
    655             ((UserManager) getActivity().getSystemService(Context.USER_SERVICE))
    656                     .removeUser(UserHandle.myUserId());
    657         } catch (RemoteException re) {
    658             Log.e(TAG, "Unable to remove self user");
    659         }
    660     }
    661 
    662     private void addUserNow(final int userType) {
    663         synchronized (mUserLock) {
    664             mAddingUser = true;
    665             //updateUserList();
    666             new Thread() {
    667                 public void run() {
    668                     UserInfo user = null;
    669                     // Could take a few seconds
    670                     if (userType == USER_TYPE_USER) {
    671                         user = createTrustedUser();
    672                     } else {
    673                         user = createLimitedUser();
    674                     }
    675                     synchronized (mUserLock) {
    676                         mAddingUser = false;
    677                         if (userType == USER_TYPE_USER) {
    678                             mHandler.sendEmptyMessage(MESSAGE_UPDATE_LIST);
    679                             mHandler.sendMessage(mHandler.obtainMessage(
    680                                     MESSAGE_SETUP_USER, user.id, user.serialNumber));
    681                         } else {
    682                             mHandler.sendMessage(mHandler.obtainMessage(
    683                                     MESSAGE_CONFIG_USER, user.id, user.serialNumber));
    684                         }
    685                     }
    686                 }
    687             }.start();
    688         }
    689     }
    690 
    691     private void switchUserNow(int userId) {
    692         try {
    693             ActivityManagerNative.getDefault().switchUser(userId);
    694         } catch (RemoteException re) {
    695             // Nothing to do
    696         }
    697     }
    698 
    699     /**
    700      * Erase the current user (guest) and switch to another user.
    701      */
    702     private void exitGuest() {
    703         // Just to be safe
    704         if (!mIsGuest) {
    705             return;
    706         }
    707         removeThisUser();
    708     }
    709 
    710     private void updateUserList() {
    711         if (getActivity() == null) return;
    712         List<UserInfo> users = mUserManager.getUsers(true);
    713         final Context context = getActivity();
    714 
    715         mUserListCategory.removeAll();
    716         mUserListCategory.setOrderingAsAdded(false);
    717         mUserListCategory.addPreference(mMePreference);
    718 
    719         final boolean voiceCapable = Utils.isVoiceCapable(context);
    720         final ArrayList<Integer> missingIcons = new ArrayList<Integer>();
    721         for (UserInfo user : users) {
    722             if (user.isManagedProfile()) {
    723                 // Managed profiles appear under Accounts Settings instead
    724                 continue;
    725             }
    726             Preference pref;
    727             if (user.id == UserHandle.myUserId()) {
    728                 pref = mMePreference;
    729             } else if (user.isGuest()) {
    730                 // Skip over Guest. We add generic Guest settings after this loop
    731                 continue;
    732             } else {
    733                 // With Telephony:
    734                 //   Secondary user: Settings
    735                 //   Guest: Settings
    736                 //   Restricted Profile: There is no Restricted Profile
    737                 // Without Telephony:
    738                 //   Secondary user: Delete
    739                 //   Guest: Nothing
    740                 //   Restricted Profile: Settings
    741                 final boolean showSettings = mIsOwner && (voiceCapable || user.isRestricted());
    742                 final boolean showDelete = mIsOwner
    743                         && (!voiceCapable && !user.isRestricted() && !user.isGuest());
    744                 pref = new UserPreference(context, null, user.id,
    745                         showSettings ? this : null,
    746                         showDelete ? this : null);
    747                 pref.setOnPreferenceClickListener(this);
    748                 pref.setKey("id=" + user.id);
    749                 mUserListCategory.addPreference(pref);
    750                 if (user.id == UserHandle.USER_OWNER) {
    751                     pref.setSummary(R.string.user_owner);
    752                 }
    753                 pref.setTitle(user.name);
    754             }
    755             if (!isInitialized(user)) {
    756                 if (user.isRestricted()) {
    757                     pref.setSummary(R.string.user_summary_restricted_not_set_up);
    758                 } else {
    759                     pref.setSummary(R.string.user_summary_not_set_up);
    760                 }
    761             } else if (user.isRestricted()) {
    762                 pref.setSummary(R.string.user_summary_restricted_profile);
    763             }
    764             if (user.iconPath != null) {
    765                 if (mUserIcons.get(user.id) == null) {
    766                     // Icon not loaded yet, print a placeholder
    767                     missingIcons.add(user.id);
    768                     pref.setIcon(getEncircledDefaultIcon());
    769                 } else {
    770                     setPhotoId(pref, user);
    771                 }
    772             } else {
    773                 // Icon not available yet, print a placeholder
    774                 pref.setIcon(getEncircledDefaultIcon());
    775             }
    776         }
    777 
    778         // Add a temporary entry for the user being created
    779         if (mAddingUser) {
    780             Preference pref = new UserPreference(getActivity(), null, UserPreference.USERID_UNKNOWN,
    781                     null, null);
    782             pref.setEnabled(false);
    783             pref.setTitle(R.string.user_new_user_name);
    784             pref.setIcon(getEncircledDefaultIcon());
    785             mUserListCategory.addPreference(pref);
    786         }
    787 
    788         boolean showGuestPreference = !mIsGuest;
    789         // If user has DISALLOW_ADD_USER don't allow creating a guest either.
    790         if (showGuestPreference && mUserManager.hasUserRestriction(UserManager.DISALLOW_ADD_USER)) {
    791             showGuestPreference = false;
    792             // If guest already exists, no user creation needed.
    793             for (UserInfo user : users) {
    794                 if (user.isGuest()) {
    795                     showGuestPreference = true;
    796                     break;
    797                 }
    798             }
    799         }
    800         if (showGuestPreference) {
    801             // Add a virtual Guest user for guest defaults
    802             Preference pref = new UserPreference(getActivity(), null,
    803                     UserPreference.USERID_GUEST_DEFAULTS,
    804                     mIsOwner && voiceCapable? this : null /* settings icon handler */,
    805                     null /* delete icon handler */);
    806             pref.setTitle(R.string.user_guest);
    807             pref.setIcon(getEncircledDefaultIcon());
    808             pref.setOnPreferenceClickListener(this);
    809             mUserListCategory.addPreference(pref);
    810         }
    811 
    812         getActivity().invalidateOptionsMenu();
    813 
    814         // Load the icons
    815         if (missingIcons.size() > 0) {
    816             loadIconsAsync(missingIcons);
    817         }
    818         boolean moreUsers = mUserManager.canAddMoreUsers();
    819         mAddUser.setEnabled(moreUsers);
    820     }
    821 
    822     private void loadIconsAsync(List<Integer> missingIcons) {
    823         final Resources resources = getResources();
    824         new AsyncTask<List<Integer>, Void, Void>() {
    825             @Override
    826             protected void onPostExecute(Void result) {
    827                 updateUserList();
    828             }
    829 
    830             @Override
    831             protected Void doInBackground(List<Integer>... values) {
    832                 for (int userId : values[0]) {
    833                     Bitmap bitmap = mUserManager.getUserIcon(userId);
    834                     if (bitmap == null) {
    835                         bitmap = UserIcons.convertToBitmap(UserIcons.getDefaultUserIcon(userId,
    836                                 /* light= */ false));
    837                     }
    838                     mUserIcons.append(userId, bitmap);
    839                 }
    840                 return null;
    841             }
    842         }.execute(missingIcons);
    843     }
    844 
    845     private void assignProfilePhoto(final UserInfo user) {
    846         if (!Utils.copyMeProfilePhoto(getActivity(), user)) {
    847             assignDefaultPhoto(user);
    848         }
    849     }
    850 
    851     private void assignDefaultPhoto(UserInfo user) {
    852         Bitmap bitmap = UserIcons.convertToBitmap(UserIcons.getDefaultUserIcon(user.id,
    853                 /* light= */ false));
    854         mUserManager.setUserIcon(user.id, bitmap);
    855     }
    856 
    857     private Drawable getEncircledDefaultIcon() {
    858         if (mDefaultIconDrawable == null) {
    859             mDefaultIconDrawable = encircle(UserIcons.convertToBitmap(
    860                     UserIcons.getDefaultUserIcon(UserHandle.USER_NULL, /* light= */ false)));
    861         }
    862         return mDefaultIconDrawable;
    863     }
    864 
    865     private void setPhotoId(Preference pref, UserInfo user) {
    866         Bitmap bitmap = mUserIcons.get(user.id);
    867         if (bitmap != null) {
    868             pref.setIcon(encircle(bitmap));
    869         }
    870     }
    871 
    872     private void setUserName(String name) {
    873         mUserManager.setUserName(UserHandle.myUserId(), name);
    874         mNicknamePreference.setSummary(name);
    875         getActivity().invalidateOptionsMenu();
    876     }
    877 
    878     @Override
    879     public boolean onPreferenceClick(Preference pref) {
    880         if (pref == mMePreference) {
    881             if (mIsGuest) {
    882                 showDialog(DIALOG_CONFIRM_EXIT_GUEST);
    883                 return true;
    884             }
    885             // If this is a limited user, launch the user info settings instead of profile editor
    886             if (mUserManager.isLinkedUser()) {
    887                 onManageUserClicked(UserHandle.myUserId(), false);
    888             } else {
    889                 showDialog(DIALOG_USER_PROFILE_EDITOR);
    890             }
    891         } else if (pref instanceof UserPreference) {
    892             int userId = ((UserPreference) pref).getUserId();
    893             if (userId == UserPreference.USERID_GUEST_DEFAULTS) {
    894                 createAndSwitchToGuestUser();
    895             } else {
    896                 // Get the latest status of the user
    897                 UserInfo user = mUserManager.getUserInfo(userId);
    898                 if (!isInitialized(user)) {
    899                     mHandler.sendMessage(mHandler.obtainMessage(
    900                             MESSAGE_SETUP_USER, user.id, user.serialNumber));
    901                 } else {
    902                     switchUserNow(userId);
    903                 }
    904             }
    905         } else if (pref == mAddUser) {
    906             // If we allow both types, show a picker, otherwise directly go to
    907             // flow for full user.
    908             if (mCanAddRestrictedProfile) {
    909                 showDialog(DIALOG_CHOOSE_USER_TYPE);
    910             } else {
    911                 onAddUserClicked(USER_TYPE_USER);
    912             }
    913         }
    914         return false;
    915     }
    916 
    917     private void createAndSwitchToGuestUser() {
    918         List<UserInfo> users = mUserManager.getUsers();
    919         for (UserInfo user : users) {
    920             if (user.isGuest()) {
    921                 switchUserNow(user.id);
    922                 return;
    923             }
    924         }
    925         // No guest user. Create one, if there's no restriction.
    926         // If it is not the primary user, then adding users from lockscreen must be enabled
    927         if (mUserManager.hasUserRestriction(UserManager.DISALLOW_ADD_USER)
    928                 || (!mIsOwner && Settings.Global.getInt(getContentResolver(),
    929                         Settings.Global.ADD_USERS_WHEN_LOCKED, 0) != 1)) {
    930             Log.i(TAG, "Blocking guest creation because it is restricted");
    931             return;
    932         }
    933         UserInfo guestUser = mUserManager.createGuest(getActivity(),
    934                     getResources().getString(R.string.user_guest));
    935         if (guestUser != null) {
    936             switchUserNow(guestUser.id);
    937         }
    938     }
    939 
    940     private boolean isInitialized(UserInfo user) {
    941         return (user.flags & UserInfo.FLAG_INITIALIZED) != 0;
    942     }
    943 
    944     private Drawable encircle(Bitmap icon) {
    945         Drawable circled = CircleFramedDrawable.getInstance(getActivity(), icon);
    946         return circled;
    947     }
    948 
    949     @Override
    950     public void onClick(View v) {
    951         if (v.getTag() instanceof UserPreference) {
    952             int userId = ((UserPreference) v.getTag()).getUserId();
    953             switch (v.getId()) {
    954             case UserPreference.DELETE_ID:
    955                 onRemoveUserClicked(userId);
    956                 break;
    957             case UserPreference.SETTINGS_ID:
    958                 onManageUserClicked(userId, false);
    959                 break;
    960             }
    961         }
    962     }
    963 
    964     @Override
    965     public void onDismiss(DialogInterface dialog) {
    966         synchronized (mUserLock) {
    967             mAddingUser = false;
    968             mRemovingUserId = -1;
    969             updateUserList();
    970         }
    971     }
    972 
    973     @Override
    974     public boolean onPreferenceChange(Preference preference, Object newValue) {
    975         if (preference == mNicknamePreference) {
    976             String value = (String) newValue;
    977             if (preference == mNicknamePreference && value != null
    978                     && value.length() > 0) {
    979                 setUserName(value);
    980             }
    981             return true;
    982         }
    983         return false;
    984     }
    985 
    986     @Override
    987     public int getHelpResource() {
    988         return R.string.help_url_users;
    989     }
    990 
    991     @Override
    992     public void onPhotoChanged(Drawable photo) {
    993         mMePreference.setIcon(photo);
    994     }
    995 
    996     @Override
    997     public void onLabelChanged(CharSequence label) {
    998         mMePreference.setTitle(label);
    999     }
   1000 }
   1001