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