blob: 6a9bb098f10d923e9d89d12a027166a4a6ddb45b [file] [log] [blame]
Amith Yamasanib810a0d2012-03-25 10:12:26 -07001/*
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
17package com.android.settings.users;
18
Amith Yamasanif162efe2013-04-29 10:43:05 -070019import android.app.Activity;
Amith Yamasaniae47ef42012-09-16 17:53:35 -070020import android.app.ActivityManagerNative;
Amith Yamasanidc6bfa62012-09-06 18:04:06 -070021import android.app.AlertDialog;
22import android.app.Dialog;
Amith Yamasanif162efe2013-04-29 10:43:05 -070023import android.app.admin.DevicePolicyManager;
Amith Yamasanidc6bfa62012-09-06 18:04:06 -070024import android.content.BroadcastReceiver;
Amith Yamasani32630392012-08-10 19:31:39 -070025import android.content.Context;
Amith Yamasanidc6bfa62012-09-06 18:04:06 -070026import android.content.DialogInterface;
27import android.content.Intent;
28import android.content.IntentFilter;
Svetoslav Ganov263f7442012-09-25 16:11:16 -070029import android.content.SharedPreferences;
Amith Yamasanib810a0d2012-03-25 10:12:26 -070030import android.content.pm.UserInfo;
Amith Yamasani5cdc9372012-11-14 16:23:40 -080031import android.content.res.Resources;
Amith Yamasanidc6bfa62012-09-06 18:04:06 -070032import android.graphics.Bitmap;
Amith Yamasani48fa8572012-04-17 17:12:01 -070033import android.graphics.drawable.Drawable;
Amith Yamasani32dccbc2012-09-13 18:06:49 -070034import android.os.AsyncTask;
Amith Yamasanib810a0d2012-03-25 10:12:26 -070035import android.os.Bundle;
Amith Yamasanidc6bfa62012-09-06 18:04:06 -070036import android.os.Handler;
37import android.os.Message;
Amith Yamasaniae47ef42012-09-16 17:53:35 -070038import android.os.RemoteException;
Amith Yamasanidc6bfa62012-09-06 18:04:06 -070039import android.os.UserHandle;
Amith Yamasani32630392012-08-10 19:31:39 -070040import android.os.UserManager;
Amith Yamasani247520c2014-07-25 12:52:29 -070041import android.provider.Settings;
Jason Monk39b46742015-09-10 15:52:51 -040042import android.support.v7.preference.Preference;
43import android.support.v7.preference.Preference.OnPreferenceClickListener;
44import android.support.v7.preference.PreferenceGroup;
45import android.support.v7.preference.PreferenceScreen;
Amith Yamasanidc6bfa62012-09-06 18:04:06 -070046import android.util.Log;
Amith Yamasanif34a85d2012-09-17 18:31:45 -070047import android.util.SparseArray;
Amith Yamasanib810a0d2012-03-25 10:12:26 -070048import android.view.Menu;
49import android.view.MenuInflater;
50import android.view.MenuItem;
Amith Yamasanidc6bfa62012-09-06 18:04:06 -070051import android.view.View;
52import android.view.View.OnClickListener;
Amith Yamasanifc8a3832013-04-23 11:44:59 -070053import android.widget.SimpleAdapter;
Amith Yamasanib810a0d2012-03-25 10:12:26 -070054
Chris Wren8a963ba2015-03-20 10:29:14 -040055import com.android.internal.logging.MetricsLogger;
Amith Yamasanif162efe2013-04-29 10:43:05 -070056import com.android.internal.widget.LockPatternUtils;
57import com.android.settings.ChooseLockGeneric;
Amith Yamasanid4abdd22013-04-17 18:27:01 -070058import com.android.settings.OwnerInfoSettings;
Amith Yamasanib810a0d2012-03-25 10:12:26 -070059import com.android.settings.R;
Amith Yamasani9627a8e2012-09-23 12:54:14 -070060import com.android.settings.SelectableEditTextPreference;
Fabrice Di Meglio263bcc82014-01-17 19:17:58 -080061import com.android.settings.SettingsActivity;
Julia Reynoldsb9195d22014-06-11 16:18:16 -040062import com.android.settings.SettingsPreferenceFragment;
Amith Yamasaniae47ef42012-09-16 17:53:35 -070063import com.android.settings.Utils;
Fyodor Kupolovc9a95ef2015-05-15 17:16:15 -070064import com.android.settings.search.BaseSearchIndexProvider;
65import com.android.settings.search.Indexable;
66import com.android.settings.search.SearchIndexableRaw;
Wei Liu6e58d512015-08-24 17:29:04 -070067import com.android.settingslib.drawable.CircleFramedDrawable;
Amith Yamasanib810a0d2012-03-25 10:12:26 -070068
Alexandra Gherghinabc6e78f2014-09-03 10:22:09 +010069import java.util.ArrayList;
Fyodor Kupolov55145092014-12-08 14:15:36 -080070import java.util.Collections;
Alexandra Gherghinabc6e78f2014-09-03 10:22:09 +010071import java.util.HashMap;
72import java.util.List;
73
Amith Yamasaniee398742014-07-24 14:13:36 -070074/**
75 * Screen that manages the list of users on the device.
76 * Guest user is an always visible entry, even if the guest is not currently
77 * active/created. It is meant for controlling properties of a guest user.
78 *
79 * The first one is always the current user.
80 * Owner is the primary user.
81 */
Julia Reynoldsb9195d22014-06-11 16:18:16 -040082public class UserSettings extends SettingsPreferenceFragment
Amith Yamasanidc6bfa62012-09-06 18:04:06 -070083 implements OnPreferenceClickListener, OnClickListener, DialogInterface.OnDismissListener,
Amith Yamasaniee398742014-07-24 14:13:36 -070084 Preference.OnPreferenceChangeListener,
Fyodor Kupolovc9a95ef2015-05-15 17:16:15 -070085 EditUserInfoController.OnContentChangedCallback, Indexable {
Amith Yamasanib810a0d2012-03-25 10:12:26 -070086
Amith Yamasanidc6bfa62012-09-06 18:04:06 -070087 private static final String TAG = "UserSettings";
88
Amith Yamasanic861cf82012-10-02 14:51:46 -070089 /** UserId of the user being removed */
90 private static final String SAVE_REMOVING_USER = "removing_user";
91 /** UserId of the user that was just added */
92 private static final String SAVE_ADDING_USER = "adding_user";
93
Amith Yamasanifc8a3832013-04-23 11:44:59 -070094 private static final String KEY_USER_LIST = "user_list";
Amith Yamasanidc6bfa62012-09-06 18:04:06 -070095 private static final String KEY_USER_ME = "user_me";
Amith Yamasanifc8a3832013-04-23 11:44:59 -070096 private static final String KEY_ADD_USER = "user_add";
Amith Yamasanidc6bfa62012-09-06 18:04:06 -070097
Amith Yamasanicc395692013-04-11 18:21:07 -070098 private static final int MENU_REMOVE_USER = Menu.FIRST;
Amith Yamasani247520c2014-07-25 12:52:29 -070099 private static final int MENU_ADD_ON_LOCKSCREEN = Menu.FIRST + 1;
Amith Yamasanidc6bfa62012-09-06 18:04:06 -0700100
101 private static final int DIALOG_CONFIRM_REMOVE = 1;
Amith Yamasanifc8a3832013-04-23 11:44:59 -0700102 private static final int DIALOG_ADD_USER = 2;
103 private static final int DIALOG_SETUP_USER = 3;
104 private static final int DIALOG_SETUP_PROFILE = 4;
Amith Yamasanicc395692013-04-11 18:21:07 -0700105 private static final int DIALOG_USER_CANNOT_MANAGE = 5;
Amith Yamasanifc8a3832013-04-23 11:44:59 -0700106 private static final int DIALOG_CHOOSE_USER_TYPE = 6;
Amith Yamasanif162efe2013-04-29 10:43:05 -0700107 private static final int DIALOG_NEED_LOCKSCREEN = 7;
Amith Yamasanic16b73e2014-07-17 19:13:51 -0700108 private static final int DIALOG_CONFIRM_EXIT_GUEST = 8;
Amith Yamasaniee398742014-07-24 14:13:36 -0700109 private static final int DIALOG_USER_PROFILE_EDITOR = 9;
Amith Yamasanidc6bfa62012-09-06 18:04:06 -0700110
111 private static final int MESSAGE_UPDATE_LIST = 1;
Amith Yamasaniae47ef42012-09-16 17:53:35 -0700112 private static final int MESSAGE_SETUP_USER = 2;
Amith Yamasanicc395692013-04-11 18:21:07 -0700113 private static final int MESSAGE_CONFIG_USER = 3;
114
Amith Yamasanifc8a3832013-04-23 11:44:59 -0700115 private static final int USER_TYPE_USER = 1;
116 private static final int USER_TYPE_RESTRICTED_PROFILE = 2;
Amith Yamasanidc6bfa62012-09-06 18:04:06 -0700117
Amith Yamasanif162efe2013-04-29 10:43:05 -0700118 private static final int REQUEST_CHOOSE_LOCK = 10;
119
Svetoslav Ganov263f7442012-09-25 16:11:16 -0700120 private static final String KEY_ADD_USER_LONG_MESSAGE_DISPLAYED =
121 "key_add_user_long_message_displayed";
122
Amith Yamasanifc8a3832013-04-23 11:44:59 -0700123 private static final String KEY_TITLE = "title";
124 private static final String KEY_SUMMARY = "summary";
125
126 private PreferenceGroup mUserListCategory;
Fyodor Kupolov55145092014-12-08 14:15:36 -0800127 private UserPreference mMePreference;
Amith Yamasani9627a8e2012-09-23 12:54:14 -0700128 private SelectableEditTextPreference mNicknamePreference;
Amith Yamasanifc8a3832013-04-23 11:44:59 -0700129 private Preference mAddUser;
Amith Yamasanidc6bfa62012-09-06 18:04:06 -0700130 private int mRemovingUserId = -1;
Amith Yamasaniae47ef42012-09-16 17:53:35 -0700131 private int mAddedUserId = 0;
Amith Yamasanidc6bfa62012-09-06 18:04:06 -0700132 private boolean mAddingUser;
Fyodor Kupolovc9a95ef2015-05-15 17:16:15 -0700133 private UserCapabilities mUserCaps;
Amith Yamasanidc6bfa62012-09-06 18:04:06 -0700134
135 private final Object mUserLock = new Object();
136 private UserManager mUserManager;
Amith Yamasani864e3b72013-03-27 12:27:01 -0700137 private SparseArray<Bitmap> mUserIcons = new SparseArray<Bitmap>();
Amith Yamasani8666b9e2012-09-27 14:50:13 -0700138
Amith Yamasaniee398742014-07-24 14:13:36 -0700139 private EditUserInfoController mEditUserInfoController =
140 new EditUserInfoController();
141
Amith Yamasanic16b73e2014-07-17 19:13:51 -0700142 // A place to cache the generated default avatar
Alexandra Gherghinabc6e78f2014-09-03 10:22:09 +0100143 private Drawable mDefaultIconDrawable;
Amith Yamasanic16b73e2014-07-17 19:13:51 -0700144
Amith Yamasanidc6bfa62012-09-06 18:04:06 -0700145 private Handler mHandler = new Handler() {
146 @Override
147 public void handleMessage(Message msg) {
148 switch (msg.what) {
149 case MESSAGE_UPDATE_LIST:
150 updateUserList();
151 break;
Amith Yamasaniae47ef42012-09-16 17:53:35 -0700152 case MESSAGE_SETUP_USER:
153 onUserCreated(msg.arg1);
154 break;
Amith Yamasanicc395692013-04-11 18:21:07 -0700155 case MESSAGE_CONFIG_USER:
156 onManageUserClicked(msg.arg1, true);
157 break;
Amith Yamasanidc6bfa62012-09-06 18:04:06 -0700158 }
159 }
160 };
161
Amith Yamasanidc6bfa62012-09-06 18:04:06 -0700162 private BroadcastReceiver mUserChangeReceiver = new BroadcastReceiver() {
Amith Yamasanidc6bfa62012-09-06 18:04:06 -0700163 @Override
164 public void onReceive(Context context, Intent intent) {
Amith Yamasanif34a85d2012-09-17 18:31:45 -0700165 if (intent.getAction().equals(Intent.ACTION_USER_REMOVED)) {
166 mRemovingUserId = -1;
167 } else if (intent.getAction().equals(Intent.ACTION_USER_INFO_CHANGED)) {
168 int userHandle = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
169 if (userHandle != -1) {
170 mUserIcons.remove(userHandle);
171 }
172 }
Amith Yamasanidc6bfa62012-09-06 18:04:06 -0700173 mHandler.sendEmptyMessage(MESSAGE_UPDATE_LIST);
174 }
175 };
Amith Yamasanib810a0d2012-03-25 10:12:26 -0700176
177 @Override
Chris Wren8a963ba2015-03-20 10:29:14 -0400178 protected int getMetricsCategory() {
179 return MetricsLogger.USER;
180 }
181
182 @Override
Amith Yamasanib810a0d2012-03-25 10:12:26 -0700183 public void onCreate(Bundle icicle) {
184 super.onCreate(icicle);
Amith Yamasani8666b9e2012-09-27 14:50:13 -0700185
Amith Yamasanic861cf82012-10-02 14:51:46 -0700186 if (icicle != null) {
187 if (icicle.containsKey(SAVE_ADDING_USER)) {
188 mAddedUserId = icicle.getInt(SAVE_ADDING_USER);
189 }
190 if (icicle.containsKey(SAVE_REMOVING_USER)) {
191 mRemovingUserId = icicle.getInt(SAVE_REMOVING_USER);
192 }
Amith Yamasaniee398742014-07-24 14:13:36 -0700193 mEditUserInfoController.onRestoreInstanceState(icicle);
Amith Yamasanic861cf82012-10-02 14:51:46 -0700194 }
Amith Yamasani0e43d322014-05-07 10:19:34 -0700195 final Context context = getActivity();
Fyodor Kupolovc9a95ef2015-05-15 17:16:15 -0700196 mUserCaps = UserCapabilities.create(context);
Amith Yamasani0e43d322014-05-07 10:19:34 -0700197 mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
Fyodor Kupolovc9a95ef2015-05-15 17:16:15 -0700198 if (!mUserCaps.mEnabled) {
Amith Yamasanicfb8d7f2014-03-26 14:46:47 -0700199 return;
200 }
Amith Yamasani0e43d322014-05-07 10:19:34 -0700201
Amith Yamasani9e6ac3d2014-06-30 15:31:37 +0530202 final int myUserId = UserHandle.myUserId();
Amith Yamasani9e6ac3d2014-06-30 15:31:37 +0530203
Amith Yamasanib810a0d2012-03-25 10:12:26 -0700204 addPreferencesFromResource(R.xml.user_settings);
Amith Yamasanifc8a3832013-04-23 11:44:59 -0700205 mUserListCategory = (PreferenceGroup) findPreference(KEY_USER_LIST);
Jason Monk39b46742015-09-10 15:52:51 -0400206 mMePreference = new UserPreference(getPrefContext(), null /* attrs */, myUserId,
Amith Yamasaniee398742014-07-24 14:13:36 -0700207 null /* settings icon handler */,
Amith Yamasanic16b73e2014-07-17 19:13:51 -0700208 null /* delete icon handler */);
Amith Yamasanid4abdd22013-04-17 18:27:01 -0700209 mMePreference.setKey(KEY_USER_ME);
Amith Yamasanidc6bfa62012-09-06 18:04:06 -0700210 mMePreference.setOnPreferenceClickListener(this);
Xiaohui Chen64f530c2015-06-24 12:35:07 -0700211 if (mUserCaps.mIsAdmin) {
212 mMePreference.setSummary(R.string.user_admin);
Amith Yamasanidc6bfa62012-09-06 18:04:06 -0700213 }
Amith Yamasanifc8a3832013-04-23 11:44:59 -0700214 mAddUser = findPreference(KEY_ADD_USER);
Fyodor Kupolov55145092014-12-08 14:15:36 -0800215 // Determine if add user/profile button should be visible
Fyodor Kupolovc9a95ef2015-05-15 17:16:15 -0700216 if (mUserCaps.mCanAddUser) {
Amith Yamasani0e43d322014-05-07 10:19:34 -0700217 mAddUser.setOnPreferenceClickListener(this);
Fyodor Kupolov55145092014-12-08 14:15:36 -0800218 // change label to only mention user, if restricted profiles are not supported
Fyodor Kupolovc9a95ef2015-05-15 17:16:15 -0700219 if (!mUserCaps.mCanAddRestrictedProfile) {
Amith Yamasani0e43d322014-05-07 10:19:34 -0700220 mAddUser.setTitle(R.string.user_add_user_menu);
221 }
Amith Yamasani233592b2013-03-01 17:05:23 -0800222 }
Amith Yamasani32dccbc2012-09-13 18:06:49 -0700223 loadProfile();
Amith Yamasanib810a0d2012-03-25 10:12:26 -0700224 setHasOptionsMenu(true);
Amith Yamasanif34a85d2012-09-17 18:31:45 -0700225 IntentFilter filter = new IntentFilter(Intent.ACTION_USER_REMOVED);
226 filter.addAction(Intent.ACTION_USER_INFO_CHANGED);
Amith Yamasani9e6ac3d2014-06-30 15:31:37 +0530227 context.registerReceiverAsUser(mUserChangeReceiver, UserHandle.ALL, filter, null,
Amith Yamasanif34a85d2012-09-17 18:31:45 -0700228 mHandler);
Amith Yamasani0ca80fe2013-06-03 16:41:03 -0700229 }
230
231 @Override
232 public void onResume() {
233 super.onResume();
Amith Yamasanicfb8d7f2014-03-26 14:46:47 -0700234
Fyodor Kupolovc9a95ef2015-05-15 17:16:15 -0700235 if (!mUserCaps.mEnabled) return;
Amith Yamasanicfb8d7f2014-03-26 14:46:47 -0700236
Amith Yamasani0ca80fe2013-06-03 16:41:03 -0700237 loadProfile();
Amith Yamasanib810a0d2012-03-25 10:12:26 -0700238 updateUserList();
239 }
240
241 @Override
Amith Yamasanidc6bfa62012-09-06 18:04:06 -0700242 public void onDestroy() {
243 super.onDestroy();
Amith Yamasanicfb8d7f2014-03-26 14:46:47 -0700244
Fyodor Kupolovc9a95ef2015-05-15 17:16:15 -0700245 if (!mUserCaps.mEnabled) return;
Amith Yamasanicfb8d7f2014-03-26 14:46:47 -0700246
Amith Yamasanidc6bfa62012-09-06 18:04:06 -0700247 getActivity().unregisterReceiver(mUserChangeReceiver);
248 }
249
250 @Override
Amith Yamasanic861cf82012-10-02 14:51:46 -0700251 public void onSaveInstanceState(Bundle outState) {
252 super.onSaveInstanceState(outState);
Amith Yamasaniee398742014-07-24 14:13:36 -0700253 mEditUserInfoController.onSaveInstanceState(outState);
Amith Yamasanic861cf82012-10-02 14:51:46 -0700254 outState.putInt(SAVE_ADDING_USER, mAddedUserId);
255 outState.putInt(SAVE_REMOVING_USER, mRemovingUserId);
256 }
257
258 @Override
Amith Yamasaniee398742014-07-24 14:13:36 -0700259 public void startActivityForResult(Intent intent, int requestCode) {
260 mEditUserInfoController.startingActivityForResult();
261 super.startActivityForResult(intent, requestCode);
262 }
263
264 @Override
Amith Yamasanib810a0d2012-03-25 10:12:26 -0700265 public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
Amith Yamasani247520c2014-07-25 12:52:29 -0700266 int pos = 0;
Emily Bernier11bd33a2013-04-11 16:24:56 -0400267 UserManager um = (UserManager) getActivity().getSystemService(Context.USER_SERVICE);
Xiaohui Chen64f530c2015-06-24 12:35:07 -0700268 if (!mUserCaps.mIsAdmin && !um.hasUserRestriction(UserManager.DISALLOW_REMOVE_USER)) {
Amith Yamasani1a634d32012-09-27 23:01:35 -0700269 String nickname = mUserManager.getUserName();
Amith Yamasani247520c2014-07-25 12:52:29 -0700270 MenuItem removeThisUser = menu.add(0, MENU_REMOVE_USER, pos++,
Amith Yamasani1a634d32012-09-27 23:01:35 -0700271 getResources().getString(R.string.user_remove_user_menu, nickname));
272 removeThisUser.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
Amith Yamasanidc6bfa62012-09-06 18:04:06 -0700273 }
Xiaohui Chen64f530c2015-06-24 12:35:07 -0700274 if (mUserCaps.mIsAdmin && !um.hasUserRestriction(UserManager.DISALLOW_ADD_USER)) {
Amith Yamasani247520c2014-07-25 12:52:29 -0700275 MenuItem allowAddOnLockscreen = menu.add(0, MENU_ADD_ON_LOCKSCREEN, pos++,
276 R.string.user_add_on_lockscreen_menu);
277 allowAddOnLockscreen.setCheckable(true);
278 allowAddOnLockscreen.setChecked(Settings.Global.getInt(getContentResolver(),
279 Settings.Global.ADD_USERS_WHEN_LOCKED, 0) == 1);
280 }
Amith Yamasani38223dc2012-09-18 09:51:07 -0700281 super.onCreateOptionsMenu(menu, inflater);
Amith Yamasanib810a0d2012-03-25 10:12:26 -0700282 }
283
284 @Override
285 public boolean onOptionsItemSelected(MenuItem item) {
286 final int itemId = item.getItemId();
Amith Yamasanicc395692013-04-11 18:21:07 -0700287 if (itemId == MENU_REMOVE_USER) {
Amith Yamasanidc6bfa62012-09-06 18:04:06 -0700288 onRemoveUserClicked(UserHandle.myUserId());
289 return true;
Amith Yamasani247520c2014-07-25 12:52:29 -0700290 } else if (itemId == MENU_ADD_ON_LOCKSCREEN) {
291 final boolean isChecked = item.isChecked();
292 Settings.Global.putInt(getContentResolver(), Settings.Global.ADD_USERS_WHEN_LOCKED,
293 isChecked ? 0 : 1);
294 item.setChecked(!isChecked);
295 return true;
Amith Yamasanib810a0d2012-03-25 10:12:26 -0700296 } else {
297 return super.onOptionsItemSelected(item);
298 }
299 }
300
Amith Yamasanic16b73e2014-07-17 19:13:51 -0700301 /**
302 * Loads profile information for the current user.
303 */
Amith Yamasani32dccbc2012-09-13 18:06:49 -0700304 private void loadProfile() {
Fyodor Kupolovc9a95ef2015-05-15 17:16:15 -0700305 if (mUserCaps.mIsGuest) {
Amith Yamasanic16b73e2014-07-17 19:13:51 -0700306 // No need to load profile information
Alexandra Gherghinabc6e78f2014-09-03 10:22:09 +0100307 mMePreference.setIcon(getEncircledDefaultIcon());
Amith Yamasanic16b73e2014-07-17 19:13:51 -0700308 mMePreference.setTitle(R.string.user_exit_guest_title);
309 return;
310 }
311
Amith Yamasani32dccbc2012-09-13 18:06:49 -0700312 new AsyncTask<Void, Void, String>() {
313 @Override
314 protected void onPostExecute(String result) {
315 finishLoadProfile(result);
316 }
317
318 @Override
319 protected String doInBackground(Void... values) {
320 UserInfo user = mUserManager.getUserInfo(UserHandle.myUserId());
321 if (user.iconPath == null || user.iconPath.equals("")) {
322 assignProfilePhoto(user);
323 }
Amith Yamasani2d578ce2014-07-25 09:37:33 -0700324 return user.name;
Amith Yamasani32dccbc2012-09-13 18:06:49 -0700325 }
326 }.execute();
327 }
328
329 private void finishLoadProfile(String profileName) {
Amith Yamasanifc8a3832013-04-23 11:44:59 -0700330 if (getActivity() == null) return;
331 mMePreference.setTitle(getString(R.string.user_you, profileName));
Amith Yamasanif34a85d2012-09-17 18:31:45 -0700332 int myUserId = UserHandle.myUserId();
333 Bitmap b = mUserManager.getUserIcon(myUserId);
334 if (b != null) {
Amith Yamasani864e3b72013-03-27 12:27:01 -0700335 mMePreference.setIcon(encircle(b));
336 mUserIcons.put(myUserId, b);
Amith Yamasanif34a85d2012-09-17 18:31:45 -0700337 }
Amith Yamasanidc6bfa62012-09-06 18:04:06 -0700338 }
339
Amith Yamasanif162efe2013-04-29 10:43:05 -0700340 private boolean hasLockscreenSecurity() {
341 LockPatternUtils lpu = new LockPatternUtils(getActivity());
Adrian Roos54375882015-04-16 17:11:22 -0700342 return lpu.isSecure(UserHandle.myUserId());
Amith Yamasanif162efe2013-04-29 10:43:05 -0700343 }
344
345 private void launchChooseLockscreen() {
346 Intent chooseLockIntent = new Intent(DevicePolicyManager.ACTION_SET_NEW_PASSWORD);
347 chooseLockIntent.putExtra(ChooseLockGeneric.ChooseLockGenericFragment.MINIMUM_QUALITY_KEY,
348 DevicePolicyManager.PASSWORD_QUALITY_SOMETHING);
349 startActivityForResult(chooseLockIntent, REQUEST_CHOOSE_LOCK);
350 }
351
352 @Override
353 public void onActivityResult(int requestCode, int resultCode, Intent data) {
354 super.onActivityResult(requestCode, resultCode, data);
355
356 if (requestCode == REQUEST_CHOOSE_LOCK) {
357 if (resultCode != Activity.RESULT_CANCELED && hasLockscreenSecurity()) {
358 addUserNow(USER_TYPE_RESTRICTED_PROFILE);
Amith Yamasanif162efe2013-04-29 10:43:05 -0700359 }
Amith Yamasaniee398742014-07-24 14:13:36 -0700360 } else {
361 mEditUserInfoController.onActivityResult(requestCode, resultCode, data);
Amith Yamasanif162efe2013-04-29 10:43:05 -0700362 }
363 }
364
Amith Yamasanicc395692013-04-11 18:21:07 -0700365 private void onAddUserClicked(int userType) {
Amith Yamasanidc6bfa62012-09-06 18:04:06 -0700366 synchronized (mUserLock) {
367 if (mRemovingUserId == -1 && !mAddingUser) {
Amith Yamasanicc395692013-04-11 18:21:07 -0700368 switch (userType) {
Amith Yamasanifc8a3832013-04-23 11:44:59 -0700369 case USER_TYPE_USER:
370 showDialog(DIALOG_ADD_USER);
Amith Yamasanicc395692013-04-11 18:21:07 -0700371 break;
Amith Yamasanifc8a3832013-04-23 11:44:59 -0700372 case USER_TYPE_RESTRICTED_PROFILE:
Amith Yamasanif162efe2013-04-29 10:43:05 -0700373 if (hasLockscreenSecurity()) {
374 addUserNow(USER_TYPE_RESTRICTED_PROFILE);
375 } else {
376 showDialog(DIALOG_NEED_LOCKSCREEN);
377 }
Amith Yamasanicc395692013-04-11 18:21:07 -0700378 break;
379 }
Amith Yamasanidc6bfa62012-09-06 18:04:06 -0700380 }
381 }
382 }
383
384 private void onRemoveUserClicked(int userId) {
385 synchronized (mUserLock) {
386 if (mRemovingUserId == -1 && !mAddingUser) {
387 mRemovingUserId = userId;
388 showDialog(DIALOG_CONFIRM_REMOVE);
Amith Yamasanidc6bfa62012-09-06 18:04:06 -0700389 }
390 }
391 }
392
Fyodor Kupolov9938f6f2015-08-26 17:24:09 -0700393 private UserInfo createRestrictedProfile() {
394 UserInfo newUserInfo = mUserManager.createRestrictedProfile(
395 getResources().getString(R.string.user_new_profile_name));
Alexandra Gherghinabc6e78f2014-09-03 10:22:09 +0100396 assignDefaultPhoto(newUserInfo);
Amith Yamasanicc395692013-04-11 18:21:07 -0700397 return newUserInfo;
398 }
399
400 private UserInfo createTrustedUser() {
Xiaohui Chen8ae46802015-07-16 14:31:41 -0700401 UserInfo newUserInfo = mUserManager.createUser(
Amith Yamasanifc8a3832013-04-23 11:44:59 -0700402 getResources().getString(R.string.user_new_user_name), 0);
Amith Yamasanicc395692013-04-11 18:21:07 -0700403 if (newUserInfo != null) {
404 assignDefaultPhoto(newUserInfo);
405 }
406 return newUserInfo;
407 }
408
409 private void onManageUserClicked(int userId, boolean newUser) {
Amith Yamasani9e6ac3d2014-06-30 15:31:37 +0530410 if (userId == UserPreference.USERID_GUEST_DEFAULTS) {
411 Bundle extras = new Bundle();
412 extras.putBoolean(UserDetailsSettings.EXTRA_USER_GUEST, true);
413 ((SettingsActivity) getActivity()).startPreferencePanel(
414 UserDetailsSettings.class.getName(),
415 extras, R.string.user_guest, null, null, 0);
416 return;
417 }
Amith Yamasanid4abdd22013-04-17 18:27:01 -0700418 UserInfo info = mUserManager.getUserInfo(userId);
Xiaohui Chen64f530c2015-06-24 12:35:07 -0700419 if (info.isRestricted() && mUserCaps.mIsAdmin) {
Amith Yamasanid4abdd22013-04-17 18:27:01 -0700420 Bundle extras = new Bundle();
Amith Yamasani0ca80fe2013-06-03 16:41:03 -0700421 extras.putInt(RestrictedProfileSettings.EXTRA_USER_ID, userId);
422 extras.putBoolean(RestrictedProfileSettings.EXTRA_NEW_USER, newUser);
Fabrice Di Meglio263bcc82014-01-17 19:17:58 -0800423 ((SettingsActivity) getActivity()).startPreferencePanel(
Amith Yamasani0ca80fe2013-06-03 16:41:03 -0700424 RestrictedProfileSettings.class.getName(),
Amith Yamasani7c4dfcc2013-05-22 12:51:30 -0700425 extras, R.string.user_restrictions_title, null,
Amith Yamasanid4abdd22013-04-17 18:27:01 -0700426 null, 0);
427 } else if (info.id == UserHandle.myUserId()) {
428 // Jump to owner info panel
Jason Monk3bcd76c2015-04-21 11:20:20 -0400429 OwnerInfoSettings.show(this);
Xiaohui Chen64f530c2015-06-24 12:35:07 -0700430 } else if (mUserCaps.mIsAdmin) {
Amith Yamasani9e6ac3d2014-06-30 15:31:37 +0530431 Bundle extras = new Bundle();
432 extras.putInt(UserDetailsSettings.EXTRA_USER_ID, userId);
433 ((SettingsActivity) getActivity()).startPreferencePanel(
434 UserDetailsSettings.class.getName(),
Amith Yamasani51c6dac2014-07-02 00:06:37 +0530435 extras,
436 -1, /* No title res id */
437 info.name, /* title */
438 null, /* resultTo */
439 0 /* resultRequestCode */);
Amith Yamasanicc395692013-04-11 18:21:07 -0700440 }
Amith Yamasani233592b2013-03-01 17:05:23 -0800441 }
442
Amith Yamasaniae47ef42012-09-16 17:53:35 -0700443 private void onUserCreated(int userId) {
444 mAddedUserId = userId;
Amith Yamasanifc8a3832013-04-23 11:44:59 -0700445 if (mUserManager.getUserInfo(userId).isRestricted()) {
446 showDialog(DIALOG_SETUP_PROFILE);
447 } else {
448 showDialog(DIALOG_SETUP_USER);
449 }
Amith Yamasaniae47ef42012-09-16 17:53:35 -0700450 }
451
Amith Yamasanidc6bfa62012-09-06 18:04:06 -0700452 @Override
Amith Yamasanic861cf82012-10-02 14:51:46 -0700453 public void onDialogShowing() {
454 super.onDialogShowing();
455
456 setOnDismissListener(this);
457 }
458
459 @Override
Amith Yamasanidc6bfa62012-09-06 18:04:06 -0700460 public Dialog onCreateDialog(int dialogId) {
Amith Yamasanifc8a3832013-04-23 11:44:59 -0700461 Context context = getActivity();
462 if (context == null) return null;
Amith Yamasanidc6bfa62012-09-06 18:04:06 -0700463 switch (dialogId) {
Amith Yamasanic861cf82012-10-02 14:51:46 -0700464 case DIALOG_CONFIRM_REMOVE: {
Amith Yamasani9e6ac3d2014-06-30 15:31:37 +0530465 Dialog dlg =
Fyodor Kupolovdbbd4fc2014-12-29 13:40:27 -0800466 UserDialogs.createRemoveDialog(getActivity(), mRemovingUserId,
Amith Yamasani9e6ac3d2014-06-30 15:31:37 +0530467 new DialogInterface.OnClickListener() {
468 public void onClick(DialogInterface dialog, int which) {
469 removeUserNow();
470 }
471 }
472 );
Amith Yamasanic861cf82012-10-02 14:51:46 -0700473 return dlg;
474 }
Amith Yamasani1a634d32012-09-27 23:01:35 -0700475 case DIALOG_USER_CANNOT_MANAGE:
Amith Yamasanifc8a3832013-04-23 11:44:59 -0700476 return new AlertDialog.Builder(context)
Amith Yamasani1a634d32012-09-27 23:01:35 -0700477 .setMessage(R.string.user_cannot_manage_message)
478 .setPositiveButton(android.R.string.ok, null)
479 .create();
Amith Yamasanifc8a3832013-04-23 11:44:59 -0700480 case DIALOG_ADD_USER: {
Svetoslav Ganov263f7442012-09-25 16:11:16 -0700481 final SharedPreferences preferences = getActivity().getPreferences(
482 Context.MODE_PRIVATE);
483 final boolean longMessageDisplayed = preferences.getBoolean(
484 KEY_ADD_USER_LONG_MESSAGE_DISPLAYED, false);
485 final int messageResId = longMessageDisplayed
486 ? R.string.user_add_user_message_short
487 : R.string.user_add_user_message_long;
Amith Yamasanifc8a3832013-04-23 11:44:59 -0700488 final int userType = dialogId == DIALOG_ADD_USER
489 ? USER_TYPE_USER : USER_TYPE_RESTRICTED_PROFILE;
490 Dialog dlg = new AlertDialog.Builder(context)
491 .setTitle(R.string.user_add_user_title)
492 .setMessage(messageResId)
493 .setPositiveButton(android.R.string.ok,
494 new DialogInterface.OnClickListener() {
495 public void onClick(DialogInterface dialog, int which) {
496 addUserNow(userType);
497 if (!longMessageDisplayed) {
498 preferences.edit().putBoolean(
499 KEY_ADD_USER_LONG_MESSAGE_DISPLAYED, true).apply();
500 }
Svetoslav Ganov263f7442012-09-25 16:11:16 -0700501 }
Amith Yamasanifc8a3832013-04-23 11:44:59 -0700502 })
503 .setNegativeButton(android.R.string.cancel, null)
504 .create();
Amith Yamasanic861cf82012-10-02 14:51:46 -0700505 return dlg;
506 }
507 case DIALOG_SETUP_USER: {
Amith Yamasanifc8a3832013-04-23 11:44:59 -0700508 Dialog dlg = new AlertDialog.Builder(context)
509 .setTitle(R.string.user_setup_dialog_title)
510 .setMessage(R.string.user_setup_dialog_message)
511 .setPositiveButton(R.string.user_setup_button_setup_now,
512 new DialogInterface.OnClickListener() {
513 public void onClick(DialogInterface dialog, int which) {
514 switchUserNow(mAddedUserId);
515 }
516 })
517 .setNegativeButton(R.string.user_setup_button_setup_later, null)
518 .create();
519 return dlg;
520 }
521 case DIALOG_SETUP_PROFILE: {
522 Dialog dlg = new AlertDialog.Builder(context)
523 .setMessage(R.string.user_setup_profile_dialog_message)
524 .setPositiveButton(android.R.string.ok,
525 new DialogInterface.OnClickListener() {
526 public void onClick(DialogInterface dialog, int which) {
527 switchUserNow(mAddedUserId);
528 }
529 })
530 .setNegativeButton(android.R.string.cancel, null)
531 .create();
532 return dlg;
533 }
534 case DIALOG_CHOOSE_USER_TYPE: {
535 List<HashMap<String, String>> data = new ArrayList<HashMap<String,String>>();
536 HashMap<String,String> addUserItem = new HashMap<String,String>();
537 addUserItem.put(KEY_TITLE, getString(R.string.user_add_user_item_title));
538 addUserItem.put(KEY_SUMMARY, getString(R.string.user_add_user_item_summary));
539 HashMap<String,String> addProfileItem = new HashMap<String,String>();
540 addProfileItem.put(KEY_TITLE, getString(R.string.user_add_profile_item_title));
541 addProfileItem.put(KEY_SUMMARY, getString(R.string.user_add_profile_item_summary));
542 data.add(addUserItem);
543 data.add(addProfileItem);
Amith Yamasanif3db0212014-12-02 17:21:23 -0800544 AlertDialog.Builder builder = new AlertDialog.Builder(context);
545 SimpleAdapter adapter = new SimpleAdapter(builder.getContext(),
546 data, R.layout.two_line_list_item,
547 new String[] {KEY_TITLE, KEY_SUMMARY},
548 new int[] {R.id.title, R.id.summary});
549 builder.setTitle(R.string.user_add_user_type_title);
550 builder.setAdapter(adapter,
551 new DialogInterface.OnClickListener() {
552 @Override
553 public void onClick(DialogInterface dialog, int which) {
554 onAddUserClicked(which == 0
555 ? USER_TYPE_USER
556 : USER_TYPE_RESTRICTED_PROFILE);
557 }
558 });
559 return builder.create();
Amith Yamasanic861cf82012-10-02 14:51:46 -0700560 }
Amith Yamasanif162efe2013-04-29 10:43:05 -0700561 case DIALOG_NEED_LOCKSCREEN: {
562 Dialog dlg = new AlertDialog.Builder(context)
563 .setMessage(R.string.user_need_lock_message)
564 .setPositiveButton(R.string.user_set_lock_button,
565 new DialogInterface.OnClickListener() {
566 @Override
567 public void onClick(DialogInterface dialog, int which) {
568 launchChooseLockscreen();
569 }
570 })
571 .setNegativeButton(android.R.string.cancel, null)
572 .create();
573 return dlg;
574 }
Amith Yamasanic16b73e2014-07-17 19:13:51 -0700575 case DIALOG_CONFIRM_EXIT_GUEST: {
576 Dialog dlg = new AlertDialog.Builder(context)
577 .setTitle(R.string.user_exit_guest_confirm_title)
578 .setMessage(R.string.user_exit_guest_confirm_message)
Amith Yamasani94c01812014-08-18 16:42:43 -0700579 .setPositiveButton(R.string.user_exit_guest_dialog_remove,
Amith Yamasanic16b73e2014-07-17 19:13:51 -0700580 new DialogInterface.OnClickListener() {
581 @Override
582 public void onClick(DialogInterface dialog, int which) {
583 exitGuest();
584 }
585 })
Amith Yamasani94c01812014-08-18 16:42:43 -0700586 .setNegativeButton(android.R.string.cancel, null)
Amith Yamasanic16b73e2014-07-17 19:13:51 -0700587 .create();
588 return dlg;
589 }
Amith Yamasaniee398742014-07-24 14:13:36 -0700590 case DIALOG_USER_PROFILE_EDITOR: {
591 Dialog dlg = mEditUserInfoController.createDialog(
Fyodor Kupolovc9a95ef2015-05-15 17:16:15 -0700592 this,
Amith Yamasaniee398742014-07-24 14:13:36 -0700593 mMePreference.getIcon(),
594 mMePreference.getTitle(),
595 R.string.profile_info_settings_title,
596 this /* callback */,
597 android.os.Process.myUserHandle());
598 return dlg;
599 }
Amith Yamasanidc6bfa62012-09-06 18:04:06 -0700600 default:
601 return null;
602 }
603 }
604
605 private void removeUserNow() {
606 if (mRemovingUserId == UserHandle.myUserId()) {
607 removeThisUser();
608 } else {
609 new Thread() {
610 public void run() {
611 synchronized (mUserLock) {
Amith Yamasanidc6bfa62012-09-06 18:04:06 -0700612 mUserManager.removeUser(mRemovingUserId);
613 mHandler.sendEmptyMessage(MESSAGE_UPDATE_LIST);
Amith Yamasanidc6bfa62012-09-06 18:04:06 -0700614 }
615 }
616 }.start();
617 }
618 }
619
620 private void removeThisUser() {
Amith Yamasaniae47ef42012-09-16 17:53:35 -0700621 try {
Xiaohui Chen64f530c2015-06-24 12:35:07 -0700622 ActivityManagerNative.getDefault().switchUser(UserHandle.USER_SYSTEM);
Amith Yamasaniae47ef42012-09-16 17:53:35 -0700623 ((UserManager) getActivity().getSystemService(Context.USER_SERVICE))
624 .removeUser(UserHandle.myUserId());
625 } catch (RemoteException re) {
626 Log.e(TAG, "Unable to remove self user");
Amith Yamasanidc6bfa62012-09-06 18:04:06 -0700627 }
628 }
629
Amith Yamasanicc395692013-04-11 18:21:07 -0700630 private void addUserNow(final int userType) {
Amith Yamasanidc6bfa62012-09-06 18:04:06 -0700631 synchronized (mUserLock) {
632 mAddingUser = true;
Amith Yamasania98c4022013-04-19 15:27:52 -0700633 //updateUserList();
Amith Yamasanidc6bfa62012-09-06 18:04:06 -0700634 new Thread() {
635 public void run() {
Fyodor Kupolovc9a95ef2015-05-15 17:16:15 -0700636 UserInfo user;
Amith Yamasanidc6bfa62012-09-06 18:04:06 -0700637 // Could take a few seconds
Amith Yamasanifc8a3832013-04-23 11:44:59 -0700638 if (userType == USER_TYPE_USER) {
Amith Yamasanicc395692013-04-11 18:21:07 -0700639 user = createTrustedUser();
640 } else {
Fyodor Kupolov9938f6f2015-08-26 17:24:09 -0700641 user = createRestrictedProfile();
Amith Yamasanidc6bfa62012-09-06 18:04:06 -0700642 }
643 synchronized (mUserLock) {
644 mAddingUser = false;
Amith Yamasanifc8a3832013-04-23 11:44:59 -0700645 if (userType == USER_TYPE_USER) {
Amith Yamasania98c4022013-04-19 15:27:52 -0700646 mHandler.sendEmptyMessage(MESSAGE_UPDATE_LIST);
Amith Yamasanicc395692013-04-11 18:21:07 -0700647 mHandler.sendMessage(mHandler.obtainMessage(
648 MESSAGE_SETUP_USER, user.id, user.serialNumber));
649 } else {
650 mHandler.sendMessage(mHandler.obtainMessage(
651 MESSAGE_CONFIG_USER, user.id, user.serialNumber));
652 }
Amith Yamasanidc6bfa62012-09-06 18:04:06 -0700653 }
654 }
655 }.start();
656 }
Amith Yamasanib810a0d2012-03-25 10:12:26 -0700657 }
658
Amith Yamasaniae47ef42012-09-16 17:53:35 -0700659 private void switchUserNow(int userId) {
660 try {
661 ActivityManagerNative.getDefault().switchUser(userId);
662 } catch (RemoteException re) {
663 // Nothing to do
664 }
665 }
666
Amith Yamasanic16b73e2014-07-17 19:13:51 -0700667 /**
668 * Erase the current user (guest) and switch to another user.
669 */
670 private void exitGuest() {
671 // Just to be safe
Fyodor Kupolovc9a95ef2015-05-15 17:16:15 -0700672 if (!mUserCaps.mIsGuest) {
Amith Yamasanic16b73e2014-07-17 19:13:51 -0700673 return;
674 }
675 removeThisUser();
676 }
677
Amith Yamasanib810a0d2012-03-25 10:12:26 -0700678 private void updateUserList() {
Amith Yamasanif34a85d2012-09-17 18:31:45 -0700679 if (getActivity() == null) return;
Amith Yamasanie278eda2012-09-20 22:44:48 -0700680 List<UserInfo> users = mUserManager.getUsers(true);
Amith Yamasani9e6ac3d2014-06-30 15:31:37 +0530681 final Context context = getActivity();
Amith Yamasanib810a0d2012-03-25 10:12:26 -0700682
Amith Yamasani9e6ac3d2014-06-30 15:31:37 +0530683 final boolean voiceCapable = Utils.isVoiceCapable(context);
Fyodor Kupolov55145092014-12-08 14:15:36 -0800684 final ArrayList<Integer> missingIcons = new ArrayList<>();
685 final ArrayList<UserPreference> userPreferences = new ArrayList<>();
686 userPreferences.add(mMePreference);
687
Amith Yamasanib810a0d2012-03-25 10:12:26 -0700688 for (UserInfo user : users) {
Xiaohui Chen148ef772015-07-16 10:06:03 -0700689 if (!user.supportsSwitchToByUser()) {
690 // Only users that can be switched to should show up here.
691 // e.g. Managed profiles appear under Accounts Settings instead
Alexandra Gherghina83adb562014-07-31 19:30:41 +0100692 continue;
693 }
Fyodor Kupolov55145092014-12-08 14:15:36 -0800694 UserPreference pref;
Amith Yamasanic861cf82012-10-02 14:51:46 -0700695 if (user.id == UserHandle.myUserId()) {
Amith Yamasanidc6bfa62012-09-06 18:04:06 -0700696 pref = mMePreference;
Amith Yamasani9e6ac3d2014-06-30 15:31:37 +0530697 } else if (user.isGuest()) {
698 // Skip over Guest. We add generic Guest settings after this loop
699 continue;
Amith Yamasanidc6bfa62012-09-06 18:04:06 -0700700 } else {
Amith Yamasani9e6ac3d2014-06-30 15:31:37 +0530701 // With Telephony:
702 // Secondary user: Settings
703 // Guest: Settings
704 // Restricted Profile: There is no Restricted Profile
705 // Without Telephony:
706 // Secondary user: Delete
707 // Guest: Nothing
708 // Restricted Profile: Settings
Xiaohui Chen64f530c2015-06-24 12:35:07 -0700709 final boolean showSettings = mUserCaps.mIsAdmin
Fyodor Kupolovc9a95ef2015-05-15 17:16:15 -0700710 && (voiceCapable || user.isRestricted());
Xiaohui Chen64f530c2015-06-24 12:35:07 -0700711 final boolean showDelete = mUserCaps.mIsAdmin
Amith Yamasani9e6ac3d2014-06-30 15:31:37 +0530712 && (!voiceCapable && !user.isRestricted() && !user.isGuest());
Jason Monk39b46742015-09-10 15:52:51 -0400713 pref = new UserPreference(getPrefContext(), null, user.id,
Amith Yamasani9e6ac3d2014-06-30 15:31:37 +0530714 showSettings ? this : null,
715 showDelete ? this : null);
Amith Yamasanidc6bfa62012-09-06 18:04:06 -0700716 pref.setOnPreferenceClickListener(this);
717 pref.setKey("id=" + user.id);
Fyodor Kupolov55145092014-12-08 14:15:36 -0800718 userPreferences.add(pref);
Xiaohui Chen64f530c2015-06-24 12:35:07 -0700719 if (user.isAdmin()) {
720 pref.setSummary(R.string.user_admin);
Amith Yamasanidc6bfa62012-09-06 18:04:06 -0700721 }
722 pref.setTitle(user.name);
Amith Yamasanifc8a3832013-04-23 11:44:59 -0700723 }
724 if (!isInitialized(user)) {
Alexandra Gherghina423bafc2014-04-23 10:56:37 +0000725 if (user.isRestricted()) {
726 pref.setSummary(R.string.user_summary_restricted_not_set_up);
Alexandra Gherghina423bafc2014-04-23 10:56:37 +0000727 } else {
728 pref.setSummary(R.string.user_summary_not_set_up);
729 }
Amith Yamasanifc8a3832013-04-23 11:44:59 -0700730 } else if (user.isRestricted()) {
731 pref.setSummary(R.string.user_summary_restricted_profile);
Amith Yamasani48fa8572012-04-17 17:12:01 -0700732 }
Amith Yamasanidc6bfa62012-09-06 18:04:06 -0700733 if (user.iconPath != null) {
Amith Yamasanif34a85d2012-09-17 18:31:45 -0700734 if (mUserIcons.get(user.id) == null) {
Alexandra Gherghinabc6e78f2014-09-03 10:22:09 +0100735 // Icon not loaded yet, print a placeholder
Amith Yamasanif34a85d2012-09-17 18:31:45 -0700736 missingIcons.add(user.id);
Alexandra Gherghinabc6e78f2014-09-03 10:22:09 +0100737 pref.setIcon(getEncircledDefaultIcon());
Amith Yamasanif34a85d2012-09-17 18:31:45 -0700738 } else {
739 setPhotoId(pref, user);
740 }
Amith Yamasanif2663ab2014-08-11 17:17:29 -0700741 } else {
Alexandra Gherghinabc6e78f2014-09-03 10:22:09 +0100742 // Icon not available yet, print a placeholder
743 pref.setIcon(getEncircledDefaultIcon());
Amith Yamasanidc6bfa62012-09-06 18:04:06 -0700744 }
745 }
Amith Yamasani247520c2014-07-25 12:52:29 -0700746
Amith Yamasanidc6bfa62012-09-06 18:04:06 -0700747 // Add a temporary entry for the user being created
748 if (mAddingUser) {
Jason Monk39b46742015-09-10 15:52:51 -0400749 UserPreference pref = new UserPreference(getPrefContext(), null,
Fyodor Kupolov55145092014-12-08 14:15:36 -0800750 UserPreference.USERID_UNKNOWN, null, null);
Amith Yamasanidc6bfa62012-09-06 18:04:06 -0700751 pref.setEnabled(false);
752 pref.setTitle(R.string.user_new_user_name);
Alexandra Gherghinabc6e78f2014-09-03 10:22:09 +0100753 pref.setIcon(getEncircledDefaultIcon());
Fyodor Kupolov55145092014-12-08 14:15:36 -0800754 userPreferences.add(pref);
Amith Yamasanib810a0d2012-03-25 10:12:26 -0700755 }
Amith Yamasani9e6ac3d2014-06-30 15:31:37 +0530756
Fyodor Kupolovc4788852015-06-09 15:54:28 -0700757 if (!mUserCaps.mIsGuest && (mUserCaps.mCanAddGuest || findGuest() != null)) {
Fyodor Kupolov55145092014-12-08 14:15:36 -0800758 // Add a virtual Guest user for guest defaults
Jason Monk39b46742015-09-10 15:52:51 -0400759 UserPreference pref = new UserPreference(getPrefContext(), null,
Fyodor Kupolov55145092014-12-08 14:15:36 -0800760 UserPreference.USERID_GUEST_DEFAULTS,
Xiaohui Chen64f530c2015-06-24 12:35:07 -0700761 mUserCaps.mIsAdmin && voiceCapable? this : null /* settings icon handler */,
Fyodor Kupolov55145092014-12-08 14:15:36 -0800762 null /* delete icon handler */);
763 pref.setTitle(R.string.user_guest);
764 pref.setIcon(getEncircledDefaultIcon());
765 pref.setOnPreferenceClickListener(this);
766 userPreferences.add(pref);
767 }
768
769 // Sort list of users by serialNum
770 Collections.sort(userPreferences, UserPreference.SERIAL_NUMBER_COMPARATOR);
771
772 getActivity().invalidateOptionsMenu();
773
774 // Load the icons
775 if (missingIcons.size() > 0) {
776 loadIconsAsync(missingIcons);
777 }
778
779 PreferenceScreen preferenceScreen = getPreferenceScreen();
780 preferenceScreen.removeAll();
781
782 // If profiles are supported, userPreferences will be added to the category labeled
783 // "User & Profiles", otherwise the category is skipped and elements are added directly
784 // to preferenceScreen
785 PreferenceGroup groupToAddUsers;
Fyodor Kupolovc9a95ef2015-05-15 17:16:15 -0700786 if (mUserCaps.mCanAddRestrictedProfile) {
Fyodor Kupolov55145092014-12-08 14:15:36 -0800787 mUserListCategory.removeAll();
788 mUserListCategory.setOrder(Preference.DEFAULT_ORDER);
789 preferenceScreen.addPreference(mUserListCategory);
790 groupToAddUsers = mUserListCategory;
791 } else {
792 groupToAddUsers = preferenceScreen;
793 }
794 for (UserPreference userPreference : userPreferences) {
795 userPreference.setOrder(Preference.DEFAULT_ORDER);
796 groupToAddUsers.addPreference(userPreference);
797 }
798
799 // Append Add user to the end of the list
Fyodor Kupolovc9a95ef2015-05-15 17:16:15 -0700800 if (mUserCaps.mCanAddUser) {
Fyodor Kupolov55145092014-12-08 14:15:36 -0800801 boolean moreUsers = mUserManager.canAddMoreUsers();
Fyodor Kupolov55145092014-12-08 14:15:36 -0800802 mAddUser.setOrder(Preference.DEFAULT_ORDER);
803 preferenceScreen.addPreference(mAddUser);
Fyodor Kupolova7a7bfe2015-05-08 15:54:38 -0700804 mAddUser.setEnabled(moreUsers);
805 if (!moreUsers) {
806 mAddUser.setSummary(getString(R.string.user_add_max_count, getMaxRealUsers()));
807 } else {
808 mAddUser.setSummary(null);
809 }
Fyodor Kupolov55145092014-12-08 14:15:36 -0800810 }
811 }
812
Fyodor Kupolova7a7bfe2015-05-08 15:54:38 -0700813 private int getMaxRealUsers() {
814 // guest is not counted against getMaxSupportedUsers() number
815 final int maxUsersAndGuest = UserManager.getMaxSupportedUsers() + 1;
816 final List<UserInfo> users = mUserManager.getUsers();
817 // managed profiles are counted against getMaxSupportedUsers()
818 int managedProfiles = 0;
819 for (UserInfo user : users) {
820 if (user.isManagedProfile()) {
821 managedProfiles++;
822 }
823 }
824 return maxUsersAndGuest - managedProfiles;
825 }
826
Amith Yamasanif34a85d2012-09-17 18:31:45 -0700827 private void loadIconsAsync(List<Integer> missingIcons) {
828 new AsyncTask<List<Integer>, Void, Void>() {
829 @Override
830 protected void onPostExecute(Void result) {
831 updateUserList();
832 }
833
834 @Override
835 protected Void doInBackground(List<Integer>... values) {
Amith Yamasanif34a85d2012-09-17 18:31:45 -0700836 for (int userId : values[0]) {
837 Bitmap bitmap = mUserManager.getUserIcon(userId);
Amith Yamasanif2663ab2014-08-11 17:17:29 -0700838 if (bitmap == null) {
Zoltan Szatmary-Bane5814ff2014-12-19 16:27:45 +0000839 bitmap = Utils.getDefaultUserIconAsBitmap(userId);
Amith Yamasanif2663ab2014-08-11 17:17:29 -0700840 }
Amith Yamasani864e3b72013-03-27 12:27:01 -0700841 mUserIcons.append(userId, bitmap);
Amith Yamasanif34a85d2012-09-17 18:31:45 -0700842 }
843 return null;
844 }
845 }.execute(missingIcons);
Amith Yamasanif34a85d2012-09-17 18:31:45 -0700846 }
Amith Yamasani5cdc9372012-11-14 16:23:40 -0800847
Amith Yamasanidc6bfa62012-09-06 18:04:06 -0700848 private void assignProfilePhoto(final UserInfo user) {
Amith Yamasaniae47ef42012-09-16 17:53:35 -0700849 if (!Utils.copyMeProfilePhoto(getActivity(), user)) {
Amith Yamasanidc6bfa62012-09-06 18:04:06 -0700850 assignDefaultPhoto(user);
Amith Yamasanidc6bfa62012-09-06 18:04:06 -0700851 }
Amith Yamasanidc6bfa62012-09-06 18:04:06 -0700852 }
853
Amith Yamasanidc6bfa62012-09-06 18:04:06 -0700854 private void assignDefaultPhoto(UserInfo user) {
Zoltan Szatmary-Bane5814ff2014-12-19 16:27:45 +0000855 Bitmap bitmap = Utils.getDefaultUserIconAsBitmap(user.id);
Amith Yamasanif34a85d2012-09-17 18:31:45 -0700856 mUserManager.setUserIcon(user.id, bitmap);
Amith Yamasanidc6bfa62012-09-06 18:04:06 -0700857 }
858
Alexandra Gherghinabc6e78f2014-09-03 10:22:09 +0100859 private Drawable getEncircledDefaultIcon() {
860 if (mDefaultIconDrawable == null) {
Zoltan Szatmary-Bane5814ff2014-12-19 16:27:45 +0000861 mDefaultIconDrawable = encircle(Utils.getDefaultUserIconAsBitmap(UserHandle.USER_NULL));
Amith Yamasanic16b73e2014-07-17 19:13:51 -0700862 }
Alexandra Gherghinabc6e78f2014-09-03 10:22:09 +0100863 return mDefaultIconDrawable;
Amith Yamasanic16b73e2014-07-17 19:13:51 -0700864 }
865
Amith Yamasanidc6bfa62012-09-06 18:04:06 -0700866 private void setPhotoId(Preference pref, UserInfo user) {
Amith Yamasanid4abdd22013-04-17 18:27:01 -0700867 Bitmap bitmap = mUserIcons.get(user.id);
Amith Yamasani864e3b72013-03-27 12:27:01 -0700868 if (bitmap != null) {
869 pref.setIcon(encircle(bitmap));
Amith Yamasanie940dac2012-09-17 10:21:27 -0700870 }
Amith Yamasani48fa8572012-04-17 17:12:01 -0700871 }
872
Amith Yamasanidc6bfa62012-09-06 18:04:06 -0700873 private void setUserName(String name) {
874 mUserManager.setUserName(UserHandle.myUserId(), name);
875 mNicknamePreference.setSummary(name);
Amith Yamasani1a634d32012-09-27 23:01:35 -0700876 getActivity().invalidateOptionsMenu();
Amith Yamasanidc6bfa62012-09-06 18:04:06 -0700877 }
878
Amith Yamasanib810a0d2012-03-25 10:12:26 -0700879 @Override
880 public boolean onPreferenceClick(Preference pref) {
Amith Yamasanidc6bfa62012-09-06 18:04:06 -0700881 if (pref == mMePreference) {
Fyodor Kupolovc9a95ef2015-05-15 17:16:15 -0700882 if (mUserCaps.mIsGuest) {
Amith Yamasanic16b73e2014-07-17 19:13:51 -0700883 showDialog(DIALOG_CONFIRM_EXIT_GUEST);
884 return true;
885 }
Amith Yamasanid4abdd22013-04-17 18:27:01 -0700886 // If this is a limited user, launch the user info settings instead of profile editor
887 if (mUserManager.isLinkedUser()) {
888 onManageUserClicked(UserHandle.myUserId(), false);
889 } else {
Amith Yamasaniee398742014-07-24 14:13:36 -0700890 showDialog(DIALOG_USER_PROFILE_EDITOR);
Amith Yamasanid4abdd22013-04-17 18:27:01 -0700891 }
Amith Yamasani1a634d32012-09-27 23:01:35 -0700892 } else if (pref instanceof UserPreference) {
893 int userId = ((UserPreference) pref).getUserId();
Amith Yamasani9e6ac3d2014-06-30 15:31:37 +0530894 if (userId == UserPreference.USERID_GUEST_DEFAULTS) {
895 createAndSwitchToGuestUser();
Amith Yamasani1a634d32012-09-27 23:01:35 -0700896 } else {
Amith Yamasani9e6ac3d2014-06-30 15:31:37 +0530897 // Get the latest status of the user
898 UserInfo user = mUserManager.getUserInfo(userId);
Amith Yamasani1a634d32012-09-27 23:01:35 -0700899 if (!isInitialized(user)) {
900 mHandler.sendMessage(mHandler.obtainMessage(
901 MESSAGE_SETUP_USER, user.id, user.serialNumber));
Amith Yamasanif7ba74d2014-08-22 12:33:23 -0700902 } else {
903 switchUserNow(userId);
Amith Yamasani1a634d32012-09-27 23:01:35 -0700904 }
905 }
Amith Yamasanifc8a3832013-04-23 11:44:59 -0700906 } else if (pref == mAddUser) {
Amith Yamasani0e43d322014-05-07 10:19:34 -0700907 // If we allow both types, show a picker, otherwise directly go to
908 // flow for full user.
Fyodor Kupolovc9a95ef2015-05-15 17:16:15 -0700909 if (mUserCaps.mCanAddRestrictedProfile) {
Amith Yamasani0e43d322014-05-07 10:19:34 -0700910 showDialog(DIALOG_CHOOSE_USER_TYPE);
911 } else {
912 onAddUserClicked(USER_TYPE_USER);
913 }
Amith Yamasanidc6bfa62012-09-06 18:04:06 -0700914 }
915 return false;
916 }
917
Amith Yamasani9e6ac3d2014-06-30 15:31:37 +0530918 private void createAndSwitchToGuestUser() {
Fyodor Kupolov097936a2015-05-21 18:31:45 -0700919 final UserInfo guest = findGuest();
920 if (guest != null) {
921 switchUserNow(guest.id);
Jason Monk7c273982014-08-07 16:02:03 -0400922 return;
923 }
Amith Yamasani9e6ac3d2014-06-30 15:31:37 +0530924 UserInfo guestUser = mUserManager.createGuest(getActivity(),
925 getResources().getString(R.string.user_guest));
926 if (guestUser != null) {
927 switchUserNow(guestUser.id);
928 }
929 }
930
Fyodor Kupolov097936a2015-05-21 18:31:45 -0700931 private UserInfo findGuest() {
932 List<UserInfo> users = mUserManager.getUsers();
933 for (UserInfo user : users) {
934 if (user.isGuest()) {
935 return user;
936 }
937 }
938 return null;
939 }
940
Amith Yamasani1a634d32012-09-27 23:01:35 -0700941 private boolean isInitialized(UserInfo user) {
942 return (user.flags & UserInfo.FLAG_INITIALIZED) != 0;
943 }
944
Amith Yamasani864e3b72013-03-27 12:27:01 -0700945 private Drawable encircle(Bitmap icon) {
946 Drawable circled = CircleFramedDrawable.getInstance(getActivity(), icon);
947 return circled;
948 }
949
Amith Yamasanidc6bfa62012-09-06 18:04:06 -0700950 @Override
951 public void onClick(View v) {
952 if (v.getTag() instanceof UserPreference) {
953 int userId = ((UserPreference) v.getTag()).getUserId();
Amith Yamasani233592b2013-03-01 17:05:23 -0800954 switch (v.getId()) {
955 case UserPreference.DELETE_ID:
Maggie Benthall44534962013-08-29 10:49:13 -0400956 onRemoveUserClicked(userId);
Amith Yamasani233592b2013-03-01 17:05:23 -0800957 break;
958 case UserPreference.SETTINGS_ID:
Amith Yamasanicc395692013-04-11 18:21:07 -0700959 onManageUserClicked(userId, false);
Amith Yamasani233592b2013-03-01 17:05:23 -0800960 break;
961 }
Amith Yamasanidc6bfa62012-09-06 18:04:06 -0700962 }
963 }
964
965 @Override
966 public void onDismiss(DialogInterface dialog) {
967 synchronized (mUserLock) {
968 mAddingUser = false;
969 mRemovingUserId = -1;
Amith Yamasanic861cf82012-10-02 14:51:46 -0700970 updateUserList();
Amith Yamasanidc6bfa62012-09-06 18:04:06 -0700971 }
972 }
973
974 @Override
975 public boolean onPreferenceChange(Preference preference, Object newValue) {
976 if (preference == mNicknamePreference) {
977 String value = (String) newValue;
978 if (preference == mNicknamePreference && value != null
979 && value.length() > 0) {
980 setUserName(value);
981 }
Amith Yamasanib810a0d2012-03-25 10:12:26 -0700982 return true;
983 }
984 return false;
985 }
Amith Yamasanidc6bfa62012-09-06 18:04:06 -0700986
Amith Yamasani38223dc2012-09-18 09:51:07 -0700987 @Override
988 public int getHelpResource() {
989 return R.string.help_url_users;
990 }
Amith Yamasaniee398742014-07-24 14:13:36 -0700991
992 @Override
993 public void onPhotoChanged(Drawable photo) {
994 mMePreference.setIcon(photo);
995 }
996
997 @Override
998 public void onLabelChanged(CharSequence label) {
999 mMePreference.setTitle(label);
1000 }
Fyodor Kupolovc9a95ef2015-05-15 17:16:15 -07001001
1002 private static class UserCapabilities {
1003 boolean mEnabled = true;
1004 boolean mCanAddUser = true;
1005 boolean mCanAddRestrictedProfile = true;
Xiaohui Chen64f530c2015-06-24 12:35:07 -07001006 boolean mIsAdmin;
Fyodor Kupolovc9a95ef2015-05-15 17:16:15 -07001007 boolean mIsGuest;
Fyodor Kupolov097936a2015-05-21 18:31:45 -07001008 boolean mCanAddGuest;
Fyodor Kupolovc9a95ef2015-05-15 17:16:15 -07001009
Xiaohui Chen64f530c2015-06-24 12:35:07 -07001010 private UserCapabilities() {}
1011
Fyodor Kupolovc9a95ef2015-05-15 17:16:15 -07001012 public static UserCapabilities create(Context context) {
1013 UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
1014 UserCapabilities caps = new UserCapabilities();
1015 if (!UserManager.supportsMultipleUsers() || Utils.isMonkeyRunning()) {
1016 caps.mEnabled = false;
1017 return caps;
1018 }
1019
Xiaohui Chen64f530c2015-06-24 12:35:07 -07001020 final UserInfo myUserInfo = userManager.getUserInfo(UserHandle.myUserId());
1021 caps.mIsGuest = myUserInfo.isGuest();
1022 caps.mIsAdmin = myUserInfo.isAdmin();
Fyodor Kupolov097936a2015-05-21 18:31:45 -07001023 final boolean disallowAddUser = userManager.hasUserRestriction(
1024 UserManager.DISALLOW_ADD_USER);
Xiaohui Chen64f530c2015-06-24 12:35:07 -07001025 if (!caps.mIsAdmin || UserManager.getMaxSupportedUsers() < 2
Fyodor Kupolovc9a95ef2015-05-15 17:16:15 -07001026 || !UserManager.supportsMultipleUsers()
Fyodor Kupolov097936a2015-05-21 18:31:45 -07001027 || disallowAddUser) {
Fyodor Kupolovc9a95ef2015-05-15 17:16:15 -07001028 caps.mCanAddUser = false;
1029 }
1030 DevicePolicyManager dpm = (DevicePolicyManager) context.getSystemService(
1031 Context.DEVICE_POLICY_SERVICE);
1032 // No restricted profiles for tablets with a device owner, or phones.
1033 if (dpm.getDeviceOwner() != null || Utils.isVoiceCapable(context)) {
1034 caps.mCanAddRestrictedProfile = false;
1035 }
Fyodor Kupolov097936a2015-05-21 18:31:45 -07001036
Xiaohui Chen64f530c2015-06-24 12:35:07 -07001037 final boolean canAddUsersWhenLocked = caps.mIsAdmin || Settings.Global.getInt(
Fyodor Kupolov097936a2015-05-21 18:31:45 -07001038 context.getContentResolver(), Settings.Global.ADD_USERS_WHEN_LOCKED, 0) == 1;
1039 caps.mCanAddGuest = !caps.mIsGuest && !disallowAddUser && canAddUsersWhenLocked;
Fyodor Kupolovc9a95ef2015-05-15 17:16:15 -07001040 return caps;
1041 }
1042
1043 @Override
1044 public String toString() {
1045 return "UserCapabilities{" +
1046 "mEnabled=" + mEnabled +
1047 ", mCanAddUser=" + mCanAddUser +
1048 ", mCanAddRestrictedProfile=" + mCanAddRestrictedProfile +
Xiaohui Chen64f530c2015-06-24 12:35:07 -07001049 ", mIsAdmin=" + mIsAdmin +
Fyodor Kupolovc9a95ef2015-05-15 17:16:15 -07001050 ", mIsGuest=" + mIsGuest +
1051 '}';
1052 }
1053 }
1054
1055 public static final Indexable.SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
1056 new BaseSearchIndexProvider() {
1057 @Override
1058 public List<SearchIndexableRaw> getRawDataToIndex(Context context,
1059 boolean enabled) {
1060 final List<SearchIndexableRaw> result = new ArrayList<>();
1061 final UserCapabilities userCaps = UserCapabilities.create(context);
1062 if (!userCaps.mEnabled) {
1063 return result;
1064 }
1065 final Resources res = context.getResources();
1066 SearchIndexableRaw data = new SearchIndexableRaw(context);
1067 data.title = res.getString(R.string.user_settings_title);
1068 data.screenTitle = res.getString(R.string.user_settings_title);
1069 result.add(data);
1070
1071 if (userCaps.mCanAddUser) {
1072 data = new SearchIndexableRaw(context);
1073 data.title = res.getString(userCaps.mCanAddRestrictedProfile ?
1074 R.string.user_add_user_or_profile_menu
1075 : R.string.user_add_user_menu);
1076 data.screenTitle = res.getString(R.string.user_settings_title);
1077 result.add(data);
1078 }
1079 return result;
1080 }
1081 };
1082
Amith Yamasanib810a0d2012-03-25 10:12:26 -07001083}