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