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 java.util.ArrayList;
     20 import java.util.HashMap;
     21 import java.util.List;
     22 
     23 import android.accounts.Account;
     24 import android.accounts.AccountManager;
     25 import android.app.Activity;
     26 import android.app.ActivityManagerNative;
     27 import android.app.AlertDialog;
     28 import android.app.Dialog;
     29 import android.app.admin.DevicePolicyManager;
     30 import android.content.BroadcastReceiver;
     31 import android.content.Context;
     32 import android.content.DialogInterface;
     33 import android.content.Intent;
     34 import android.content.IntentFilter;
     35 import android.content.SharedPreferences;
     36 import android.content.pm.UserInfo;
     37 import android.content.res.Resources;
     38 import android.graphics.Bitmap;
     39 import android.graphics.BitmapFactory;
     40 import android.graphics.drawable.Drawable;
     41 import android.os.AsyncTask;
     42 import android.os.Bundle;
     43 import android.os.Handler;
     44 import android.os.Message;
     45 import android.os.RemoteException;
     46 import android.os.UserHandle;
     47 import android.os.UserManager;
     48 import android.preference.Preference;
     49 import android.preference.Preference.OnPreferenceClickListener;
     50 import android.preference.PreferenceActivity;
     51 import android.preference.PreferenceGroup;
     52 import android.provider.ContactsContract;
     53 import android.provider.ContactsContract.Contacts;
     54 import android.provider.Settings.Secure;
     55 import android.util.Log;
     56 import android.util.SparseArray;
     57 import android.view.Menu;
     58 import android.view.MenuInflater;
     59 import android.view.MenuItem;
     60 import android.view.View;
     61 import android.view.View.OnClickListener;
     62 import android.widget.SimpleAdapter;
     63 
     64 import com.android.internal.widget.LockPatternUtils;
     65 import com.android.settings.ChooseLockGeneric;
     66 import com.android.settings.OwnerInfoSettings;
     67 import com.android.settings.R;
     68 import com.android.settings.RestrictedSettingsFragment;
     69 import com.android.settings.SelectableEditTextPreference;
     70 import com.android.settings.Utils;
     71 
     72 public class UserSettings extends RestrictedSettingsFragment
     73         implements OnPreferenceClickListener, OnClickListener, DialogInterface.OnDismissListener,
     74         Preference.OnPreferenceChangeListener {
     75 
     76     private static final String TAG = "UserSettings";
     77 
     78     /** UserId of the user being removed */
     79     private static final String SAVE_REMOVING_USER = "removing_user";
     80     /** UserId of the user that was just added */
     81     private static final String SAVE_ADDING_USER = "adding_user";
     82 
     83     private static final String KEY_USER_LIST = "user_list";
     84     private static final String KEY_USER_ME = "user_me";
     85     private static final String KEY_ADD_USER = "user_add";
     86 
     87     private static final int MENU_REMOVE_USER = Menu.FIRST;
     88 
     89     private static final int DIALOG_CONFIRM_REMOVE = 1;
     90     private static final int DIALOG_ADD_USER = 2;
     91     private static final int DIALOG_SETUP_USER = 3;
     92     private static final int DIALOG_SETUP_PROFILE = 4;
     93     private static final int DIALOG_USER_CANNOT_MANAGE = 5;
     94     private static final int DIALOG_CHOOSE_USER_TYPE = 6;
     95     private static final int DIALOG_NEED_LOCKSCREEN = 7;
     96 
     97     private static final int MESSAGE_UPDATE_LIST = 1;
     98     private static final int MESSAGE_SETUP_USER = 2;
     99     private static final int MESSAGE_CONFIG_USER = 3;
    100 
    101     private static final int USER_TYPE_USER = 1;
    102     private static final int USER_TYPE_RESTRICTED_PROFILE = 2;
    103 
    104     private static final int REQUEST_CHOOSE_LOCK = 10;
    105 
    106     private static final String KEY_ADD_USER_LONG_MESSAGE_DISPLAYED =
    107             "key_add_user_long_message_displayed";
    108 
    109     static final int[] USER_DRAWABLES = {
    110         R.drawable.avatar_default_1,
    111         R.drawable.avatar_default_2,
    112         R.drawable.avatar_default_3,
    113         R.drawable.avatar_default_4,
    114         R.drawable.avatar_default_5,
    115         R.drawable.avatar_default_6,
    116         R.drawable.avatar_default_7,
    117         R.drawable.avatar_default_8
    118     };
    119 
    120     private static final String KEY_TITLE = "title";
    121     private static final String KEY_SUMMARY = "summary";
    122 
    123     private PreferenceGroup mUserListCategory;
    124     private Preference mMePreference;
    125     private SelectableEditTextPreference mNicknamePreference;
    126     private Preference mAddUser;
    127     private int mRemovingUserId = -1;
    128     private int mAddedUserId = 0;
    129     private boolean mAddingUser;
    130     private boolean mProfileExists;
    131 
    132     private final Object mUserLock = new Object();
    133     private UserManager mUserManager;
    134     private SparseArray<Bitmap> mUserIcons = new SparseArray<Bitmap>();
    135     private boolean mIsOwner = UserHandle.myUserId() == UserHandle.USER_OWNER;
    136 
    137     public UserSettings() {
    138         super(RestrictedSettingsFragment.RESTRICTIONS_PIN_SET);
    139     }
    140 
    141     private Handler mHandler = new Handler() {
    142         @Override
    143         public void handleMessage(Message msg) {
    144             switch (msg.what) {
    145             case MESSAGE_UPDATE_LIST:
    146                 updateUserList();
    147                 break;
    148             case MESSAGE_SETUP_USER:
    149                 onUserCreated(msg.arg1);
    150                 break;
    151             case MESSAGE_CONFIG_USER:
    152                 onManageUserClicked(msg.arg1, true);
    153                 break;
    154             }
    155         }
    156     };
    157 
    158     private BroadcastReceiver mUserChangeReceiver = new BroadcastReceiver() {
    159         @Override
    160         public void onReceive(Context context, Intent intent) {
    161             if (intent.getAction().equals(Intent.ACTION_USER_REMOVED)) {
    162                 mRemovingUserId = -1;
    163             } else if (intent.getAction().equals(Intent.ACTION_USER_INFO_CHANGED)) {
    164                 int userHandle = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
    165                 if (userHandle != -1) {
    166                     mUserIcons.remove(userHandle);
    167                 }
    168             }
    169             mHandler.sendEmptyMessage(MESSAGE_UPDATE_LIST);
    170         }
    171     };
    172 
    173     @Override
    174     public void onCreate(Bundle icicle) {
    175         super.onCreate(icicle);
    176 
    177         if (icicle != null) {
    178             if (icicle.containsKey(SAVE_ADDING_USER)) {
    179                 mAddedUserId = icicle.getInt(SAVE_ADDING_USER);
    180             }
    181             if (icicle.containsKey(SAVE_REMOVING_USER)) {
    182                 mRemovingUserId = icicle.getInt(SAVE_REMOVING_USER);
    183             }
    184         }
    185 
    186         mUserManager = (UserManager) getActivity().getSystemService(Context.USER_SERVICE);
    187         addPreferencesFromResource(R.xml.user_settings);
    188         mUserListCategory = (PreferenceGroup) findPreference(KEY_USER_LIST);
    189         mMePreference = new UserPreference(getActivity(), null, UserHandle.myUserId(),
    190                 mUserManager.isLinkedUser() ? null : this, null);
    191         mMePreference.setKey(KEY_USER_ME);
    192         mMePreference.setOnPreferenceClickListener(this);
    193         if (mIsOwner) {
    194             mMePreference.setSummary(R.string.user_owner);
    195         }
    196         mAddUser = findPreference(KEY_ADD_USER);
    197         mAddUser.setOnPreferenceClickListener(this);
    198         if (!mIsOwner || UserManager.getMaxSupportedUsers() < 2) {
    199             removePreference(KEY_ADD_USER);
    200         }
    201         loadProfile();
    202         setHasOptionsMenu(true);
    203         IntentFilter filter = new IntentFilter(Intent.ACTION_USER_REMOVED);
    204         filter.addAction(Intent.ACTION_USER_INFO_CHANGED);
    205         getActivity().registerReceiverAsUser(mUserChangeReceiver, UserHandle.ALL, filter, null,
    206                 mHandler);
    207     }
    208 
    209     @Override
    210     public void onResume() {
    211         super.onResume();
    212         loadProfile();
    213         updateUserList();
    214     }
    215 
    216     @Override
    217     public void onDestroy() {
    218         super.onDestroy();
    219         getActivity().unregisterReceiver(mUserChangeReceiver);
    220     }
    221 
    222     @Override
    223     public void onSaveInstanceState(Bundle outState) {
    224         super.onSaveInstanceState(outState);
    225 
    226         outState.putInt(SAVE_ADDING_USER, mAddedUserId);
    227         outState.putInt(SAVE_REMOVING_USER, mRemovingUserId);
    228     }
    229 
    230     @Override
    231     public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    232         UserManager um = (UserManager) getActivity().getSystemService(Context.USER_SERVICE);
    233         if (!mIsOwner && !um.hasUserRestriction(UserManager.DISALLOW_REMOVE_USER)) {
    234             String nickname = mUserManager.getUserName();
    235             MenuItem removeThisUser = menu.add(0, MENU_REMOVE_USER, 0,
    236                     getResources().getString(R.string.user_remove_user_menu, nickname));
    237             removeThisUser.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
    238         }
    239         super.onCreateOptionsMenu(menu, inflater);
    240     }
    241 
    242     @Override
    243     public boolean onOptionsItemSelected(MenuItem item) {
    244         final int itemId = item.getItemId();
    245         if (itemId == MENU_REMOVE_USER) {
    246             onRemoveUserClicked(UserHandle.myUserId());
    247             return true;
    248         } else {
    249             return super.onOptionsItemSelected(item);
    250         }
    251     }
    252 
    253     private void loadProfile() {
    254         mProfileExists = false;
    255         new AsyncTask<Void, Void, String>() {
    256             @Override
    257             protected void onPostExecute(String result) {
    258                 finishLoadProfile(result);
    259             }
    260 
    261             @Override
    262             protected String doInBackground(Void... values) {
    263                 UserInfo user = mUserManager.getUserInfo(UserHandle.myUserId());
    264                 if (user.iconPath == null || user.iconPath.equals("")) {
    265                     assignProfilePhoto(user);
    266                 }
    267                 String profileName = getProfileName();
    268                 if (profileName == null) {
    269                     profileName = user.name;
    270                 }
    271                 return profileName;
    272             }
    273         }.execute();
    274     }
    275 
    276     private void finishLoadProfile(String profileName) {
    277         if (getActivity() == null) return;
    278         mMePreference.setTitle(getString(R.string.user_you, profileName));
    279         int myUserId = UserHandle.myUserId();
    280         Bitmap b = mUserManager.getUserIcon(myUserId);
    281         if (b != null) {
    282             mMePreference.setIcon(encircle(b));
    283             mUserIcons.put(myUserId, b);
    284         }
    285     }
    286 
    287     private boolean hasLockscreenSecurity() {
    288         LockPatternUtils lpu = new LockPatternUtils(getActivity());
    289         return lpu.isLockPasswordEnabled() || lpu.isLockPatternEnabled();
    290     }
    291 
    292     private void launchChooseLockscreen() {
    293         Intent chooseLockIntent = new Intent(DevicePolicyManager.ACTION_SET_NEW_PASSWORD);
    294         chooseLockIntent.putExtra(ChooseLockGeneric.ChooseLockGenericFragment.MINIMUM_QUALITY_KEY,
    295                 DevicePolicyManager.PASSWORD_QUALITY_SOMETHING);
    296         startActivityForResult(chooseLockIntent, REQUEST_CHOOSE_LOCK);
    297     }
    298 
    299     @Override
    300     public void onActivityResult(int requestCode, int resultCode, Intent data) {
    301         super.onActivityResult(requestCode, resultCode, data);
    302 
    303         if (requestCode == REQUEST_CHOOSE_LOCK) {
    304             if (resultCode != Activity.RESULT_CANCELED && hasLockscreenSecurity()) {
    305                 addUserNow(USER_TYPE_RESTRICTED_PROFILE);
    306             } else {
    307                 showDialog(DIALOG_NEED_LOCKSCREEN);
    308             }
    309         }
    310     }
    311 
    312     private void onAddUserClicked(int userType) {
    313         synchronized (mUserLock) {
    314             if (mRemovingUserId == -1 && !mAddingUser) {
    315                 switch (userType) {
    316                 case USER_TYPE_USER:
    317                     showDialog(DIALOG_ADD_USER);
    318                     break;
    319                 case USER_TYPE_RESTRICTED_PROFILE:
    320                     if (hasLockscreenSecurity()) {
    321                         addUserNow(USER_TYPE_RESTRICTED_PROFILE);
    322                     } else {
    323                         showDialog(DIALOG_NEED_LOCKSCREEN);
    324                     }
    325                     break;
    326                 }
    327             }
    328         }
    329     }
    330 
    331     private void onRemoveUserClicked(int userId) {
    332         synchronized (mUserLock) {
    333             if (mRemovingUserId == -1 && !mAddingUser) {
    334                 mRemovingUserId = userId;
    335                 showDialog(DIALOG_CONFIRM_REMOVE);
    336             }
    337         }
    338     }
    339 
    340     private UserInfo createLimitedUser() {
    341         UserInfo newUserInfo = mUserManager.createUser(
    342                 getResources().getString(R.string.user_new_profile_name),
    343                 UserInfo.FLAG_RESTRICTED);
    344         int userId = newUserInfo.id;
    345         UserHandle user = new UserHandle(userId);
    346         mUserManager.setUserRestriction(UserManager.DISALLOW_MODIFY_ACCOUNTS, true, user);
    347         mUserManager.setUserRestriction(UserManager.DISALLOW_SHARE_LOCATION, true, user);
    348         Secure.putStringForUser(getContentResolver(),
    349                 Secure.LOCATION_PROVIDERS_ALLOWED, "", userId);
    350         Bitmap bitmap = BitmapFactory.decodeResource(getResources(),
    351                 UserSettings.USER_DRAWABLES[
    352                         userId % UserSettings.USER_DRAWABLES.length]);
    353         mUserManager.setUserIcon(userId, bitmap);
    354         // Add shared accounts
    355         AccountManager am = AccountManager.get(getActivity());
    356         Account [] accounts = am.getAccounts();
    357         if (accounts != null) {
    358             for (Account account : accounts) {
    359                 am.addSharedAccount(account, user);
    360             }
    361         }
    362         return newUserInfo;
    363     }
    364 
    365     private UserInfo createTrustedUser() {
    366         UserInfo newUserInfo = mUserManager.createUser(
    367                 getResources().getString(R.string.user_new_user_name), 0);
    368         if (newUserInfo != null) {
    369             assignDefaultPhoto(newUserInfo);
    370         }
    371         return newUserInfo;
    372     }
    373 
    374     private void onManageUserClicked(int userId, boolean newUser) {
    375         UserInfo info = mUserManager.getUserInfo(userId);
    376         if (info.isRestricted() && mIsOwner) {
    377             Bundle extras = new Bundle();
    378             extras.putInt(RestrictedProfileSettings.EXTRA_USER_ID, userId);
    379             extras.putBoolean(RestrictedProfileSettings.EXTRA_NEW_USER, newUser);
    380             ((PreferenceActivity) getActivity()).startPreferencePanel(
    381                     RestrictedProfileSettings.class.getName(),
    382                     extras, R.string.user_restrictions_title, null,
    383                     null, 0);
    384         } else if (info.id == UserHandle.myUserId()) {
    385             // Jump to owner info panel
    386             Bundle extras = new Bundle();
    387             if (!info.isRestricted()) {
    388                 extras.putBoolean(OwnerInfoSettings.EXTRA_SHOW_NICKNAME, true);
    389             }
    390             int titleResId = info.id == UserHandle.USER_OWNER ? R.string.owner_info_settings_title
    391                     : (info.isRestricted() ? R.string.profile_info_settings_title
    392                             : R.string.user_info_settings_title);
    393             ((PreferenceActivity) getActivity()).startPreferencePanel(
    394                     OwnerInfoSettings.class.getName(),
    395                     extras, titleResId, null, null, 0);
    396         }
    397     }
    398 
    399     private void onUserCreated(int userId) {
    400         mAddedUserId = userId;
    401         if (mUserManager.getUserInfo(userId).isRestricted()) {
    402             showDialog(DIALOG_SETUP_PROFILE);
    403         } else {
    404             showDialog(DIALOG_SETUP_USER);
    405         }
    406     }
    407 
    408     @Override
    409     public void onDialogShowing() {
    410         super.onDialogShowing();
    411 
    412         setOnDismissListener(this);
    413     }
    414 
    415     @Override
    416     public Dialog onCreateDialog(int dialogId) {
    417         Context context = getActivity();
    418         if (context == null) return null;
    419         switch (dialogId) {
    420             case DIALOG_CONFIRM_REMOVE: {
    421                 Dialog dlg = new AlertDialog.Builder(getActivity())
    422                     .setTitle(UserHandle.myUserId() == mRemovingUserId
    423                             ? R.string.user_confirm_remove_self_title
    424                             : (mUserManager.getUserInfo(mRemovingUserId).isRestricted()
    425                                     ? R.string.user_profile_confirm_remove_title
    426                                     : R.string.user_confirm_remove_title))
    427                     .setMessage(UserHandle.myUserId() == mRemovingUserId
    428                             ? R.string.user_confirm_remove_self_message
    429                             : (mUserManager.getUserInfo(mRemovingUserId).isRestricted()
    430                                     ? R.string.user_profile_confirm_remove_message
    431                                     : R.string.user_confirm_remove_message))
    432                     .setPositiveButton(R.string.user_delete_button,
    433                         new DialogInterface.OnClickListener() {
    434                             public void onClick(DialogInterface dialog, int which) {
    435                                 removeUserNow();
    436                             }
    437                     })
    438                     .setNegativeButton(android.R.string.cancel, null)
    439                     .create();
    440                 return dlg;
    441             }
    442             case DIALOG_USER_CANNOT_MANAGE:
    443                 return new AlertDialog.Builder(context)
    444                     .setMessage(R.string.user_cannot_manage_message)
    445                     .setPositiveButton(android.R.string.ok, null)
    446                     .create();
    447             case DIALOG_ADD_USER: {
    448                 final SharedPreferences preferences = getActivity().getPreferences(
    449                         Context.MODE_PRIVATE);
    450                 final boolean longMessageDisplayed = preferences.getBoolean(
    451                         KEY_ADD_USER_LONG_MESSAGE_DISPLAYED, false);
    452                 final int messageResId = longMessageDisplayed
    453                         ? R.string.user_add_user_message_short
    454                         : R.string.user_add_user_message_long;
    455                 final int userType = dialogId == DIALOG_ADD_USER
    456                         ? USER_TYPE_USER : USER_TYPE_RESTRICTED_PROFILE;
    457                 Dialog dlg = new AlertDialog.Builder(context)
    458                     .setTitle(R.string.user_add_user_title)
    459                     .setMessage(messageResId)
    460                     .setPositiveButton(android.R.string.ok,
    461                         new DialogInterface.OnClickListener() {
    462                             public void onClick(DialogInterface dialog, int which) {
    463                                 addUserNow(userType);
    464                                 if (!longMessageDisplayed) {
    465                                     preferences.edit().putBoolean(
    466                                             KEY_ADD_USER_LONG_MESSAGE_DISPLAYED, true).apply();
    467                                 }
    468                             }
    469                     })
    470                     .setNegativeButton(android.R.string.cancel, null)
    471                     .create();
    472                 return dlg;
    473             }
    474             case DIALOG_SETUP_USER: {
    475                 Dialog dlg = new AlertDialog.Builder(context)
    476                     .setTitle(R.string.user_setup_dialog_title)
    477                     .setMessage(R.string.user_setup_dialog_message)
    478                     .setPositiveButton(R.string.user_setup_button_setup_now,
    479                         new DialogInterface.OnClickListener() {
    480                             public void onClick(DialogInterface dialog, int which) {
    481                                 switchUserNow(mAddedUserId);
    482                             }
    483                     })
    484                     .setNegativeButton(R.string.user_setup_button_setup_later, null)
    485                     .create();
    486                 return dlg;
    487             }
    488             case DIALOG_SETUP_PROFILE: {
    489                 Dialog dlg = new AlertDialog.Builder(context)
    490                     .setMessage(R.string.user_setup_profile_dialog_message)
    491                     .setPositiveButton(android.R.string.ok,
    492                         new DialogInterface.OnClickListener() {
    493                             public void onClick(DialogInterface dialog, int which) {
    494                                 switchUserNow(mAddedUserId);
    495                             }
    496                     })
    497                     .setNegativeButton(android.R.string.cancel, null)
    498                     .create();
    499                 return dlg;
    500             }
    501             case DIALOG_CHOOSE_USER_TYPE: {
    502                 List<HashMap<String, String>> data = new ArrayList<HashMap<String,String>>();
    503                 HashMap<String,String> addUserItem = new HashMap<String,String>();
    504                 addUserItem.put(KEY_TITLE, getString(R.string.user_add_user_item_title));
    505                 addUserItem.put(KEY_SUMMARY, getString(R.string.user_add_user_item_summary));
    506                 HashMap<String,String> addProfileItem = new HashMap<String,String>();
    507                 addProfileItem.put(KEY_TITLE, getString(R.string.user_add_profile_item_title));
    508                 addProfileItem.put(KEY_SUMMARY, getString(R.string.user_add_profile_item_summary));
    509                 data.add(addUserItem);
    510                 data.add(addProfileItem);
    511                 Dialog dlg = new AlertDialog.Builder(context)
    512                         .setTitle(R.string.user_add_user_type_title)
    513                         .setAdapter(new SimpleAdapter(context, data, R.layout.two_line_list_item,
    514                                 new String[] {KEY_TITLE, KEY_SUMMARY},
    515                                 new int[] {R.id.title, R.id.summary}),
    516                                 new DialogInterface.OnClickListener() {
    517                                     public void onClick(DialogInterface dialog, int which) {
    518                                         onAddUserClicked(which == 0
    519                                                 ? USER_TYPE_USER
    520                                                 : USER_TYPE_RESTRICTED_PROFILE);
    521                                     }
    522                                 })
    523                         .create();
    524                 return dlg;
    525             }
    526             case DIALOG_NEED_LOCKSCREEN: {
    527                 Dialog dlg = new AlertDialog.Builder(context)
    528                         .setMessage(R.string.user_need_lock_message)
    529                         .setPositiveButton(R.string.user_set_lock_button,
    530                                 new DialogInterface.OnClickListener() {
    531                                     @Override
    532                                     public void onClick(DialogInterface dialog, int which) {
    533                                         launchChooseLockscreen();
    534                                     }
    535                                 })
    536                         .setNegativeButton(android.R.string.cancel, null)
    537                         .create();
    538                 return dlg;
    539             }
    540             default:
    541                 return null;
    542         }
    543     }
    544 
    545     private void removeUserNow() {
    546         if (mRemovingUserId == UserHandle.myUserId()) {
    547             removeThisUser();
    548         } else {
    549             new Thread() {
    550                 public void run() {
    551                     synchronized (mUserLock) {
    552                         mUserManager.removeUser(mRemovingUserId);
    553                         mHandler.sendEmptyMessage(MESSAGE_UPDATE_LIST);
    554                     }
    555                 }
    556             }.start();
    557         }
    558     }
    559 
    560     private void removeThisUser() {
    561         try {
    562             ActivityManagerNative.getDefault().switchUser(UserHandle.USER_OWNER);
    563             ((UserManager) getActivity().getSystemService(Context.USER_SERVICE))
    564                     .removeUser(UserHandle.myUserId());
    565         } catch (RemoteException re) {
    566             Log.e(TAG, "Unable to remove self user");
    567         }
    568     }
    569 
    570     private void addUserNow(final int userType) {
    571         synchronized (mUserLock) {
    572             mAddingUser = true;
    573             //updateUserList();
    574             new Thread() {
    575                 public void run() {
    576                     UserInfo user = null;
    577                     // Could take a few seconds
    578                     if (userType == USER_TYPE_USER) {
    579                         user = createTrustedUser();
    580                     } else {
    581                         user = createLimitedUser();
    582                     }
    583                     synchronized (mUserLock) {
    584                         mAddingUser = false;
    585                         if (userType == USER_TYPE_USER) {
    586                             mHandler.sendEmptyMessage(MESSAGE_UPDATE_LIST);
    587                             mHandler.sendMessage(mHandler.obtainMessage(
    588                                     MESSAGE_SETUP_USER, user.id, user.serialNumber));
    589                         } else {
    590                             mHandler.sendMessage(mHandler.obtainMessage(
    591                                     MESSAGE_CONFIG_USER, user.id, user.serialNumber));
    592                         }
    593                     }
    594                 }
    595             }.start();
    596         }
    597     }
    598 
    599     private void switchUserNow(int userId) {
    600         try {
    601             ActivityManagerNative.getDefault().switchUser(userId);
    602         } catch (RemoteException re) {
    603             // Nothing to do
    604         }
    605     }
    606 
    607     private void updateUserList() {
    608         if (getActivity() == null) return;
    609         List<UserInfo> users = mUserManager.getUsers(true);
    610 
    611         mUserListCategory.removeAll();
    612         mUserListCategory.setOrderingAsAdded(false);
    613         mUserListCategory.addPreference(mMePreference);
    614 
    615         final ArrayList<Integer> missingIcons = new ArrayList<Integer>();
    616         for (UserInfo user : users) {
    617             Preference pref;
    618             if (user.id == UserHandle.myUserId()) {
    619                 pref = mMePreference;
    620             } else {
    621                 pref = new UserPreference(getActivity(), null, user.id,
    622                         mIsOwner && user.isRestricted() ? this : null,
    623                         mIsOwner ? this : null);
    624                 pref.setOnPreferenceClickListener(this);
    625                 pref.setKey("id=" + user.id);
    626                 mUserListCategory.addPreference(pref);
    627                 if (user.id == UserHandle.USER_OWNER) {
    628                     pref.setSummary(R.string.user_owner);
    629                 }
    630                 pref.setTitle(user.name);
    631             }
    632             if (!isInitialized(user)) {
    633                 pref.setSummary(user.isRestricted()
    634                         ? R.string.user_summary_restricted_not_set_up
    635                         : R.string.user_summary_not_set_up);
    636             } else if (user.isRestricted()) {
    637                 pref.setSummary(R.string.user_summary_restricted_profile);
    638             }
    639             if (user.iconPath != null) {
    640                 if (mUserIcons.get(user.id) == null) {
    641                     missingIcons.add(user.id);
    642                     pref.setIcon(encircle(R.drawable.avatar_default_1));
    643                 } else {
    644                     setPhotoId(pref, user);
    645                 }
    646             }
    647         }
    648         // Add a temporary entry for the user being created
    649         if (mAddingUser) {
    650             Preference pref = new UserPreference(getActivity(), null, UserPreference.USERID_UNKNOWN,
    651                     null, null);
    652             pref.setEnabled(false);
    653             pref.setTitle(R.string.user_new_user_name);
    654             pref.setIcon(encircle(R.drawable.avatar_default_1));
    655             mUserListCategory.addPreference(pref);
    656         }
    657         getActivity().invalidateOptionsMenu();
    658 
    659         // Load the icons
    660         if (missingIcons.size() > 0) {
    661             loadIconsAsync(missingIcons);
    662         }
    663         boolean moreUsers = mUserManager.getMaxSupportedUsers() > users.size();
    664         mAddUser.setEnabled(moreUsers);
    665     }
    666 
    667     private void loadIconsAsync(List<Integer> missingIcons) {
    668         final Resources resources = getResources();
    669         new AsyncTask<List<Integer>, Void, Void>() {
    670             @Override
    671             protected void onPostExecute(Void result) {
    672                 updateUserList();
    673             }
    674 
    675             @Override
    676             protected Void doInBackground(List<Integer>... values) {
    677                 for (int userId : values[0]) {
    678                     Bitmap bitmap = mUserManager.getUserIcon(userId);
    679                     mUserIcons.append(userId, bitmap);
    680                 }
    681                 return null;
    682             }
    683         }.execute(missingIcons);
    684     }
    685 
    686     private void assignProfilePhoto(final UserInfo user) {
    687         if (!Utils.copyMeProfilePhoto(getActivity(), user)) {
    688             assignDefaultPhoto(user);
    689         }
    690     }
    691 
    692     private String getProfileName() {
    693         String name = Utils.getMeProfileName(getActivity(), true);
    694         if (name != null) {
    695             mProfileExists = true;
    696         }
    697         return name;
    698     }
    699 
    700     private void assignDefaultPhoto(UserInfo user) {
    701         Bitmap bitmap = BitmapFactory.decodeResource(getResources(),
    702                 USER_DRAWABLES[user.id % USER_DRAWABLES.length]);
    703         mUserManager.setUserIcon(user.id, bitmap);
    704     }
    705 
    706     private void setPhotoId(Preference pref, UserInfo user) {
    707         Bitmap bitmap = mUserIcons.get(user.id);
    708         if (bitmap != null) {
    709             pref.setIcon(encircle(bitmap));
    710         }
    711     }
    712 
    713     private void setUserName(String name) {
    714         mUserManager.setUserName(UserHandle.myUserId(), name);
    715         mNicknamePreference.setSummary(name);
    716         getActivity().invalidateOptionsMenu();
    717     }
    718 
    719     @Override
    720     public boolean onPreferenceClick(Preference pref) {
    721         if (pref == mMePreference) {
    722             Intent editProfile;
    723             if (!mProfileExists) {
    724                 editProfile = new Intent(Intent.ACTION_INSERT, Contacts.CONTENT_URI);
    725                 // TODO: Make this a proper API
    726                 editProfile.putExtra("newLocalProfile", true);
    727             } else {
    728                 editProfile = new Intent(Intent.ACTION_EDIT, ContactsContract.Profile.CONTENT_URI);
    729             }
    730             // To make sure that it returns back here when done
    731             // TODO: Make this a proper API
    732             editProfile.putExtra("finishActivityOnSaveCompleted", true);
    733 
    734             // If this is a limited user, launch the user info settings instead of profile editor
    735             if (mUserManager.isLinkedUser()) {
    736                 onManageUserClicked(UserHandle.myUserId(), false);
    737             } else {
    738                 startActivity(editProfile);
    739             }
    740         } else if (pref instanceof UserPreference) {
    741             int userId = ((UserPreference) pref).getUserId();
    742             // Get the latest status of the user
    743             UserInfo user = mUserManager.getUserInfo(userId);
    744             if (UserHandle.myUserId() != UserHandle.USER_OWNER) {
    745                 showDialog(DIALOG_USER_CANNOT_MANAGE);
    746             } else {
    747                 if (!isInitialized(user)) {
    748                     mHandler.sendMessage(mHandler.obtainMessage(
    749                             MESSAGE_SETUP_USER, user.id, user.serialNumber));
    750                 } else if (user.isRestricted()) {
    751                     onManageUserClicked(user.id, false);
    752                 }
    753             }
    754         } else if (pref == mAddUser) {
    755             showDialog(DIALOG_CHOOSE_USER_TYPE);
    756         }
    757         return false;
    758     }
    759 
    760     private boolean isInitialized(UserInfo user) {
    761         return (user.flags & UserInfo.FLAG_INITIALIZED) != 0;
    762     }
    763 
    764     private Drawable encircle(int iconResId) {
    765         Bitmap icon = BitmapFactory.decodeResource(getResources(), iconResId);
    766         return encircle(icon);
    767     }
    768 
    769     private Drawable encircle(Bitmap icon) {
    770         Drawable circled = CircleFramedDrawable.getInstance(getActivity(), icon);
    771         return circled;
    772     }
    773 
    774     @Override
    775     public void onClick(View v) {
    776         if (v.getTag() instanceof UserPreference) {
    777             int userId = ((UserPreference) v.getTag()).getUserId();
    778             switch (v.getId()) {
    779             case UserPreference.DELETE_ID:
    780                 onRemoveUserClicked(userId);
    781                 break;
    782             case UserPreference.SETTINGS_ID:
    783                 onManageUserClicked(userId, false);
    784                 break;
    785             }
    786         }
    787     }
    788 
    789     @Override
    790     public void onDismiss(DialogInterface dialog) {
    791         synchronized (mUserLock) {
    792             mAddingUser = false;
    793             mRemovingUserId = -1;
    794             updateUserList();
    795         }
    796     }
    797 
    798     @Override
    799     public boolean onPreferenceChange(Preference preference, Object newValue) {
    800         if (preference == mNicknamePreference) {
    801             String value = (String) newValue;
    802             if (preference == mNicknamePreference && value != null
    803                     && value.length() > 0) {
    804                 setUserName(value);
    805             }
    806             return true;
    807         }
    808         return false;
    809     }
    810 
    811     @Override
    812     public int getHelpResource() {
    813         return R.string.help_url_users;
    814     }
    815 }
    816