Home | History | Annotate | Download | only in users
      1 /*
      2  * Copyright (C) 2012 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.settings.users;
     18 
     19 import android.app.Activity;
     20 import android.app.ActivityManager;
     21 import android.app.AlertDialog;
     22 import android.app.Dialog;
     23 import android.app.admin.DevicePolicyManager;
     24 import android.content.BroadcastReceiver;
     25 import android.content.Context;
     26 import android.content.DialogInterface;
     27 import android.content.Intent;
     28 import android.content.IntentFilter;
     29 import android.content.SharedPreferences;
     30 import android.content.pm.UserInfo;
     31 import android.content.res.Resources;
     32 import android.graphics.Bitmap;
     33 import android.graphics.BitmapFactory;
     34 import android.graphics.drawable.Drawable;
     35 import android.net.Uri;
     36 import android.os.AsyncTask;
     37 import android.os.Bundle;
     38 import android.os.Handler;
     39 import android.os.Message;
     40 import android.os.RemoteException;
     41 import android.os.UserHandle;
     42 import android.os.UserManager;
     43 import android.provider.ContactsContract;
     44 import android.provider.SearchIndexableResource;
     45 import android.provider.Settings.Global;
     46 import android.support.annotation.VisibleForTesting;
     47 import android.support.annotation.WorkerThread;
     48 import android.support.v7.preference.Preference;
     49 import android.support.v7.preference.Preference.OnPreferenceClickListener;
     50 import android.support.v7.preference.PreferenceGroup;
     51 import android.support.v7.preference.PreferenceScreen;
     52 import android.util.Log;
     53 import android.util.SparseArray;
     54 import android.view.Menu;
     55 import android.view.MenuInflater;
     56 import android.view.MenuItem;
     57 import android.view.View;
     58 import android.view.View.OnClickListener;
     59 import android.widget.SimpleAdapter;
     60 
     61 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
     62 import com.android.internal.util.UserIcons;
     63 import com.android.internal.widget.LockPatternUtils;
     64 import com.android.settings.R;
     65 import com.android.settings.SettingsPreferenceFragment;
     66 import com.android.settings.Utils;
     67 import com.android.settings.core.SubSettingLauncher;
     68 import com.android.settings.dashboard.SummaryLoader;
     69 import com.android.settings.password.ChooseLockGeneric;
     70 import com.android.settings.search.BaseSearchIndexProvider;
     71 import com.android.settings.search.Indexable;
     72 import com.android.settingslib.RestrictedLockUtils;
     73 import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
     74 import com.android.settingslib.RestrictedPreference;
     75 import com.android.settingslib.drawable.CircleFramedDrawable;
     76 
     77 import java.io.IOException;
     78 import java.io.InputStream;
     79 import java.util.ArrayList;
     80 import java.util.Collections;
     81 import java.util.HashMap;
     82 import java.util.List;
     83 
     84 /**
     85  * Screen that manages the list of users on the device.
     86  * Guest user is an always visible entry, even if the guest is not currently
     87  * active/created. It is meant for controlling properties of a guest user.
     88  *
     89  * The first one is always the current user.
     90  * Owner is the primary user.
     91  */
     92 public class UserSettings extends SettingsPreferenceFragment
     93         implements OnPreferenceClickListener, OnClickListener, DialogInterface.OnDismissListener,
     94         EditUserInfoController.OnContentChangedCallback, Indexable {
     95 
     96     private static final String TAG = "UserSettings";
     97 
     98     /** UserId of the user being removed */
     99     private static final String SAVE_REMOVING_USER = "removing_user";
    100     /** UserId of the user that was just added */
    101     private static final String SAVE_ADDING_USER = "adding_user";
    102 
    103     private static final String KEY_USER_LIST = "user_list";
    104     private static final String KEY_USER_ME = "user_me";
    105     private static final String KEY_ADD_USER = "user_add";
    106     private static final String KEY_ADD_USER_WHEN_LOCKED = "user_settings_add_users_when_locked";
    107 
    108     private static final int MENU_REMOVE_USER = Menu.FIRST;
    109 
    110     private static final int DIALOG_CONFIRM_REMOVE = 1;
    111     private static final int DIALOG_ADD_USER = 2;
    112     private static final int DIALOG_SETUP_USER = 3;
    113     private static final int DIALOG_SETUP_PROFILE = 4;
    114     private static final int DIALOG_USER_CANNOT_MANAGE = 5;
    115     private static final int DIALOG_CHOOSE_USER_TYPE = 6;
    116     private static final int DIALOG_NEED_LOCKSCREEN = 7;
    117     private static final int DIALOG_CONFIRM_EXIT_GUEST = 8;
    118     private static final int DIALOG_USER_PROFILE_EDITOR = 9;
    119 
    120     private static final int MESSAGE_UPDATE_LIST = 1;
    121     private static final int MESSAGE_SETUP_USER = 2;
    122     private static final int MESSAGE_CONFIG_USER = 3;
    123 
    124     private static final int USER_TYPE_USER = 1;
    125     private static final int USER_TYPE_RESTRICTED_PROFILE = 2;
    126 
    127     private static final int REQUEST_CHOOSE_LOCK = 10;
    128 
    129     private static final String KEY_ADD_USER_LONG_MESSAGE_DISPLAYED =
    130             "key_add_user_long_message_displayed";
    131 
    132     private static final String KEY_TITLE = "title";
    133     private static final String KEY_SUMMARY = "summary";
    134 
    135     private PreferenceGroup mUserListCategory;
    136     private UserPreference mMePreference;
    137     private RestrictedPreference mAddUser;
    138     private int mRemovingUserId = -1;
    139     private int mAddedUserId = 0;
    140     private boolean mAddingUser;
    141     private String mAddingUserName;
    142     private UserCapabilities mUserCaps;
    143     private boolean mShouldUpdateUserList = true;
    144     private final Object mUserLock = new Object();
    145     private UserManager mUserManager;
    146     private SparseArray<Bitmap> mUserIcons = new SparseArray<>();
    147     private static SparseArray<Bitmap> sDarkDefaultUserBitmapCache = new SparseArray<>();
    148 
    149     private EditUserInfoController mEditUserInfoController = new EditUserInfoController();
    150     private AddUserWhenLockedPreferenceController mAddUserWhenLockedPreferenceController;
    151 
    152     // A place to cache the generated default avatar
    153     private Drawable mDefaultIconDrawable;
    154 
    155     private Handler mHandler = new Handler() {
    156         @Override
    157         public void handleMessage(Message msg) {
    158             switch (msg.what) {
    159                 case MESSAGE_UPDATE_LIST:
    160                     updateUserList();
    161                     break;
    162                 case MESSAGE_SETUP_USER:
    163                     onUserCreated(msg.arg1);
    164                     break;
    165                 case MESSAGE_CONFIG_USER:
    166                     onManageUserClicked(msg.arg1, true);
    167                     break;
    168             }
    169         }
    170     };
    171 
    172     private BroadcastReceiver mUserChangeReceiver = new BroadcastReceiver() {
    173         @Override
    174         public void onReceive(Context context, Intent intent) {
    175             if (intent.getAction().equals(Intent.ACTION_USER_REMOVED)) {
    176                 mRemovingUserId = -1;
    177             } else if (intent.getAction().equals(Intent.ACTION_USER_INFO_CHANGED)) {
    178                 int userHandle = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
    179                 if (userHandle != -1) {
    180                     mUserIcons.remove(userHandle);
    181                 }
    182             }
    183             mHandler.sendEmptyMessage(MESSAGE_UPDATE_LIST);
    184         }
    185     };
    186 
    187     @Override
    188     public int getMetricsCategory() {
    189         return MetricsEvent.USER;
    190     }
    191 
    192     @Override
    193     public void onCreate(Bundle icicle) {
    194         super.onCreate(icicle);
    195         addPreferencesFromResource(R.xml.user_settings);
    196         if (Global.getInt(getContext().getContentResolver(), Global.DEVICE_PROVISIONED, 0) == 0) {
    197             getActivity().finish();
    198             return;
    199         }
    200         final Context context = getActivity();
    201         mAddUserWhenLockedPreferenceController = new AddUserWhenLockedPreferenceController(
    202                 context, KEY_ADD_USER_WHEN_LOCKED, getLifecycle());
    203         final PreferenceScreen screen = getPreferenceScreen();
    204         mAddUserWhenLockedPreferenceController.displayPreference(screen);
    205 
    206         screen.findPreference(mAddUserWhenLockedPreferenceController.getPreferenceKey())
    207                 .setOnPreferenceChangeListener(mAddUserWhenLockedPreferenceController);
    208 
    209         if (icicle != null) {
    210             if (icicle.containsKey(SAVE_ADDING_USER)) {
    211                 mAddedUserId = icicle.getInt(SAVE_ADDING_USER);
    212             }
    213             if (icicle.containsKey(SAVE_REMOVING_USER)) {
    214                 mRemovingUserId = icicle.getInt(SAVE_REMOVING_USER);
    215             }
    216             mEditUserInfoController.onRestoreInstanceState(icicle);
    217         }
    218 
    219         mUserCaps = UserCapabilities.create(context);
    220         mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
    221         if (!mUserCaps.mEnabled) {
    222             return;
    223         }
    224 
    225         final int myUserId = UserHandle.myUserId();
    226 
    227         mUserListCategory = (PreferenceGroup) findPreference(KEY_USER_LIST);
    228         mMePreference = new UserPreference(getPrefContext(), null /* attrs */, myUserId,
    229                 null /* settings icon handler */,
    230                 null /* delete icon handler */);
    231         mMePreference.setKey(KEY_USER_ME);
    232         mMePreference.setOnPreferenceClickListener(this);
    233         if (mUserCaps.mIsAdmin) {
    234             mMePreference.setSummary(R.string.user_admin);
    235         }
    236         mAddUser = (RestrictedPreference) findPreference(KEY_ADD_USER);
    237         mAddUser.useAdminDisabledSummary(false);
    238         // Determine if add user/profile button should be visible
    239         if (mUserCaps.mCanAddUser && Utils.isDeviceProvisioned(getActivity())) {
    240             mAddUser.setVisible(true);
    241             mAddUser.setOnPreferenceClickListener(this);
    242             // change label to only mention user, if restricted profiles are not supported
    243             if (!mUserCaps.mCanAddRestrictedProfile) {
    244                 mAddUser.setTitle(R.string.user_add_user_menu);
    245             }
    246         } else {
    247             mAddUser.setVisible(false);
    248         }
    249         final IntentFilter filter = new IntentFilter(Intent.ACTION_USER_REMOVED);
    250         filter.addAction(Intent.ACTION_USER_INFO_CHANGED);
    251         context.registerReceiverAsUser(mUserChangeReceiver, UserHandle.ALL, filter, null, mHandler);
    252         loadProfile();
    253         updateUserList();
    254         mShouldUpdateUserList = false;
    255     }
    256 
    257     @Override
    258     public void onResume() {
    259         super.onResume();
    260 
    261         if (!mUserCaps.mEnabled) {
    262             return;
    263         }
    264         final PreferenceScreen screen = getPreferenceScreen();
    265 
    266         if (mAddUserWhenLockedPreferenceController.isAvailable()) {
    267             mAddUserWhenLockedPreferenceController.updateState(screen.findPreference(
    268                     mAddUserWhenLockedPreferenceController.getPreferenceKey()));
    269         }
    270 
    271         if (mShouldUpdateUserList) {
    272             mUserCaps.updateAddUserCapabilities(getActivity());
    273             loadProfile();
    274             updateUserList();
    275         }
    276     }
    277 
    278     @Override
    279     public void onPause() {
    280         mShouldUpdateUserList = true;
    281         super.onPause();
    282     }
    283 
    284     @Override
    285     public void onDestroy() {
    286         super.onDestroy();
    287 
    288         if (mUserCaps == null || !mUserCaps.mEnabled) {
    289             return;
    290         }
    291 
    292         getActivity().unregisterReceiver(mUserChangeReceiver);
    293     }
    294 
    295     @Override
    296     public void onSaveInstanceState(Bundle outState) {
    297         super.onSaveInstanceState(outState);
    298         mEditUserInfoController.onSaveInstanceState(outState);
    299         outState.putInt(SAVE_ADDING_USER, mAddedUserId);
    300         outState.putInt(SAVE_REMOVING_USER, mRemovingUserId);
    301     }
    302 
    303     @Override
    304     public void startActivityForResult(Intent intent, int requestCode) {
    305         mEditUserInfoController.startingActivityForResult();
    306         super.startActivityForResult(intent, requestCode);
    307     }
    308 
    309     @Override
    310     public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    311         int pos = 0;
    312         UserManager um = getContext().getSystemService(UserManager.class);
    313         boolean allowRemoveUser = !um.hasUserRestriction(UserManager.DISALLOW_REMOVE_USER);
    314         boolean canSwitchUsers = um.canSwitchUsers();
    315         if (!mUserCaps.mIsAdmin && allowRemoveUser && canSwitchUsers) {
    316             String nickname = mUserManager.getUserName();
    317             MenuItem removeThisUser = menu.add(0, MENU_REMOVE_USER, pos++,
    318                     getResources().getString(R.string.user_remove_user_menu, nickname));
    319             removeThisUser.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
    320         }
    321         super.onCreateOptionsMenu(menu, inflater);
    322     }
    323 
    324     @Override
    325     public boolean onOptionsItemSelected(MenuItem item) {
    326         final int itemId = item.getItemId();
    327         if (itemId == MENU_REMOVE_USER) {
    328             onRemoveUserClicked(UserHandle.myUserId());
    329             return true;
    330         } else {
    331             return super.onOptionsItemSelected(item);
    332         }
    333     }
    334 
    335     /**
    336      * Loads profile information for the current user.
    337      */
    338     private void loadProfile() {
    339         if (mUserCaps.mIsGuest) {
    340             // No need to load profile information
    341             mMePreference.setIcon(getEncircledDefaultIcon());
    342             mMePreference.setTitle(R.string.user_exit_guest_title);
    343             return;
    344         }
    345 
    346         new AsyncTask<Void, Void, String>() {
    347             @Override
    348             protected void onPostExecute(String result) {
    349                 finishLoadProfile(result);
    350             }
    351 
    352             @Override
    353             protected String doInBackground(Void... values) {
    354                 UserInfo user = mUserManager.getUserInfo(UserHandle.myUserId());
    355                 if (user.iconPath == null || user.iconPath.equals("")) {
    356                     // Assign profile photo.
    357                     copyMeProfilePhoto(getActivity(), user);
    358                 }
    359                 return user.name;
    360             }
    361         }.execute();
    362     }
    363 
    364     private void finishLoadProfile(String profileName) {
    365         if (getActivity() == null) return;
    366         mMePreference.setTitle(getString(R.string.user_you, profileName));
    367         int myUserId = UserHandle.myUserId();
    368         Bitmap b = mUserManager.getUserIcon(myUserId);
    369         if (b != null) {
    370             mMePreference.setIcon(encircle(b));
    371             mUserIcons.put(myUserId, b);
    372         }
    373     }
    374 
    375     private boolean hasLockscreenSecurity() {
    376         LockPatternUtils lpu = new LockPatternUtils(getActivity());
    377         return lpu.isSecure(UserHandle.myUserId());
    378     }
    379 
    380     private void launchChooseLockscreen() {
    381         Intent chooseLockIntent = new Intent(DevicePolicyManager.ACTION_SET_NEW_PASSWORD);
    382         chooseLockIntent.putExtra(ChooseLockGeneric.ChooseLockGenericFragment.MINIMUM_QUALITY_KEY,
    383                 DevicePolicyManager.PASSWORD_QUALITY_SOMETHING);
    384         startActivityForResult(chooseLockIntent, REQUEST_CHOOSE_LOCK);
    385     }
    386 
    387     @Override
    388     public void onActivityResult(int requestCode, int resultCode, Intent data) {
    389         super.onActivityResult(requestCode, resultCode, data);
    390 
    391         if (requestCode == REQUEST_CHOOSE_LOCK) {
    392             if (resultCode != Activity.RESULT_CANCELED && hasLockscreenSecurity()) {
    393                 addUserNow(USER_TYPE_RESTRICTED_PROFILE);
    394             }
    395         } else {
    396             mEditUserInfoController.onActivityResult(requestCode, resultCode, data);
    397         }
    398     }
    399 
    400     private void onAddUserClicked(int userType) {
    401         synchronized (mUserLock) {
    402             if (mRemovingUserId == -1 && !mAddingUser) {
    403                 switch (userType) {
    404                     case USER_TYPE_USER:
    405                         showDialog(DIALOG_ADD_USER);
    406                         break;
    407                     case USER_TYPE_RESTRICTED_PROFILE:
    408                         if (hasLockscreenSecurity()) {
    409                             addUserNow(USER_TYPE_RESTRICTED_PROFILE);
    410                         } else {
    411                             showDialog(DIALOG_NEED_LOCKSCREEN);
    412                         }
    413                         break;
    414                 }
    415             }
    416         }
    417     }
    418 
    419     private void onRemoveUserClicked(int userId) {
    420         synchronized (mUserLock) {
    421             if (mRemovingUserId == -1 && !mAddingUser) {
    422                 mRemovingUserId = userId;
    423                 showDialog(DIALOG_CONFIRM_REMOVE);
    424             }
    425         }
    426     }
    427 
    428     private UserInfo createRestrictedProfile() {
    429         UserInfo newUserInfo = mUserManager.createRestrictedProfile(mAddingUserName);
    430         if (newUserInfo != null && !assignDefaultPhoto(getActivity(), newUserInfo.id)) {
    431             return null;
    432         }
    433         return newUserInfo;
    434     }
    435 
    436     private UserInfo createTrustedUser() {
    437         UserInfo newUserInfo = mUserManager.createUser(mAddingUserName, 0);
    438         if (newUserInfo != null && !assignDefaultPhoto(getActivity(), newUserInfo.id)) {
    439             return null;
    440         }
    441         return newUserInfo;
    442     }
    443 
    444     private void onManageUserClicked(int userId, boolean newUser) {
    445         mAddingUser = false;
    446         if (userId == UserPreference.USERID_GUEST_DEFAULTS) {
    447             Bundle extras = new Bundle();
    448             extras.putBoolean(UserDetailsSettings.EXTRA_USER_GUEST, true);
    449             new SubSettingLauncher(getContext())
    450                     .setDestination(UserDetailsSettings.class.getName())
    451                     .setArguments(extras)
    452                     .setTitle(R.string.user_guest)
    453                     .setSourceMetricsCategory(getMetricsCategory())
    454                     .launch();
    455             return;
    456         }
    457         UserInfo info = mUserManager.getUserInfo(userId);
    458         if (info.isRestricted() && mUserCaps.mIsAdmin) {
    459             Bundle extras = new Bundle();
    460             extras.putInt(RestrictedProfileSettings.EXTRA_USER_ID, userId);
    461             extras.putBoolean(RestrictedProfileSettings.EXTRA_NEW_USER, newUser);
    462             new SubSettingLauncher(getContext())
    463                     .setDestination(RestrictedProfileSettings.class.getName())
    464                     .setArguments(extras)
    465                     .setTitle(R.string.user_restrictions_title)
    466                     .setSourceMetricsCategory(getMetricsCategory())
    467                     .launch();
    468         } else if (info.id == UserHandle.myUserId()) {
    469             // Jump to owner info panel
    470             OwnerInfoSettings.show(this);
    471         } else if (mUserCaps.mIsAdmin) {
    472             final Bundle extras = new Bundle();
    473             extras.putInt(UserDetailsSettings.EXTRA_USER_ID, userId);
    474             new SubSettingLauncher(getContext())
    475                     .setDestination(UserDetailsSettings.class.getName())
    476                     .setArguments(extras)
    477                     .setTitle(info.name)
    478                     .setSourceMetricsCategory(getMetricsCategory())
    479                     .launch();
    480         }
    481     }
    482 
    483     private void onUserCreated(int userId) {
    484         mAddedUserId = userId;
    485         mAddingUser = false;
    486         if (!isResumed()) {
    487             Log.w(TAG, "Cannot show dialog after onPause");
    488             return;
    489         }
    490         if (mUserManager.getUserInfo(userId).isRestricted()) {
    491             showDialog(DIALOG_SETUP_PROFILE);
    492         } else {
    493             showDialog(DIALOG_SETUP_USER);
    494         }
    495     }
    496 
    497     @Override
    498     public void onDialogShowing() {
    499         super.onDialogShowing();
    500 
    501         setOnDismissListener(this);
    502     }
    503 
    504     @Override
    505     public Dialog onCreateDialog(int dialogId) {
    506         Context context = getActivity();
    507         if (context == null) return null;
    508         switch (dialogId) {
    509             case DIALOG_CONFIRM_REMOVE: {
    510                 Dialog dlg =
    511                         UserDialogs.createRemoveDialog(getActivity(), mRemovingUserId,
    512                                 new DialogInterface.OnClickListener() {
    513                                     public void onClick(DialogInterface dialog, int which) {
    514                                         removeUserNow();
    515                                     }
    516                                 }
    517                         );
    518                 return dlg;
    519             }
    520             case DIALOG_USER_CANNOT_MANAGE:
    521                 return new AlertDialog.Builder(context)
    522                         .setMessage(R.string.user_cannot_manage_message)
    523                         .setPositiveButton(android.R.string.ok, null)
    524                         .create();
    525             case DIALOG_ADD_USER: {
    526                 final SharedPreferences preferences = getActivity().getPreferences(
    527                         Context.MODE_PRIVATE);
    528                 final boolean longMessageDisplayed = preferences.getBoolean(
    529                         KEY_ADD_USER_LONG_MESSAGE_DISPLAYED, false);
    530                 final int messageResId = longMessageDisplayed
    531                         ? R.string.user_add_user_message_short
    532                         : R.string.user_add_user_message_long;
    533                 final int userType = dialogId == DIALOG_ADD_USER
    534                         ? USER_TYPE_USER : USER_TYPE_RESTRICTED_PROFILE;
    535                 Dialog dlg = new AlertDialog.Builder(context)
    536                         .setTitle(R.string.user_add_user_title)
    537                         .setMessage(messageResId)
    538                         .setPositiveButton(android.R.string.ok,
    539                                 new DialogInterface.OnClickListener() {
    540                                     public void onClick(DialogInterface dialog, int which) {
    541                                         addUserNow(userType);
    542                                         if (!longMessageDisplayed) {
    543                                             preferences.edit().putBoolean(
    544                                                     KEY_ADD_USER_LONG_MESSAGE_DISPLAYED,
    545                                                     true).apply();
    546                                         }
    547                                     }
    548                                 })
    549                         .setNegativeButton(android.R.string.cancel, null)
    550                         .create();
    551                 return dlg;
    552             }
    553             case DIALOG_SETUP_USER: {
    554                 Dialog dlg = new AlertDialog.Builder(context)
    555                         .setTitle(R.string.user_setup_dialog_title)
    556                         .setMessage(R.string.user_setup_dialog_message)
    557                         .setPositiveButton(R.string.user_setup_button_setup_now,
    558                                 new DialogInterface.OnClickListener() {
    559                                     public void onClick(DialogInterface dialog, int which) {
    560                                         switchUserNow(mAddedUserId);
    561                                     }
    562                                 })
    563                         .setNegativeButton(R.string.user_setup_button_setup_later, null)
    564                         .create();
    565                 return dlg;
    566             }
    567             case DIALOG_SETUP_PROFILE: {
    568                 Dialog dlg = new AlertDialog.Builder(context)
    569                         .setMessage(R.string.user_setup_profile_dialog_message)
    570                         .setPositiveButton(android.R.string.ok,
    571                                 new DialogInterface.OnClickListener() {
    572                                     public void onClick(DialogInterface dialog, int which) {
    573                                         switchUserNow(mAddedUserId);
    574                                     }
    575                                 })
    576                         .setNegativeButton(android.R.string.cancel, null)
    577                         .create();
    578                 return dlg;
    579             }
    580             case DIALOG_CHOOSE_USER_TYPE: {
    581                 List<HashMap<String, String>> data = new ArrayList<HashMap<String, String>>();
    582                 HashMap<String, String> addUserItem = new HashMap<String, String>();
    583                 addUserItem.put(KEY_TITLE, getString(R.string.user_add_user_item_title));
    584                 addUserItem.put(KEY_SUMMARY, getString(R.string.user_add_user_item_summary));
    585                 HashMap<String, String> addProfileItem = new HashMap<String, String>();
    586                 addProfileItem.put(KEY_TITLE, getString(R.string.user_add_profile_item_title));
    587                 addProfileItem.put(KEY_SUMMARY, getString(R.string.user_add_profile_item_summary));
    588                 data.add(addUserItem);
    589                 data.add(addProfileItem);
    590                 AlertDialog.Builder builder = new AlertDialog.Builder(context);
    591                 SimpleAdapter adapter = new SimpleAdapter(builder.getContext(),
    592                         data, R.layout.two_line_list_item,
    593                         new String[] {KEY_TITLE, KEY_SUMMARY},
    594                         new int[] {R.id.title, R.id.summary});
    595                 builder.setTitle(R.string.user_add_user_type_title);
    596                 builder.setAdapter(adapter,
    597                         new DialogInterface.OnClickListener() {
    598                             @Override
    599                             public void onClick(DialogInterface dialog, int which) {
    600                                 onAddUserClicked(which == 0
    601                                         ? USER_TYPE_USER
    602                                         : USER_TYPE_RESTRICTED_PROFILE);
    603                             }
    604                         });
    605                 return builder.create();
    606             }
    607             case DIALOG_NEED_LOCKSCREEN: {
    608                 Dialog dlg = new AlertDialog.Builder(context)
    609                         .setMessage(R.string.user_need_lock_message)
    610                         .setPositiveButton(R.string.user_set_lock_button,
    611                                 new DialogInterface.OnClickListener() {
    612                                     @Override
    613                                     public void onClick(DialogInterface dialog, int which) {
    614                                         launchChooseLockscreen();
    615                                     }
    616                                 })
    617                         .setNegativeButton(android.R.string.cancel, null)
    618                         .create();
    619                 return dlg;
    620             }
    621             case DIALOG_CONFIRM_EXIT_GUEST: {
    622                 Dialog dlg = new AlertDialog.Builder(context)
    623                         .setTitle(R.string.user_exit_guest_confirm_title)
    624                         .setMessage(R.string.user_exit_guest_confirm_message)
    625                         .setPositiveButton(R.string.user_exit_guest_dialog_remove,
    626                                 new DialogInterface.OnClickListener() {
    627                                     @Override
    628                                     public void onClick(DialogInterface dialog, int which) {
    629                                         exitGuest();
    630                                     }
    631                                 })
    632                         .setNegativeButton(android.R.string.cancel, null)
    633                         .create();
    634                 return dlg;
    635             }
    636             case DIALOG_USER_PROFILE_EDITOR: {
    637                 Dialog dlg = mEditUserInfoController.createDialog(
    638                         this,
    639                         null,
    640                         mMePreference.getTitle(),
    641                         R.string.profile_info_settings_title,
    642                         this /* callback */,
    643                         android.os.Process.myUserHandle());
    644                 return dlg;
    645             }
    646             default:
    647                 return null;
    648         }
    649     }
    650 
    651     @Override
    652     public int getDialogMetricsCategory(int dialogId) {
    653         switch (dialogId) {
    654             case DIALOG_CONFIRM_REMOVE:
    655                 return MetricsEvent.DIALOG_USER_REMOVE;
    656             case DIALOG_USER_CANNOT_MANAGE:
    657                 return MetricsEvent.DIALOG_USER_CANNOT_MANAGE;
    658             case DIALOG_ADD_USER:
    659                 return MetricsEvent.DIALOG_USER_ADD;
    660             case DIALOG_SETUP_USER:
    661                 return MetricsEvent.DIALOG_USER_SETUP;
    662             case DIALOG_SETUP_PROFILE:
    663                 return MetricsEvent.DIALOG_USER_SETUP_PROFILE;
    664             case DIALOG_CHOOSE_USER_TYPE:
    665                 return MetricsEvent.DIALOG_USER_CHOOSE_TYPE;
    666             case DIALOG_NEED_LOCKSCREEN:
    667                 return MetricsEvent.DIALOG_USER_NEED_LOCKSCREEN;
    668             case DIALOG_CONFIRM_EXIT_GUEST:
    669                 return MetricsEvent.DIALOG_USER_CONFIRM_EXIT_GUEST;
    670             case DIALOG_USER_PROFILE_EDITOR:
    671                 return MetricsEvent.DIALOG_USER_EDIT_PROFILE;
    672             default:
    673                 return 0;
    674         }
    675     }
    676 
    677     private void removeUserNow() {
    678         if (mRemovingUserId == UserHandle.myUserId()) {
    679             removeThisUser();
    680         } else {
    681             new Thread() {
    682                 public void run() {
    683                     synchronized (mUserLock) {
    684                         mUserManager.removeUser(mRemovingUserId);
    685                         mHandler.sendEmptyMessage(MESSAGE_UPDATE_LIST);
    686                     }
    687                 }
    688             }.start();
    689         }
    690     }
    691 
    692     private void removeThisUser() {
    693         if (!mUserManager.canSwitchUsers()) {
    694             Log.w(TAG, "Cannot remove current user when switching is disabled");
    695             return;
    696         }
    697         try {
    698             ActivityManager.getService().switchUser(UserHandle.USER_SYSTEM);
    699             getContext().getSystemService(UserManager.class).removeUser(UserHandle.myUserId());
    700         } catch (RemoteException re) {
    701             Log.e(TAG, "Unable to remove self user");
    702         }
    703     }
    704 
    705     private void addUserNow(final int userType) {
    706         synchronized (mUserLock) {
    707             mAddingUser = true;
    708             mAddingUserName = userType == USER_TYPE_USER ? getString(R.string.user_new_user_name)
    709                     : getString(R.string.user_new_profile_name);
    710             //updateUserList();
    711             new Thread() {
    712                 public void run() {
    713                     UserInfo user;
    714                     // Could take a few seconds
    715                     if (userType == USER_TYPE_USER) {
    716                         user = createTrustedUser();
    717                     } else {
    718                         user = createRestrictedProfile();
    719                     }
    720                     if (user == null) {
    721                         mAddingUser = false;
    722                         return;
    723                     }
    724                     synchronized (mUserLock) {
    725                         if (userType == USER_TYPE_USER) {
    726                             mHandler.sendEmptyMessage(MESSAGE_UPDATE_LIST);
    727                             // Skip setting up user which results in user switching when the
    728                             // restriction is set.
    729                             if (!mUserCaps.mDisallowSwitchUser) {
    730                                 mHandler.sendMessage(mHandler.obtainMessage(
    731                                         MESSAGE_SETUP_USER, user.id, user.serialNumber));
    732                             }
    733                         } else {
    734                             mHandler.sendMessage(mHandler.obtainMessage(
    735                                     MESSAGE_CONFIG_USER, user.id, user.serialNumber));
    736                         }
    737                     }
    738                 }
    739             }.start();
    740         }
    741     }
    742 
    743     private void switchUserNow(int userId) {
    744         try {
    745             ActivityManager.getService().switchUser(userId);
    746         } catch (RemoteException re) {
    747             // Nothing to do
    748         }
    749     }
    750 
    751     /**
    752      * Erase the current user (guest) and switch to another user.
    753      */
    754     private void exitGuest() {
    755         // Just to be safe
    756         if (!mUserCaps.mIsGuest) {
    757             return;
    758         }
    759         removeThisUser();
    760     }
    761 
    762     private void updateUserList() {
    763         if (getActivity() == null) return;
    764         List<UserInfo> users = mUserManager.getUsers(true);
    765         final Context context = getActivity();
    766 
    767         final boolean voiceCapable = Utils.isVoiceCapable(context);
    768         final ArrayList<Integer> missingIcons = new ArrayList<>();
    769         final ArrayList<UserPreference> userPreferences = new ArrayList<>();
    770         int guestId = UserPreference.USERID_GUEST_DEFAULTS;
    771         userPreferences.add(mMePreference);
    772 
    773         for (UserInfo user : users) {
    774             if (!user.supportsSwitchToByUser()) {
    775                 // Only users that can be switched to should show up here.
    776                 // e.g. Managed profiles appear under Accounts Settings instead
    777                 continue;
    778             }
    779             UserPreference pref;
    780             if (user.id == UserHandle.myUserId()) {
    781                 pref = mMePreference;
    782             } else if (user.isGuest()) {
    783                 // Skip over Guest. We add generic Guest settings after this loop
    784                 guestId = user.id;
    785                 continue;
    786             } else {
    787                 // With Telephony:
    788                 //   Secondary user: Settings
    789                 //   Guest: Settings
    790                 //   Restricted Profile: There is no Restricted Profile
    791                 // Without Telephony:
    792                 //   Secondary user: Delete
    793                 //   Guest: Nothing
    794                 //   Restricted Profile: Settings
    795                 final boolean showSettings = mUserCaps.mIsAdmin
    796                         && (voiceCapable || user.isRestricted());
    797                 final boolean showDelete = mUserCaps.mIsAdmin
    798                         && (!voiceCapable && !user.isRestricted() && !user.isGuest());
    799                 pref = new UserPreference(getPrefContext(), null, user.id,
    800                         showSettings ? this : null,
    801                         showDelete ? this : null);
    802                 pref.setKey("id=" + user.id);
    803                 userPreferences.add(pref);
    804                 if (user.isAdmin()) {
    805                     pref.setSummary(R.string.user_admin);
    806                 }
    807                 pref.setTitle(user.name);
    808                 pref.setSelectable(false);
    809             }
    810             if (pref == null) {
    811                 continue;
    812             }
    813             if (!isInitialized(user)) {
    814                 if (user.isRestricted()) {
    815                     pref.setSummary(R.string.user_summary_restricted_not_set_up);
    816                 } else {
    817                     pref.setSummary(R.string.user_summary_not_set_up);
    818                 }
    819                 // Disallow setting up user which results in user switching when the restriction is
    820                 // set.
    821                 if (!mUserCaps.mDisallowSwitchUser) {
    822                     pref.setOnPreferenceClickListener(this);
    823                     pref.setSelectable(true);
    824                 }
    825             } else if (user.isRestricted()) {
    826                 pref.setSummary(R.string.user_summary_restricted_profile);
    827             }
    828             if (user.iconPath != null) {
    829                 if (mUserIcons.get(user.id) == null) {
    830                     // Icon not loaded yet, print a placeholder
    831                     missingIcons.add(user.id);
    832                     pref.setIcon(getEncircledDefaultIcon());
    833                 } else {
    834                     setPhotoId(pref, user);
    835                 }
    836             } else {
    837                 // Icon not available yet, print a placeholder
    838                 pref.setIcon(getEncircledDefaultIcon());
    839             }
    840         }
    841 
    842         // Add a temporary entry for the user being created
    843         if (mAddingUser) {
    844             UserPreference pref = new UserPreference(getPrefContext(), null,
    845                     UserPreference.USERID_UNKNOWN, null, null);
    846             pref.setEnabled(false);
    847             pref.setTitle(mAddingUserName);
    848             pref.setIcon(getEncircledDefaultIcon());
    849             userPreferences.add(pref);
    850         }
    851 
    852         // Check if Guest tile should be added.
    853         if (!mUserCaps.mIsGuest && (mUserCaps.mCanAddGuest ||
    854                 mUserCaps.mDisallowAddUserSetByAdmin)) {
    855             // Add a virtual Guest user for guest defaults
    856             UserPreference pref = new UserPreference(getPrefContext(), null,
    857                     UserPreference.USERID_GUEST_DEFAULTS,
    858                     mUserCaps.mIsAdmin && voiceCapable ? this : null /* settings icon handler */,
    859                     null /* delete icon handler */);
    860             pref.setTitle(R.string.user_guest);
    861             pref.setIcon(getEncircledDefaultIcon());
    862             userPreferences.add(pref);
    863             if (mUserCaps.mDisallowAddUser) {
    864                 pref.setDisabledByAdmin(mUserCaps.mEnforcedAdmin);
    865             } else if (mUserCaps.mDisallowSwitchUser) {
    866                 pref.setDisabledByAdmin(RestrictedLockUtils.getDeviceOwner(context));
    867             } else {
    868                 pref.setDisabledByAdmin(null);
    869             }
    870             int finalGuestId = guestId;
    871             pref.setOnPreferenceClickListener(preference -> {
    872                 int id = finalGuestId;
    873                 if (id == UserPreference.USERID_GUEST_DEFAULTS) {
    874                     UserInfo guest = mUserManager.createGuest(
    875                             getContext(), preference.getTitle().toString());
    876                     if (guest != null) {
    877                         id = guest.id;
    878                     }
    879                 }
    880                 try {
    881                     ActivityManager.getService().switchUser(id);
    882                 } catch (RemoteException e) {
    883                     e.rethrowFromSystemServer();
    884                 }
    885                 return true;
    886             });
    887         }
    888 
    889         // Sort list of users by serialNum
    890         Collections.sort(userPreferences, UserPreference.SERIAL_NUMBER_COMPARATOR);
    891 
    892         getActivity().invalidateOptionsMenu();
    893 
    894         // Load the icons
    895         if (missingIcons.size() > 0) {
    896             loadIconsAsync(missingIcons);
    897         }
    898 
    899         // Remove everything from mUserListCategory and add new users.
    900         mUserListCategory.removeAll();
    901         // If profiles are supported, mUserListCategory will have a special title
    902         if (mUserCaps.mCanAddRestrictedProfile) {
    903             mUserListCategory.setTitle(R.string.user_list_title);
    904         } else {
    905             mUserListCategory.setTitle(null);
    906         }
    907 
    908         for (UserPreference userPreference : userPreferences) {
    909             userPreference.setOrder(Preference.DEFAULT_ORDER);
    910             mUserListCategory.addPreference(userPreference);
    911         }
    912 
    913         // Append Add user to the end of the list
    914         if ((mUserCaps.mCanAddUser || mUserCaps.mDisallowAddUserSetByAdmin) &&
    915                 Utils.isDeviceProvisioned(getActivity())) {
    916             boolean moreUsers = mUserManager.canAddMoreUsers();
    917             mAddUser.setEnabled(moreUsers && !mAddingUser);
    918             if (!moreUsers) {
    919                 mAddUser.setSummary(getString(R.string.user_add_max_count, getMaxRealUsers()));
    920             } else {
    921                 mAddUser.setSummary(null);
    922             }
    923             if (mAddUser.isEnabled()) {
    924                 mAddUser.setDisabledByAdmin(
    925                         mUserCaps.mDisallowAddUser ? mUserCaps.mEnforcedAdmin : null);
    926             }
    927         }
    928 
    929     }
    930 
    931     private int getMaxRealUsers() {
    932         // guest is not counted against getMaxSupportedUsers() number
    933         final int maxUsersAndGuest = UserManager.getMaxSupportedUsers() + 1;
    934         final List<UserInfo> users = mUserManager.getUsers();
    935         // managed profiles are counted against getMaxSupportedUsers()
    936         int managedProfiles = 0;
    937         for (UserInfo user : users) {
    938             if (user.isManagedProfile()) {
    939                 managedProfiles++;
    940             }
    941         }
    942         return maxUsersAndGuest - managedProfiles;
    943     }
    944 
    945     private void loadIconsAsync(List<Integer> missingIcons) {
    946         new AsyncTask<List<Integer>, Void, Void>() {
    947             @Override
    948             protected void onPostExecute(Void result) {
    949                 updateUserList();
    950             }
    951 
    952             @Override
    953             protected Void doInBackground(List<Integer>... values) {
    954                 for (int userId : values[0]) {
    955                     Bitmap bitmap = mUserManager.getUserIcon(userId);
    956                     if (bitmap == null) {
    957                         bitmap = getDefaultUserIconAsBitmap(getContext().getResources(), userId);
    958                     }
    959                     mUserIcons.append(userId, bitmap);
    960                 }
    961                 return null;
    962             }
    963         }.execute(missingIcons);
    964     }
    965 
    966     private Drawable getEncircledDefaultIcon() {
    967         if (mDefaultIconDrawable == null) {
    968             mDefaultIconDrawable = encircle(
    969                     getDefaultUserIconAsBitmap(getContext().getResources(), UserHandle.USER_NULL));
    970         }
    971         return mDefaultIconDrawable;
    972     }
    973 
    974     private void setPhotoId(Preference pref, UserInfo user) {
    975         Bitmap bitmap = mUserIcons.get(user.id);
    976         if (bitmap != null) {
    977             pref.setIcon(encircle(bitmap));
    978         }
    979     }
    980 
    981     @Override
    982     public boolean onPreferenceClick(Preference pref) {
    983         if (pref == mMePreference) {
    984             if (mUserCaps.mIsGuest) {
    985                 showDialog(DIALOG_CONFIRM_EXIT_GUEST);
    986                 return true;
    987             }
    988             // If this is a limited user, launch the user info settings instead of profile editor
    989             if (mUserManager.isLinkedUser()) {
    990                 onManageUserClicked(UserHandle.myUserId(), false);
    991             } else {
    992                 showDialog(DIALOG_USER_PROFILE_EDITOR);
    993             }
    994         } else if (pref instanceof UserPreference) {
    995             int userId = ((UserPreference) pref).getUserId();
    996             // Get the latest status of the user
    997             UserInfo user = mUserManager.getUserInfo(userId);
    998             if (!isInitialized(user)) {
    999                 mHandler.sendMessage(mHandler.obtainMessage(
   1000                         MESSAGE_SETUP_USER, user.id, user.serialNumber));
   1001             }
   1002         } else if (pref == mAddUser) {
   1003             // If we allow both types, show a picker, otherwise directly go to
   1004             // flow for full user.
   1005             if (mUserCaps.mCanAddRestrictedProfile) {
   1006                 showDialog(DIALOG_CHOOSE_USER_TYPE);
   1007             } else {
   1008                 onAddUserClicked(USER_TYPE_USER);
   1009             }
   1010         }
   1011         return false;
   1012     }
   1013 
   1014     private boolean isInitialized(UserInfo user) {
   1015         return (user.flags & UserInfo.FLAG_INITIALIZED) != 0;
   1016     }
   1017 
   1018     private Drawable encircle(Bitmap icon) {
   1019         Drawable circled = CircleFramedDrawable.getInstance(getActivity(), icon);
   1020         return circled;
   1021     }
   1022 
   1023     @Override
   1024     public void onClick(View v) {
   1025         if (v.getTag() instanceof UserPreference) {
   1026             int userId = ((UserPreference) v.getTag()).getUserId();
   1027             switch (v.getId()) {
   1028                 case UserPreference.DELETE_ID:
   1029                     final EnforcedAdmin removeDisallowedAdmin =
   1030                             RestrictedLockUtils.checkIfRestrictionEnforced(getContext(),
   1031                                     UserManager.DISALLOW_REMOVE_USER, UserHandle.myUserId());
   1032                     if (removeDisallowedAdmin != null) {
   1033                         RestrictedLockUtils.sendShowAdminSupportDetailsIntent(getContext(),
   1034                                 removeDisallowedAdmin);
   1035                     } else {
   1036                         onRemoveUserClicked(userId);
   1037                     }
   1038                     break;
   1039                 case UserPreference.SETTINGS_ID:
   1040                     onManageUserClicked(userId, false);
   1041                     break;
   1042             }
   1043         }
   1044     }
   1045 
   1046     @Override
   1047     public void onDismiss(DialogInterface dialog) {
   1048         synchronized (mUserLock) {
   1049             mRemovingUserId = -1;
   1050             updateUserList();
   1051         }
   1052     }
   1053 
   1054     @Override
   1055     public int getHelpResource() {
   1056         return R.string.help_url_users;
   1057     }
   1058 
   1059     @Override
   1060     public void onPhotoChanged(Drawable photo) {
   1061         mMePreference.setIcon(photo);
   1062     }
   1063 
   1064     @Override
   1065     public void onLabelChanged(CharSequence label) {
   1066         mMePreference.setTitle(label);
   1067     }
   1068 
   1069     /**
   1070      * Returns a default user icon (as a {@link Bitmap}) for the given user.
   1071      *
   1072      * Note that for guest users, you should pass in {@code UserHandle.USER_NULL}.
   1073      *
   1074      * @param resources resources object to fetch the user icon.
   1075      * @param userId    the user id or {@code UserHandle.USER_NULL} for a non-user specific icon
   1076      */
   1077     private static Bitmap getDefaultUserIconAsBitmap(Resources resources, int userId) {
   1078         Bitmap bitmap = null;
   1079         // Try finding the corresponding bitmap in the dark bitmap cache
   1080         bitmap = sDarkDefaultUserBitmapCache.get(userId);
   1081         if (bitmap == null) {
   1082             bitmap = UserIcons.convertToBitmap(
   1083                     UserIcons.getDefaultUserIcon(resources, userId, false));
   1084             // Save it to cache
   1085             sDarkDefaultUserBitmapCache.put(userId, bitmap);
   1086         }
   1087         return bitmap;
   1088     }
   1089 
   1090     /**
   1091      * Assign the default photo to user with {@paramref userId}
   1092      *
   1093      * @param context used to get the {@link UserManager}
   1094      * @param userId  used to get the icon bitmap
   1095      * @return true if assign photo successfully, false if failed
   1096      */
   1097     @VisibleForTesting
   1098     static boolean assignDefaultPhoto(Context context, int userId) {
   1099         if (context == null) {
   1100             return false;
   1101         }
   1102         UserManager um = (UserManager) context.getSystemService(Context.USER_SERVICE);
   1103         Bitmap bitmap = getDefaultUserIconAsBitmap(context.getResources(), userId);
   1104         um.setUserIcon(userId, bitmap);
   1105 
   1106         return true;
   1107     }
   1108 
   1109     @WorkerThread
   1110     static void copyMeProfilePhoto(Context context, UserInfo user) {
   1111         Uri contactUri = ContactsContract.Profile.CONTENT_URI;
   1112 
   1113         int userId = user != null ? user.id : UserHandle.myUserId();
   1114 
   1115         InputStream avatarDataStream = ContactsContract.Contacts.openContactPhotoInputStream(
   1116                 context.getContentResolver(),
   1117                 contactUri, true);
   1118         // If there's no profile photo, assign a default avatar
   1119         if (avatarDataStream == null) {
   1120             assignDefaultPhoto(context, userId);
   1121             return;
   1122         }
   1123 
   1124         UserManager um = (UserManager) context.getSystemService(Context.USER_SERVICE);
   1125         Bitmap icon = BitmapFactory.decodeStream(avatarDataStream);
   1126         um.setUserIcon(userId, icon);
   1127         try {
   1128             avatarDataStream.close();
   1129         } catch (IOException ioe) {
   1130         }
   1131     }
   1132 
   1133     private static class SummaryProvider implements SummaryLoader.SummaryProvider {
   1134 
   1135         private final Context mContext;
   1136         private final SummaryLoader mSummaryLoader;
   1137 
   1138         public SummaryProvider(Context context, SummaryLoader summaryLoader) {
   1139             mContext = context;
   1140             mSummaryLoader = summaryLoader;
   1141         }
   1142 
   1143         @Override
   1144         public void setListening(boolean listening) {
   1145             if (listening) {
   1146                 UserInfo info = mContext.getSystemService(UserManager.class).getUserInfo(
   1147                         UserHandle.myUserId());
   1148                 mSummaryLoader.setSummary(this, mContext.getString(R.string.users_summary,
   1149                         info.name));
   1150             }
   1151         }
   1152     }
   1153 
   1154     public static final SummaryLoader.SummaryProviderFactory SUMMARY_PROVIDER_FACTORY =
   1155             (activity, summaryLoader) -> new SummaryProvider(activity, summaryLoader);
   1156 
   1157     public static final Indexable.SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
   1158             new BaseSearchIndexProvider() {
   1159 
   1160                 @Override
   1161                 protected boolean isPageSearchEnabled(Context context) {
   1162                     final UserCapabilities userCaps = UserCapabilities.create(context);
   1163                     return userCaps.mEnabled;
   1164                 }
   1165 
   1166                 @Override
   1167                 public List<SearchIndexableResource> getXmlResourcesToIndex(Context context,
   1168                         boolean enabled) {
   1169                     final List<SearchIndexableResource> index = new ArrayList<>();
   1170                     // Append the rest of the settings
   1171                     final SearchIndexableResource sir = new SearchIndexableResource(context);
   1172                     sir.xmlResId = R.xml.user_settings;
   1173                     index.add(sir);
   1174                     return index;
   1175                 }
   1176 
   1177                 @Override
   1178                 public List<String> getNonIndexableKeysFromXml(Context context, int xmlResId) {
   1179                     final List<String> niks = super.getNonIndexableKeysFromXml(context, xmlResId);
   1180                     new AddUserWhenLockedPreferenceController(
   1181                             context, KEY_ADD_USER_WHEN_LOCKED, null /* lifecycle */)
   1182                             .updateNonIndexableKeys(niks);
   1183                     new AutoSyncDataPreferenceController(context, null /* parent */)
   1184                             .updateNonIndexableKeys(niks);
   1185                     new AutoSyncPersonalDataPreferenceController(context, null /* parent */)
   1186                             .updateNonIndexableKeys(niks);
   1187                     new AutoSyncWorkDataPreferenceController(context, null /* parent */)
   1188                             .updateNonIndexableKeys(niks);
   1189                     return niks;
   1190                 }
   1191             };
   1192 
   1193 }
   1194