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