blob: 53fd446b24449e19355139654318bc5d0663c0ab [file] [log] [blame]
Adrian Roos00a0b1f2014-07-16 16:44:49 +02001/*
2 * Copyright (C) 2014 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.systemui.statusbar.policy;
18
Adrian Roos00a0b1f2014-07-16 16:44:49 +020019import android.app.ActivityManager;
20import android.app.ActivityManagerNative;
Adrian Roos50052442014-07-17 23:35:18 +020021import android.app.Dialog;
Fyodor Kupolovf4d6ad22015-04-13 11:52:18 -070022import android.app.Notification;
23import android.app.NotificationManager;
24import android.app.PendingIntent;
Adrian Roos00a0b1f2014-07-16 16:44:49 +020025import android.content.BroadcastReceiver;
26import android.content.Context;
Adrian Roos50052442014-07-17 23:35:18 +020027import android.content.DialogInterface;
Adrian Roos00a0b1f2014-07-16 16:44:49 +020028import android.content.Intent;
29import android.content.IntentFilter;
30import android.content.pm.UserInfo;
Jason Monk2daf62c2014-07-31 14:35:06 -040031import android.database.ContentObserver;
Adrian Roos00a0b1f2014-07-16 16:44:49 +020032import android.graphics.Bitmap;
Adrian Roosccdff622014-08-06 00:07:18 +020033import android.graphics.drawable.Drawable;
Adrian Roos00a0b1f2014-07-16 16:44:49 +020034import android.os.AsyncTask;
Jason Monk2daf62c2014-07-31 14:35:06 -040035import android.os.Handler;
Adrian Roos00a0b1f2014-07-16 16:44:49 +020036import android.os.RemoteException;
Adrian Roose9c7d432014-07-17 18:27:38 +020037import android.os.UserHandle;
Adrian Roos00a0b1f2014-07-16 16:44:49 +020038import android.os.UserManager;
Jason Monk2daf62c2014-07-31 14:35:06 -040039import android.provider.Settings;
Adrian Roos00a0b1f2014-07-16 16:44:49 +020040import android.util.Log;
Adrian Roose9c7d432014-07-17 18:27:38 +020041import android.util.SparseArray;
Adrian Roos88b11932015-07-22 14:59:48 -070042import android.util.SparseBooleanArray;
Adrian Roos00a0b1f2014-07-16 16:44:49 +020043import android.view.View;
44import android.view.ViewGroup;
Adrian Roos00a0b1f2014-07-16 16:44:49 +020045import android.widget.BaseAdapter;
46
Chris Wrenf6e9228b2016-01-26 18:04:35 -050047import com.android.internal.logging.MetricsProto.MetricsEvent;
Alexandra Gherghina64d4dca2014-08-28 18:26:56 +010048import com.android.internal.util.UserIcons;
Sudheer Shanka1c7cda82015-12-31 14:46:02 +000049import com.android.settingslib.RestrictedLockUtils;
Alexandra Gherghina64d4dca2014-08-28 18:26:56 +010050import com.android.systemui.BitmapHelper;
51import com.android.systemui.GuestResumeSessionReceiver;
52import com.android.systemui.R;
53import com.android.systemui.qs.QSTile;
54import com.android.systemui.qs.tiles.UserDetailView;
Sudheer Shanka1c7cda82015-12-31 14:46:02 +000055import com.android.systemui.statusbar.phone.ActivityStarter;
Alexandra Gherghina64d4dca2014-08-28 18:26:56 +010056import com.android.systemui.statusbar.phone.SystemUIDialog;
57
Adrian Roos00a0b1f2014-07-16 16:44:49 +020058import java.io.FileDescriptor;
59import java.io.PrintWriter;
60import java.lang.ref.WeakReference;
61import java.util.ArrayList;
62import java.util.List;
63
Sudheer Shanka1c7cda82015-12-31 14:46:02 +000064import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
65
Adrian Roos00a0b1f2014-07-16 16:44:49 +020066/**
67 * Keeps a list of all users on the device for user switching.
68 */
69public class UserSwitcherController {
70
71 private static final String TAG = "UserSwitcherController";
Adrian Roos50052442014-07-17 23:35:18 +020072 private static final boolean DEBUG = false;
Jason Monk2daf62c2014-07-31 14:35:06 -040073 private static final String SIMPLE_USER_SWITCHER_GLOBAL_SETTING =
74 "lockscreenSimpleUserSwitcher";
Fyodor Kupolovf4d6ad22015-04-13 11:52:18 -070075 private static final String ACTION_REMOVE_GUEST = "com.android.systemui.REMOVE_GUEST";
Xiaohui Chen860397f2015-07-22 15:03:48 -070076 private static final String ACTION_LOGOUT_USER = "com.android.systemui.LOGOUT_USER";
Adrian Roos88b11932015-07-22 14:59:48 -070077 private static final int PAUSE_REFRESH_USERS_TIMEOUT_MS = 3000;
Adrian Roos00a0b1f2014-07-16 16:44:49 +020078
Amith Yamasanid81f8272015-07-23 17:15:45 -070079 private static final int ID_REMOVE_GUEST = 1010;
Xiaohui Chen860397f2015-07-22 15:03:48 -070080 private static final int ID_LOGOUT_USER = 1011;
Amith Yamasanid81f8272015-07-23 17:15:45 -070081 private static final String TAG_REMOVE_GUEST = "remove_guest";
Xiaohui Chen860397f2015-07-22 15:03:48 -070082 private static final String TAG_LOGOUT_USER = "logout_user";
83
Amith Yamasanid81f8272015-07-23 17:15:45 -070084 private static final String PERMISSION_SELF = "com.android.systemui.permission.SELF";
85
Adrian Roos00a0b1f2014-07-16 16:44:49 +020086 private final Context mContext;
87 private final UserManager mUserManager;
88 private final ArrayList<WeakReference<BaseUserAdapter>> mAdapters = new ArrayList<>();
Adrian Roos50052442014-07-17 23:35:18 +020089 private final GuestResumeSessionReceiver mGuestResumeSessionReceiver
90 = new GuestResumeSessionReceiver();
Adrian Roosccdff622014-08-06 00:07:18 +020091 private final KeyguardMonitor mKeyguardMonitor;
Adrian Roos88b11932015-07-22 14:59:48 -070092 private final Handler mHandler;
Sudheer Shanka1c7cda82015-12-31 14:46:02 +000093 private final ActivityStarter mActivityStarter;
Adrian Roos00a0b1f2014-07-16 16:44:49 +020094
95 private ArrayList<UserRecord> mUsers = new ArrayList<>();
Adrian Roos50052442014-07-17 23:35:18 +020096 private Dialog mExitGuestDialog;
Adrian Roos0c6763a2014-09-08 19:11:00 +020097 private Dialog mAddUserDialog;
Xiaohui Chen7cb69df2015-07-13 16:01:01 -070098 private int mLastNonGuestUser = UserHandle.USER_SYSTEM;
Adrian Roosccdff622014-08-06 00:07:18 +020099 private boolean mSimpleUserSwitcher;
100 private boolean mAddUsersWhenLocked;
Adrian Roos88b11932015-07-22 14:59:48 -0700101 private boolean mPauseRefreshUsers;
Fyodor Kupolov07140f72016-02-17 10:46:11 -0800102 private boolean mAllowUserSwitchingWhenSystemUserLocked;
Adrian Roos88b11932015-07-22 14:59:48 -0700103 private SparseBooleanArray mForcePictureLoadForUserId = new SparseBooleanArray(2);
Adrian Roos00a0b1f2014-07-16 16:44:49 +0200104
Adrian Roos88b11932015-07-22 14:59:48 -0700105 public UserSwitcherController(Context context, KeyguardMonitor keyguardMonitor,
Sudheer Shanka1c7cda82015-12-31 14:46:02 +0000106 Handler handler, ActivityStarter activityStarter) {
Adrian Roos00a0b1f2014-07-16 16:44:49 +0200107 mContext = context;
Adrian Roos50052442014-07-17 23:35:18 +0200108 mGuestResumeSessionReceiver.register(context);
Adrian Roosccdff622014-08-06 00:07:18 +0200109 mKeyguardMonitor = keyguardMonitor;
Adrian Roos88b11932015-07-22 14:59:48 -0700110 mHandler = handler;
Sudheer Shanka1c7cda82015-12-31 14:46:02 +0000111 mActivityStarter = activityStarter;
Adrian Roos00a0b1f2014-07-16 16:44:49 +0200112 mUserManager = UserManager.get(context);
113 IntentFilter filter = new IntentFilter();
114 filter.addAction(Intent.ACTION_USER_ADDED);
115 filter.addAction(Intent.ACTION_USER_REMOVED);
116 filter.addAction(Intent.ACTION_USER_INFO_CHANGED);
117 filter.addAction(Intent.ACTION_USER_SWITCHED);
Adrian Roose9c7d432014-07-17 18:27:38 +0200118 filter.addAction(Intent.ACTION_USER_STOPPING);
Fyodor Kupolov07140f72016-02-17 10:46:11 -0800119 filter.addAction(Intent.ACTION_USER_UNLOCKED);
Xiaohui Chen7cb69df2015-07-13 16:01:01 -0700120 mContext.registerReceiverAsUser(mReceiver, UserHandle.SYSTEM, filter,
Adrian Roose9c7d432014-07-17 18:27:38 +0200121 null /* permission */, null /* scheduler */);
Jason Monk2daf62c2014-07-31 14:35:06 -0400122
Amith Yamasanid81f8272015-07-23 17:15:45 -0700123 filter = new IntentFilter();
124 filter.addAction(ACTION_REMOVE_GUEST);
Xiaohui Chen860397f2015-07-22 15:03:48 -0700125 filter.addAction(ACTION_LOGOUT_USER);
Amith Yamasani5891a342015-07-24 13:50:58 -0700126 mContext.registerReceiverAsUser(mReceiver, UserHandle.SYSTEM, filter,
Amith Yamasanid81f8272015-07-23 17:15:45 -0700127 PERMISSION_SELF, null /* scheduler */);
Adrian Roosccdff622014-08-06 00:07:18 +0200128
Jason Monk2daf62c2014-07-31 14:35:06 -0400129 mContext.getContentResolver().registerContentObserver(
130 Settings.Global.getUriFor(SIMPLE_USER_SWITCHER_GLOBAL_SETTING), true,
Adrian Roosccdff622014-08-06 00:07:18 +0200131 mSettingsObserver);
132 mContext.getContentResolver().registerContentObserver(
133 Settings.Global.getUriFor(Settings.Global.ADD_USERS_WHEN_LOCKED), true,
134 mSettingsObserver);
Fyodor Kupolov07140f72016-02-17 10:46:11 -0800135 mContext.getContentResolver().registerContentObserver(
136 Settings.Global.getUriFor(
137 Settings.Global.ALLOW_USER_SWITCHING_WHEN_SYSTEM_USER_LOCKED),
138 true, mSettingsObserver);
Adrian Roosccdff622014-08-06 00:07:18 +0200139 // Fetch initial values.
140 mSettingsObserver.onChange(false);
141
142 keyguardMonitor.addCallback(mCallback);
Jason Monk2daf62c2014-07-31 14:35:06 -0400143
Adrian Roose9c7d432014-07-17 18:27:38 +0200144 refreshUsers(UserHandle.USER_NULL);
Adrian Roos00a0b1f2014-07-16 16:44:49 +0200145 }
146
Adrian Roose9c7d432014-07-17 18:27:38 +0200147 /**
148 * Refreshes users from UserManager.
149 *
150 * The pictures are only loaded if they have not been loaded yet.
151 *
152 * @param forcePictureLoadForId forces the picture of the given user to be reloaded.
153 */
Amith Yamasani95ab7842014-08-11 17:09:26 -0700154 @SuppressWarnings("unchecked")
Adrian Roose9c7d432014-07-17 18:27:38 +0200155 private void refreshUsers(int forcePictureLoadForId) {
Adrian Roos88b11932015-07-22 14:59:48 -0700156 if (DEBUG) Log.d(TAG, "refreshUsers(forcePictureLoadForId=" + forcePictureLoadForId+")");
157 if (forcePictureLoadForId != UserHandle.USER_NULL) {
158 mForcePictureLoadForUserId.put(forcePictureLoadForId, true);
159 }
160
161 if (mPauseRefreshUsers) {
162 return;
163 }
Adrian Roosc5db3902014-11-21 13:54:04 +0000164
165 SparseArray<Bitmap> bitmaps = new SparseArray<>(mUsers.size());
166 final int N = mUsers.size();
167 for (int i = 0; i < N; i++) {
168 UserRecord r = mUsers.get(i);
Adrian Roos88b11932015-07-22 14:59:48 -0700169 if (r == null || r.picture == null ||
170 r.info == null || mForcePictureLoadForUserId.get(r.info.id)) {
Adrian Roosc5db3902014-11-21 13:54:04 +0000171 continue;
Adrian Roose9c7d432014-07-17 18:27:38 +0200172 }
Adrian Roosc5db3902014-11-21 13:54:04 +0000173 bitmaps.put(r.info.id, r.picture);
Adrian Roose9c7d432014-07-17 18:27:38 +0200174 }
Adrian Roos88b11932015-07-22 14:59:48 -0700175 mForcePictureLoadForUserId.clear();
Adrian Roose9c7d432014-07-17 18:27:38 +0200176
Adrian Roosccdff622014-08-06 00:07:18 +0200177 final boolean addUsersWhenLocked = mAddUsersWhenLocked;
Adrian Roose9c7d432014-07-17 18:27:38 +0200178 new AsyncTask<SparseArray<Bitmap>, Void, ArrayList<UserRecord>>() {
179 @SuppressWarnings("unchecked")
Adrian Roos00a0b1f2014-07-16 16:44:49 +0200180 @Override
Adrian Roose9c7d432014-07-17 18:27:38 +0200181 protected ArrayList<UserRecord> doInBackground(SparseArray<Bitmap>... params) {
182 final SparseArray<Bitmap> bitmaps = params[0];
Adrian Roos00a0b1f2014-07-16 16:44:49 +0200183 List<UserInfo> infos = mUserManager.getUsers(true);
184 if (infos == null) {
185 return null;
186 }
187 ArrayList<UserRecord> records = new ArrayList<>(infos.size());
188 int currentId = ActivityManager.getCurrentUser();
Fyodor Kupolov07140f72016-02-17 10:46:11 -0800189 boolean allowUserSwitching = mAllowUserSwitchingWhenSystemUserLocked
190 || mUserManager.isUserUnlocked(UserHandle.SYSTEM);
Xiaohui Chen7cb69df2015-07-13 16:01:01 -0700191 UserInfo currentUserInfo = null;
Adrian Roos00a0b1f2014-07-16 16:44:49 +0200192 UserRecord guestRecord = null;
Dan Sandler4d75c072014-07-17 16:01:28 -0400193 int avatarSize = mContext.getResources()
194 .getDimensionPixelSize(R.dimen.max_avatar_size);
Adrian Roos00a0b1f2014-07-16 16:44:49 +0200195
196 for (UserInfo info : infos) {
197 boolean isCurrent = currentId == info.id;
Xiaohui Chen7cb69df2015-07-13 16:01:01 -0700198 if (isCurrent) {
199 currentUserInfo = info;
200 }
Fyodor Kupolov07140f72016-02-17 10:46:11 -0800201 boolean switchToEnabled = allowUserSwitching || isCurrent;
Lenka Trochtova1ddda472016-02-12 10:42:12 +0100202 if (info.isEnabled()) {
203 if (info.isGuest()) {
204 guestRecord = new UserRecord(info, null /* picture */,
205 true /* isGuest */, isCurrent, false /* isAddUser */,
206 false /* isRestricted */, switchToEnabled);
207 } else if (info.supportsSwitchToByUser()) {
208 Bitmap picture = bitmaps.get(info.id);
209 if (picture == null) {
210 picture = mUserManager.getUserIcon(info.id);
Adrian Rooscba0faa2014-11-17 17:41:28 +0100211
Lenka Trochtova1ddda472016-02-12 10:42:12 +0100212 if (picture != null) {
213 picture = BitmapHelper.createCircularClip(
214 picture, avatarSize, avatarSize);
215 }
Adrian Rooscba0faa2014-11-17 17:41:28 +0100216 }
Lenka Trochtova1ddda472016-02-12 10:42:12 +0100217 int index = isCurrent ? 0 : records.size();
218 records.add(index, new UserRecord(info, picture, false /* isGuest */,
219 isCurrent, false /* isAddUser */, false /* isRestricted */,
220 switchToEnabled));
Dan Sandler4d75c072014-07-17 16:01:28 -0400221 }
Adrian Roos00a0b1f2014-07-16 16:44:49 +0200222 }
223 }
224
Sudheer Shankaa8fbbb32016-02-11 17:17:57 +0000225 boolean systemCanCreateUsers = !mUserManager.hasBaseUserRestriction(
226 UserManager.DISALLOW_ADD_USER, UserHandle.SYSTEM);
Xiaohui Chen7cb69df2015-07-13 16:01:01 -0700227 boolean currentUserCanCreateUsers = currentUserInfo != null
228 && (currentUserInfo.isAdmin()
Sudheer Shankaa8fbbb32016-02-11 17:17:57 +0000229 || currentUserInfo.id == UserHandle.USER_SYSTEM)
230 && systemCanCreateUsers;
231 boolean anyoneCanCreateUsers = systemCanCreateUsers && addUsersWhenLocked;
232 boolean canCreateGuest = (currentUserCanCreateUsers || anyoneCanCreateUsers)
Adrian Roosccdff622014-08-06 00:07:18 +0200233 && guestRecord == null;
Sudheer Shankaa8fbbb32016-02-11 17:17:57 +0000234 boolean canCreateUser = (currentUserCanCreateUsers || anyoneCanCreateUsers)
Amith Yamasani95ab7842014-08-11 17:09:26 -0700235 && mUserManager.canAddMoreUsers();
Adrian Roosccdff622014-08-06 00:07:18 +0200236 boolean createIsRestricted = !addUsersWhenLocked;
237
Jason Monk2daf62c2014-07-31 14:35:06 -0400238 if (!mSimpleUserSwitcher) {
239 if (guestRecord == null) {
Adrian Roosccdff622014-08-06 00:07:18 +0200240 if (canCreateGuest) {
Sudheer Shanka1c7cda82015-12-31 14:46:02 +0000241 guestRecord = new UserRecord(null /* info */, null /* picture */,
Adrian Roosccdff622014-08-06 00:07:18 +0200242 true /* isGuest */, false /* isCurrent */,
Fyodor Kupolov07140f72016-02-17 10:46:11 -0800243 false /* isAddUser */, createIsRestricted, allowUserSwitching);
Sudheer Shankaa8fbbb32016-02-11 17:17:57 +0000244 checkIfAddUserDisallowedByAdminOnly(guestRecord);
Sudheer Shanka1c7cda82015-12-31 14:46:02 +0000245 records.add(guestRecord);
Adrian Roosccdff622014-08-06 00:07:18 +0200246 }
Jason Monk2daf62c2014-07-31 14:35:06 -0400247 } else {
Adrian Roosbed6e3b2014-08-21 20:31:41 +0200248 int index = guestRecord.isCurrent ? 0 : records.size();
249 records.add(index, guestRecord);
Jason Monk2daf62c2014-07-31 14:35:06 -0400250 }
Adrian Roos00a0b1f2014-07-16 16:44:49 +0200251 }
252
Jason Monk092be7d2014-09-02 15:26:13 -0400253 if (!mSimpleUserSwitcher && canCreateUser) {
Sudheer Shanka1c7cda82015-12-31 14:46:02 +0000254 UserRecord addUserRecord = new UserRecord(null /* info */, null /* picture */,
Adrian Roosccdff622014-08-06 00:07:18 +0200255 false /* isGuest */, false /* isCurrent */, true /* isAddUser */,
Fyodor Kupolov07140f72016-02-17 10:46:11 -0800256 createIsRestricted, allowUserSwitching);
Sudheer Shankaa8fbbb32016-02-11 17:17:57 +0000257 checkIfAddUserDisallowedByAdminOnly(addUserRecord);
Sudheer Shanka1c7cda82015-12-31 14:46:02 +0000258 records.add(addUserRecord);
Adrian Roosccdff622014-08-06 00:07:18 +0200259 }
260
Adrian Roos00a0b1f2014-07-16 16:44:49 +0200261 return records;
262 }
263
264 @Override
265 protected void onPostExecute(ArrayList<UserRecord> userRecords) {
266 if (userRecords != null) {
267 mUsers = userRecords;
268 notifyAdapters();
269 }
270 }
Adrian Roosccdff622014-08-06 00:07:18 +0200271 }.execute((SparseArray) bitmaps);
Adrian Roos00a0b1f2014-07-16 16:44:49 +0200272 }
273
Adrian Roos88b11932015-07-22 14:59:48 -0700274 private void pauseRefreshUsers() {
275 if (!mPauseRefreshUsers) {
276 mHandler.postDelayed(mUnpauseRefreshUsers, PAUSE_REFRESH_USERS_TIMEOUT_MS);
277 mPauseRefreshUsers = true;
278 }
279 }
280
Adrian Roos00a0b1f2014-07-16 16:44:49 +0200281 private void notifyAdapters() {
282 for (int i = mAdapters.size() - 1; i >= 0; i--) {
283 BaseUserAdapter adapter = mAdapters.get(i).get();
284 if (adapter != null) {
285 adapter.notifyDataSetChanged();
286 } else {
287 mAdapters.remove(i);
288 }
289 }
290 }
291
Jason Monk2daf62c2014-07-31 14:35:06 -0400292 public boolean isSimpleUserSwitcher() {
293 return mSimpleUserSwitcher;
294 }
295
Xiyuan Xiacc3a74f62015-07-22 14:16:34 -0700296 public boolean useFullscreenUserSwitcher() {
297 // Use adb to override:
298 // adb shell settings put system enable_fullscreen_user_switcher 0 # Turn it off.
299 // adb shell settings put system enable_fullscreen_user_switcher 1 # Turn it on.
300 // Restart SystemUI or adb reboot.
301 final int DEFAULT = -1;
302 final int overrideUseFullscreenUserSwitcher =
303 Settings.System.getInt(mContext.getContentResolver(),
304 "enable_fullscreen_user_switcher", DEFAULT);
305 if (overrideUseFullscreenUserSwitcher != DEFAULT) {
306 return overrideUseFullscreenUserSwitcher != 0;
307 }
308 // Otherwise default to the build setting.
Xiyuan Xia40f9dab2015-08-17 13:19:30 -0700309 return mContext.getResources().getBoolean(R.bool.config_enableFullscreenUserSwitcher);
Xiyuan Xiacc3a74f62015-07-22 14:16:34 -0700310 }
311
Xiyuan Xia1b30f792016-01-06 08:50:30 -0800312 public void logoutCurrentUser() {
313 int currentUser = ActivityManager.getCurrentUser();
314 if (currentUser != UserHandle.USER_SYSTEM) {
315 switchToUserId(UserHandle.USER_SYSTEM);
316 stopUserId(currentUser);
317 }
318 }
319
Xiyuan Xiacc3a74f62015-07-22 14:16:34 -0700320 public void removeUserId(int userId) {
321 if (userId == UserHandle.USER_SYSTEM) {
322 Log.w(TAG, "User " + userId + " could not removed.");
323 return;
324 }
325 if (ActivityManager.getCurrentUser() == userId) {
326 switchToUserId(UserHandle.USER_SYSTEM);
327 }
328 if (mUserManager.removeUser(userId)) {
329 refreshUsers(UserHandle.USER_NULL);
330 }
331 }
332
Adrian Roos00a0b1f2014-07-16 16:44:49 +0200333 public void switchTo(UserRecord record) {
334 int id;
335 if (record.isGuest && record.info == null) {
336 // No guest user. Create one.
Adrian Roosf99727c2014-09-17 16:15:07 +0200337 UserInfo guest = mUserManager.createGuest(
338 mContext, mContext.getString(R.string.guest_nickname));
339 if (guest == null) {
340 // Couldn't create guest, most likely because there already exists one, we just
341 // haven't reloaded the user list yet.
342 return;
343 }
344 id = guest.id;
Adrian Roosccdff622014-08-06 00:07:18 +0200345 } else if (record.isAddUser) {
Adrian Roos0c6763a2014-09-08 19:11:00 +0200346 showAddUserDialog();
347 return;
Adrian Roos00a0b1f2014-07-16 16:44:49 +0200348 } else {
349 id = record.info.id;
350 }
351
352 if (ActivityManager.getCurrentUser() == id) {
Adrian Roose9c7d432014-07-17 18:27:38 +0200353 if (record.isGuest) {
Adrian Roos50052442014-07-17 23:35:18 +0200354 showExitGuestDialog(id);
Adrian Roose9c7d432014-07-17 18:27:38 +0200355 }
Adrian Roos00a0b1f2014-07-16 16:44:49 +0200356 return;
357 }
358
Adrian Roose9c7d432014-07-17 18:27:38 +0200359 switchToUserId(id);
360 }
361
Xiyuan Xia1b30f792016-01-06 08:50:30 -0800362 public void switchTo(int userId) {
363 final int count = mUsers.size();
364 for (int i = 0; i < count; ++i) {
365 UserRecord record = mUsers.get(i);
366 if (record.info != null && record.info.id == userId) {
367 switchTo(record);
368 return;
369 }
370 }
371
372 Log.e(TAG, "Couldn't switch to user, id=" + userId);
373 }
374
Adrian Roose9c7d432014-07-17 18:27:38 +0200375 private void switchToUserId(int id) {
Adrian Roos00a0b1f2014-07-16 16:44:49 +0200376 try {
Adrian Roos88b11932015-07-22 14:59:48 -0700377 pauseRefreshUsers();
Adrian Roos00a0b1f2014-07-16 16:44:49 +0200378 ActivityManagerNative.getDefault().switchUser(id);
379 } catch (RemoteException e) {
380 Log.e(TAG, "Couldn't switch user.", e);
381 }
382 }
383
Xiaohui Chen860397f2015-07-22 15:03:48 -0700384 private void stopUserId(int id) {
385 try {
Fyodor Kupolov9cbfc9e2015-10-07 15:52:33 -0700386 ActivityManagerNative.getDefault().stopUser(id, /* force= */ false, null);
Xiaohui Chen860397f2015-07-22 15:03:48 -0700387 } catch (RemoteException e) {
388 Log.e(TAG, "Couldn't stop user.", e);
389 }
390 }
391
Adrian Roos50052442014-07-17 23:35:18 +0200392 private void showExitGuestDialog(int id) {
393 if (mExitGuestDialog != null && mExitGuestDialog.isShowing()) {
394 mExitGuestDialog.cancel();
395 }
396 mExitGuestDialog = new ExitGuestDialog(mContext, id);
397 mExitGuestDialog.show();
398 }
399
Adrian Roos0c6763a2014-09-08 19:11:00 +0200400 private void showAddUserDialog() {
401 if (mAddUserDialog != null && mAddUserDialog.isShowing()) {
402 mAddUserDialog.cancel();
403 }
404 mAddUserDialog = new AddUserDialog(mContext);
405 mAddUserDialog.show();
406 }
407
Adrian Roose9c7d432014-07-17 18:27:38 +0200408 private void exitGuest(int id) {
Xiaohui Chen7cb69df2015-07-13 16:01:01 -0700409 int newId = UserHandle.USER_SYSTEM;
410 if (mLastNonGuestUser != UserHandle.USER_SYSTEM) {
Adrian Roos70441462014-07-22 16:03:12 +0200411 UserInfo info = mUserManager.getUserInfo(mLastNonGuestUser);
Xiaohui Chen7cb69df2015-07-13 16:01:01 -0700412 if (info != null && info.isEnabled() && info.supportsSwitchToByUser()) {
Adrian Roos70441462014-07-22 16:03:12 +0200413 newId = info.id;
414 }
415 }
416 switchToUserId(newId);
Adrian Roose9c7d432014-07-17 18:27:38 +0200417 mUserManager.removeUser(id);
418 }
419
Adrian Roos00a0b1f2014-07-16 16:44:49 +0200420 private BroadcastReceiver mReceiver = new BroadcastReceiver() {
421 @Override
422 public void onReceive(Context context, Intent intent) {
Adrian Roos50052442014-07-17 23:35:18 +0200423 if (DEBUG) {
424 Log.v(TAG, "Broadcast: a=" + intent.getAction()
425 + " user=" + intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1));
426 }
Adrian Roos88b11932015-07-22 14:59:48 -0700427
428 boolean unpauseRefreshUsers = false;
429 int forcePictureLoadForId = UserHandle.USER_NULL;
430
Fyodor Kupolovf4d6ad22015-04-13 11:52:18 -0700431 if (ACTION_REMOVE_GUEST.equals(intent.getAction())) {
432 int currentUser = ActivityManager.getCurrentUser();
433 UserInfo userInfo = mUserManager.getUserInfo(currentUser);
434 if (userInfo != null && userInfo.isGuest()) {
435 showExitGuestDialog(currentUser);
436 }
437 return;
Adrian Roos80996bb2015-07-24 16:38:58 -0700438 } else if (ACTION_LOGOUT_USER.equals(intent.getAction())) {
Xiyuan Xia1b30f792016-01-06 08:50:30 -0800439 logoutCurrentUser();
Adrian Roos88b11932015-07-22 14:59:48 -0700440 } else if (Intent.ACTION_USER_SWITCHED.equals(intent.getAction())) {
Adrian Roos50052442014-07-17 23:35:18 +0200441 if (mExitGuestDialog != null && mExitGuestDialog.isShowing()) {
442 mExitGuestDialog.cancel();
443 mExitGuestDialog = null;
444 }
445
Adrian Roos00a0b1f2014-07-16 16:44:49 +0200446 final int currentId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
Xiaohui Chen7cb69df2015-07-13 16:01:01 -0700447 final UserInfo userInfo = mUserManager.getUserInfo(currentId);
Adrian Roos00a0b1f2014-07-16 16:44:49 +0200448 final int N = mUsers.size();
449 for (int i = 0; i < N; i++) {
450 UserRecord record = mUsers.get(i);
Adrian Roose9c7d432014-07-17 18:27:38 +0200451 if (record.info == null) continue;
Adrian Roos00a0b1f2014-07-16 16:44:49 +0200452 boolean shouldBeCurrent = record.info.id == currentId;
453 if (record.isCurrent != shouldBeCurrent) {
454 mUsers.set(i, record.copyWithIsCurrent(shouldBeCurrent));
455 }
Adrian Roos70441462014-07-22 16:03:12 +0200456 if (shouldBeCurrent && !record.isGuest) {
457 mLastNonGuestUser = record.info.id;
458 }
Xiaohui Chen7cb69df2015-07-13 16:01:01 -0700459 if ((userInfo == null || !userInfo.isAdmin()) && record.isRestricted) {
Adrian Roosccdff622014-08-06 00:07:18 +0200460 // Immediately remove restricted records in case the AsyncTask is too slow.
461 mUsers.remove(i);
462 i--;
463 }
Adrian Roos00a0b1f2014-07-16 16:44:49 +0200464 }
465 notifyAdapters();
Xiaohui Chen860397f2015-07-22 15:03:48 -0700466
467 if (UserManager.isSplitSystemUser() && userInfo != null && !userInfo.isGuest()
468 && userInfo.id != UserHandle.USER_SYSTEM) {
469 showLogoutNotification(currentId);
470 }
Fyodor Kupolovce161862015-08-18 12:41:52 -0700471 if (userInfo != null && userInfo.isGuest()) {
472 showGuestNotification(currentId);
473 }
Adrian Roos88b11932015-07-22 14:59:48 -0700474 unpauseRefreshUsers = true;
475 } else if (Intent.ACTION_USER_INFO_CHANGED.equals(intent.getAction())) {
Adrian Roose9c7d432014-07-17 18:27:38 +0200476 forcePictureLoadForId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE,
477 UserHandle.USER_NULL);
Fyodor Kupolov07140f72016-02-17 10:46:11 -0800478 } else if (Intent.ACTION_USER_UNLOCKED.equals(intent.getAction())) {
479 // Unlocking the system user may require a refresh
480 int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL);
481 if (userId != UserHandle.USER_SYSTEM) {
482 return;
483 }
Adrian Roose9c7d432014-07-17 18:27:38 +0200484 }
485 refreshUsers(forcePictureLoadForId);
Adrian Roos88b11932015-07-22 14:59:48 -0700486 if (unpauseRefreshUsers) {
487 mUnpauseRefreshUsers.run();
488 }
Adrian Roos00a0b1f2014-07-16 16:44:49 +0200489 }
Fyodor Kupolovf4d6ad22015-04-13 11:52:18 -0700490
491 private void showGuestNotification(int guestUserId) {
492 PendingIntent removeGuestPI = PendingIntent.getBroadcastAsUser(mContext,
Xiaohui Chen7cb69df2015-07-13 16:01:01 -0700493 0, new Intent(ACTION_REMOVE_GUEST), 0, UserHandle.SYSTEM);
Fyodor Kupolovf4d6ad22015-04-13 11:52:18 -0700494 Notification notification = new Notification.Builder(mContext)
495 .setVisibility(Notification.VISIBILITY_SECRET)
496 .setPriority(Notification.PRIORITY_MIN)
497 .setSmallIcon(R.drawable.ic_person)
498 .setContentTitle(mContext.getString(R.string.guest_notification_title))
499 .setContentText(mContext.getString(R.string.guest_notification_text))
Fyodor Kupolov52408f42015-08-17 16:34:07 -0700500 .setContentIntent(removeGuestPI)
Fyodor Kupolovf4d6ad22015-04-13 11:52:18 -0700501 .setShowWhen(false)
502 .addAction(R.drawable.ic_delete,
503 mContext.getString(R.string.guest_notification_remove_action),
504 removeGuestPI)
505 .build();
Amith Yamasanid81f8272015-07-23 17:15:45 -0700506 NotificationManager.from(mContext).notifyAsUser(TAG_REMOVE_GUEST, ID_REMOVE_GUEST,
507 notification, new UserHandle(guestUserId));
Fyodor Kupolovf4d6ad22015-04-13 11:52:18 -0700508 }
Xiaohui Chen860397f2015-07-22 15:03:48 -0700509
510 private void showLogoutNotification(int userId) {
511 PendingIntent logoutPI = PendingIntent.getBroadcastAsUser(mContext,
512 0, new Intent(ACTION_LOGOUT_USER), 0, UserHandle.SYSTEM);
513 Notification notification = new Notification.Builder(mContext)
514 .setVisibility(Notification.VISIBILITY_SECRET)
515 .setPriority(Notification.PRIORITY_MIN)
516 .setSmallIcon(R.drawable.ic_person)
517 .setContentTitle(mContext.getString(R.string.user_logout_notification_title))
518 .setContentText(mContext.getString(R.string.user_logout_notification_text))
Fyodor Kupolov52408f42015-08-17 16:34:07 -0700519 .setContentIntent(logoutPI)
Fyodor Kupolovce161862015-08-18 12:41:52 -0700520 .setOngoing(true)
Xiaohui Chen860397f2015-07-22 15:03:48 -0700521 .setShowWhen(false)
522 .addAction(R.drawable.ic_delete,
523 mContext.getString(R.string.user_logout_notification_action),
524 logoutPI)
525 .build();
526 NotificationManager.from(mContext).notifyAsUser(TAG_LOGOUT_USER, ID_LOGOUT_USER,
527 notification, new UserHandle(userId));
528 }
Adrian Roos00a0b1f2014-07-16 16:44:49 +0200529 };
530
Adrian Roos88b11932015-07-22 14:59:48 -0700531 private final Runnable mUnpauseRefreshUsers = new Runnable() {
532 @Override
533 public void run() {
534 mHandler.removeCallbacks(this);
535 mPauseRefreshUsers = false;
536 refreshUsers(UserHandle.USER_NULL);
537 }
538 };
539
Adrian Roosccdff622014-08-06 00:07:18 +0200540 private final ContentObserver mSettingsObserver = new ContentObserver(new Handler()) {
Jason Monk2daf62c2014-07-31 14:35:06 -0400541 public void onChange(boolean selfChange) {
542 mSimpleUserSwitcher = Settings.Global.getInt(mContext.getContentResolver(),
543 SIMPLE_USER_SWITCHER_GLOBAL_SETTING, 0) != 0;
Adrian Roosccdff622014-08-06 00:07:18 +0200544 mAddUsersWhenLocked = Settings.Global.getInt(mContext.getContentResolver(),
545 Settings.Global.ADD_USERS_WHEN_LOCKED, 0) != 0;
Fyodor Kupolov07140f72016-02-17 10:46:11 -0800546 mAllowUserSwitchingWhenSystemUserLocked = Settings.Global.getInt(
547 mContext.getContentResolver(),
548 Settings.Global.ALLOW_USER_SWITCHING_WHEN_SYSTEM_USER_LOCKED, 0) != 0;
Jason Monk2daf62c2014-07-31 14:35:06 -0400549 refreshUsers(UserHandle.USER_NULL);
550 };
551 };
552
Adrian Roos00a0b1f2014-07-16 16:44:49 +0200553 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
554 pw.println("UserSwitcherController state:");
Adrian Roos70441462014-07-22 16:03:12 +0200555 pw.println(" mLastNonGuestUser=" + mLastNonGuestUser);
Adrian Roos00a0b1f2014-07-16 16:44:49 +0200556 pw.print(" mUsers.size="); pw.println(mUsers.size());
557 for (int i = 0; i < mUsers.size(); i++) {
558 final UserRecord u = mUsers.get(i);
559 pw.print(" "); pw.println(u.toString());
560 }
561 }
562
Adrian Roos57cf5702014-09-03 15:56:30 +0200563 public String getCurrentUserName(Context context) {
564 if (mUsers.isEmpty()) return null;
565 UserRecord item = mUsers.get(0);
566 if (item == null || item.info == null) return null;
567 if (item.isGuest) return context.getString(R.string.guest_nickname);
568 return item.info.name;
569 }
570
Adrian Roos00a0b1f2014-07-16 16:44:49 +0200571 public static abstract class BaseUserAdapter extends BaseAdapter {
572
573 final UserSwitcherController mController;
574
575 protected BaseUserAdapter(UserSwitcherController controller) {
576 mController = controller;
577 controller.mAdapters.add(new WeakReference<>(this));
578 }
579
580 @Override
581 public int getCount() {
Adrian Roosccdff622014-08-06 00:07:18 +0200582 boolean secureKeyguardShowing = mController.mKeyguardMonitor.isShowing()
Jason Monk8a3a9642015-06-05 11:01:30 -0400583 && mController.mKeyguardMonitor.isSecure()
Selim Cineke8bae622015-07-15 13:24:06 -0700584 && !mController.mKeyguardMonitor.canSkipBouncer();
Adrian Roosccdff622014-08-06 00:07:18 +0200585 if (!secureKeyguardShowing) {
586 return mController.mUsers.size();
587 }
588 // The lock screen is secure and showing. Filter out restricted records.
589 final int N = mController.mUsers.size();
590 int count = 0;
591 for (int i = 0; i < N; i++) {
592 if (mController.mUsers.get(i).isRestricted) {
593 break;
594 } else {
595 count++;
596 }
597 }
598 return count;
Adrian Roos00a0b1f2014-07-16 16:44:49 +0200599 }
600
601 @Override
602 public UserRecord getItem(int position) {
603 return mController.mUsers.get(position);
604 }
605
606 @Override
607 public long getItemId(int position) {
Adrian Roose9c7d432014-07-17 18:27:38 +0200608 return position;
Adrian Roos00a0b1f2014-07-16 16:44:49 +0200609 }
610
611 public void switchTo(UserRecord record) {
612 mController.switchTo(record);
613 }
Adrian Roose9c7d432014-07-17 18:27:38 +0200614
615 public String getName(Context context, UserRecord item) {
616 if (item.isGuest) {
617 if (item.isCurrent) {
618 return context.getString(R.string.guest_exit_guest);
619 } else {
620 return context.getString(
621 item.info == null ? R.string.guest_new_guest : R.string.guest_nickname);
622 }
Adrian Roosccdff622014-08-06 00:07:18 +0200623 } else if (item.isAddUser) {
624 return context.getString(R.string.user_add_user);
Adrian Roose9c7d432014-07-17 18:27:38 +0200625 } else {
626 return item.info.name;
627 }
628 }
Adrian Roos723632e2014-07-23 21:13:21 +0200629
Adrian Roosccdff622014-08-06 00:07:18 +0200630 public Drawable getDrawable(Context context, UserRecord item) {
631 if (item.isAddUser) {
632 return context.getDrawable(R.drawable.ic_add_circle_qs);
633 }
Alexandra Gherghina64d4dca2014-08-28 18:26:56 +0100634 return UserIcons.getDefaultUserIcon(item.isGuest ? UserHandle.USER_NULL : item.info.id,
635 /* light= */ true);
Adrian Roosccdff622014-08-06 00:07:18 +0200636 }
Adrian Roos844c92b2014-12-01 14:19:05 +0100637
638 public void refresh() {
639 mController.refreshUsers(UserHandle.USER_NULL);
640 }
Adrian Roos00a0b1f2014-07-16 16:44:49 +0200641 }
642
Sudheer Shankaa8fbbb32016-02-11 17:17:57 +0000643 private void checkIfAddUserDisallowedByAdminOnly(UserRecord record) {
Sudheer Shanka1c7cda82015-12-31 14:46:02 +0000644 EnforcedAdmin admin = RestrictedLockUtils.checkIfRestrictionEnforced(mContext,
Sudheer Shankab6fc9312016-01-27 19:59:03 +0000645 UserManager.DISALLOW_ADD_USER, ActivityManager.getCurrentUser());
Sudheer Shankaa8fbbb32016-02-11 17:17:57 +0000646 if (admin != null && !RestrictedLockUtils.hasBaseUserRestriction(mContext,
647 UserManager.DISALLOW_ADD_USER, ActivityManager.getCurrentUser())) {
Sudheer Shanka1c7cda82015-12-31 14:46:02 +0000648 record.isDisabledByAdmin = true;
649 record.enforcedAdmin = admin;
650 } else {
651 record.isDisabledByAdmin = false;
652 record.enforcedAdmin = null;
653 }
654 }
655
656 public void startActivity(Intent intent) {
657 mActivityStarter.startActivity(intent, true);
658 }
659
Adrian Roos00a0b1f2014-07-16 16:44:49 +0200660 public static final class UserRecord {
661 public final UserInfo info;
662 public final Bitmap picture;
663 public final boolean isGuest;
664 public final boolean isCurrent;
Adrian Roosccdff622014-08-06 00:07:18 +0200665 public final boolean isAddUser;
666 /** If true, the record is only visible to the owner and only when unlocked. */
667 public final boolean isRestricted;
Sudheer Shanka1c7cda82015-12-31 14:46:02 +0000668 public boolean isDisabledByAdmin;
669 public EnforcedAdmin enforcedAdmin;
Fyodor Kupolov07140f72016-02-17 10:46:11 -0800670 public boolean isSwitchToEnabled;
Adrian Roos00a0b1f2014-07-16 16:44:49 +0200671
Adrian Roosccdff622014-08-06 00:07:18 +0200672 public UserRecord(UserInfo info, Bitmap picture, boolean isGuest, boolean isCurrent,
Fyodor Kupolov07140f72016-02-17 10:46:11 -0800673 boolean isAddUser, boolean isRestricted, boolean isSwitchToEnabled) {
Adrian Roos00a0b1f2014-07-16 16:44:49 +0200674 this.info = info;
675 this.picture = picture;
676 this.isGuest = isGuest;
677 this.isCurrent = isCurrent;
Adrian Roosccdff622014-08-06 00:07:18 +0200678 this.isAddUser = isAddUser;
679 this.isRestricted = isRestricted;
Fyodor Kupolov07140f72016-02-17 10:46:11 -0800680 this.isSwitchToEnabled = isSwitchToEnabled;
Adrian Roos00a0b1f2014-07-16 16:44:49 +0200681 }
682
683 public UserRecord copyWithIsCurrent(boolean _isCurrent) {
Fyodor Kupolov07140f72016-02-17 10:46:11 -0800684 return new UserRecord(info, picture, isGuest, _isCurrent, isAddUser, isRestricted,
685 isSwitchToEnabled);
Adrian Roos00a0b1f2014-07-16 16:44:49 +0200686 }
687
688 public String toString() {
689 StringBuilder sb = new StringBuilder();
690 sb.append("UserRecord(");
691 if (info != null) {
Fyodor Kupolov07140f72016-02-17 10:46:11 -0800692 sb.append("name=\"").append(info.name).append("\" id=").append(info.id);
Adrian Roos00a0b1f2014-07-16 16:44:49 +0200693 } else {
Adrian Roosccdff622014-08-06 00:07:18 +0200694 if (isGuest) {
695 sb.append("<add guest placeholder>");
696 } else if (isAddUser) {
697 sb.append("<add user placeholder>");
698 }
Adrian Roos00a0b1f2014-07-16 16:44:49 +0200699 }
Adrian Roosccdff622014-08-06 00:07:18 +0200700 if (isGuest) sb.append(" <isGuest>");
701 if (isAddUser) sb.append(" <isAddUser>");
702 if (isCurrent) sb.append(" <isCurrent>");
703 if (picture != null) sb.append(" <hasPicture>");
704 if (isRestricted) sb.append(" <isRestricted>");
Sudheer Shanka1c7cda82015-12-31 14:46:02 +0000705 if (isDisabledByAdmin) {
706 sb.append(" <isDisabledByAdmin>");
Fyodor Kupolov07140f72016-02-17 10:46:11 -0800707 sb.append(" enforcedAdmin=").append(enforcedAdmin);
708 }
709 if (isSwitchToEnabled) {
710 sb.append(" <isSwitchToEnabled>");
Sudheer Shanka1c7cda82015-12-31 14:46:02 +0000711 }
Adrian Roos00a0b1f2014-07-16 16:44:49 +0200712 sb.append(')');
713 return sb.toString();
714 }
715 }
716
717 public final QSTile.DetailAdapter userDetailAdapter = new QSTile.DetailAdapter() {
Jason Monk76c67aa2016-02-19 14:49:42 -0500718 private final Intent USER_SETTINGS_INTENT = new Intent(Settings.ACTION_USER_SETTINGS);
Adrian Roos00a0b1f2014-07-16 16:44:49 +0200719
720 @Override
Jason Monkc06fbb12016-01-08 14:12:18 -0500721 public CharSequence getTitle() {
722 return mContext.getString(R.string.quick_settings_user_title);
Adrian Roos00a0b1f2014-07-16 16:44:49 +0200723 }
724
725 @Override
726 public View createDetailView(Context context, View convertView, ViewGroup parent) {
Adrian Roos19408922014-08-07 20:54:12 +0200727 UserDetailView v;
Adrian Roos00a0b1f2014-07-16 16:44:49 +0200728 if (!(convertView instanceof UserDetailView)) {
Adrian Roos19408922014-08-07 20:54:12 +0200729 v = UserDetailView.inflate(context, parent, false);
Adrian Roos00a0b1f2014-07-16 16:44:49 +0200730 v.createAndSetAdapter(UserSwitcherController.this);
Adrian Roos19408922014-08-07 20:54:12 +0200731 } else {
732 v = (UserDetailView) convertView;
Adrian Roos00a0b1f2014-07-16 16:44:49 +0200733 }
Adrian Roos844c92b2014-12-01 14:19:05 +0100734 v.refreshAdapter();
Adrian Roos00a0b1f2014-07-16 16:44:49 +0200735 return v;
736 }
737
738 @Override
739 public Intent getSettingsIntent() {
740 return USER_SETTINGS_INTENT;
741 }
742
743 @Override
744 public Boolean getToggleState() {
745 return null;
746 }
747
748 @Override
749 public void setToggleState(boolean state) {
750 }
Chris Wren457a21c2015-05-06 17:50:34 -0400751
752 @Override
753 public int getMetricsCategory() {
Chris Wrenf6e9228b2016-01-26 18:04:35 -0500754 return MetricsEvent.QS_USERDETAIL;
Chris Wren457a21c2015-05-06 17:50:34 -0400755 }
Adrian Roos00a0b1f2014-07-16 16:44:49 +0200756 };
Adrian Roos50052442014-07-17 23:35:18 +0200757
Adrian Roosccdff622014-08-06 00:07:18 +0200758 private final KeyguardMonitor.Callback mCallback = new KeyguardMonitor.Callback() {
759 @Override
760 public void onKeyguardChanged() {
761 notifyAdapters();
762 }
763 };
764
Adrian Roos50052442014-07-17 23:35:18 +0200765 private final class ExitGuestDialog extends SystemUIDialog implements
766 DialogInterface.OnClickListener {
767
768 private final int mGuestId;
769
770 public ExitGuestDialog(Context context, int guestId) {
771 super(context);
772 setTitle(R.string.guest_exit_guest_dialog_title);
773 setMessage(context.getString(R.string.guest_exit_guest_dialog_message));
774 setButton(DialogInterface.BUTTON_NEGATIVE,
Amith Yamasanie5b274a2014-08-18 07:57:56 -0700775 context.getString(android.R.string.cancel), this);
Adrian Roos50052442014-07-17 23:35:18 +0200776 setButton(DialogInterface.BUTTON_POSITIVE,
Amith Yamasanie5b274a2014-08-18 07:57:56 -0700777 context.getString(R.string.guest_exit_guest_dialog_remove), this);
Adrian Roos50052442014-07-17 23:35:18 +0200778 setCanceledOnTouchOutside(false);
779 mGuestId = guestId;
780 }
781
782 @Override
783 public void onClick(DialogInterface dialog, int which) {
784 if (which == BUTTON_NEGATIVE) {
785 cancel();
786 } else {
787 dismiss();
788 exitGuest(mGuestId);
789 }
790 }
791 }
Adrian Roos0c6763a2014-09-08 19:11:00 +0200792
793 private final class AddUserDialog extends SystemUIDialog implements
794 DialogInterface.OnClickListener {
795
796 public AddUserDialog(Context context) {
797 super(context);
798 setTitle(R.string.user_add_user_title);
799 setMessage(context.getString(R.string.user_add_user_message_short));
800 setButton(DialogInterface.BUTTON_NEGATIVE,
801 context.getString(android.R.string.cancel), this);
802 setButton(DialogInterface.BUTTON_POSITIVE,
803 context.getString(android.R.string.ok), this);
804 }
805
806 @Override
807 public void onClick(DialogInterface dialog, int which) {
808 if (which == BUTTON_NEGATIVE) {
809 cancel();
810 } else {
811 dismiss();
Guang Zhuccbeb612014-10-21 14:33:50 -0700812 if (ActivityManager.isUserAMonkey()) {
813 return;
814 }
Xiaohui Chencfe64c82015-07-16 14:30:50 -0700815 UserInfo user = mUserManager.createUser(
Adrian Roosf99727c2014-09-17 16:15:07 +0200816 mContext.getString(R.string.user_new_user_name), 0 /* flags */);
817 if (user == null) {
818 // Couldn't create user, most likely because there are too many, but we haven't
819 // been able to reload the list yet.
820 return;
821 }
822 int id = user.id;
Alexandra Gherghina64d4dca2014-08-28 18:26:56 +0100823 Bitmap icon = UserIcons.convertToBitmap(UserIcons.getDefaultUserIcon(
824 id, /* light= */ false));
825 mUserManager.setUserIcon(id, icon);
Adrian Roos0c6763a2014-09-08 19:11:00 +0200826 switchToUserId(id);
827 }
828 }
829 }
Adrian Roos00a0b1f2014-07-16 16:44:49 +0200830}