• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 
17 package com.android.systemui.statusbar.policy;
18 
19 import static android.os.UserManager.SWITCHABILITY_STATUS_OK;
20 
21 import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
22 import static com.android.systemui.DejankUtils.whitelistIpcs;
23 
24 import android.annotation.UserIdInt;
25 import android.app.ActivityManager;
26 import android.app.AlertDialog;
27 import android.app.Dialog;
28 import android.app.IActivityTaskManager;
29 import android.app.admin.DevicePolicyManager;
30 import android.content.BroadcastReceiver;
31 import android.content.Context;
32 import android.content.DialogInterface;
33 import android.content.Intent;
34 import android.content.IntentFilter;
35 import android.content.pm.UserInfo;
36 import android.database.ContentObserver;
37 import android.graphics.Bitmap;
38 import android.graphics.ColorFilter;
39 import android.graphics.ColorMatrix;
40 import android.graphics.ColorMatrixColorFilter;
41 import android.graphics.drawable.Drawable;
42 import android.os.AsyncTask;
43 import android.os.Handler;
44 import android.os.RemoteException;
45 import android.os.UserHandle;
46 import android.os.UserManager;
47 import android.provider.Settings;
48 import android.telephony.TelephonyCallback;
49 import android.util.Log;
50 import android.util.SparseArray;
51 import android.util.SparseBooleanArray;
52 import android.view.View;
53 import android.view.ViewGroup;
54 import android.view.WindowManagerGlobal;
55 import android.widget.BaseAdapter;
56 
57 import com.android.internal.annotations.VisibleForTesting;
58 import com.android.internal.logging.UiEventLogger;
59 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
60 import com.android.settingslib.RestrictedLockUtilsInternal;
61 import com.android.systemui.Dumpable;
62 import com.android.systemui.GuestResumeSessionReceiver;
63 import com.android.systemui.Prefs;
64 import com.android.systemui.Prefs.Key;
65 import com.android.systemui.R;
66 import com.android.systemui.SystemUISecondaryUserService;
67 import com.android.systemui.broadcast.BroadcastDispatcher;
68 import com.android.systemui.dagger.SysUISingleton;
69 import com.android.systemui.dagger.qualifiers.Background;
70 import com.android.systemui.dagger.qualifiers.Main;
71 import com.android.systemui.plugins.ActivityStarter;
72 import com.android.systemui.plugins.FalsingManager;
73 import com.android.systemui.plugins.qs.DetailAdapter;
74 import com.android.systemui.qs.QSUserSwitcherEvent;
75 import com.android.systemui.qs.tiles.UserDetailView;
76 import com.android.systemui.settings.UserTracker;
77 import com.android.systemui.statusbar.phone.SystemUIDialog;
78 import com.android.systemui.telephony.TelephonyListenerManager;
79 import com.android.systemui.user.CreateUserActivity;
80 import com.android.systemui.util.settings.SecureSettings;
81 
82 import java.io.FileDescriptor;
83 import java.io.PrintWriter;
84 import java.lang.ref.WeakReference;
85 import java.util.ArrayList;
86 import java.util.List;
87 import java.util.concurrent.Executor;
88 import java.util.concurrent.atomic.AtomicBoolean;
89 
90 import javax.inject.Inject;
91 import javax.inject.Provider;
92 
93 /**
94  * Keeps a list of all users on the device for user switching.
95  */
96 @SysUISingleton
97 public class UserSwitcherController implements Dumpable {
98 
99     public static final float USER_SWITCH_ENABLED_ALPHA = 1.0f;
100     public static final float USER_SWITCH_DISABLED_ALPHA = 0.38f;
101 
102     private static final String TAG = "UserSwitcherController";
103     private static final boolean DEBUG = false;
104     private static final String SIMPLE_USER_SWITCHER_GLOBAL_SETTING =
105             "lockscreenSimpleUserSwitcher";
106     private static final int PAUSE_REFRESH_USERS_TIMEOUT_MS = 3000;
107 
108     private static final String PERMISSION_SELF = "com.android.systemui.permission.SELF";
109 
110     protected final Context mContext;
111     protected final UserTracker mUserTracker;
112     protected final UserManager mUserManager;
113     private final ContentObserver mSettingsObserver;
114     private final ArrayList<WeakReference<BaseUserAdapter>> mAdapters = new ArrayList<>();
115     @VisibleForTesting
116     final GuestResumeSessionReceiver mGuestResumeSessionReceiver;
117     private final KeyguardStateController mKeyguardStateController;
118     private final DeviceProvisionedController mDeviceProvisionedController;
119     private final DevicePolicyManager mDevicePolicyManager;
120     protected final Handler mHandler;
121     private final ActivityStarter mActivityStarter;
122     private final BroadcastDispatcher mBroadcastDispatcher;
123     private final TelephonyListenerManager mTelephonyListenerManager;
124     private final IActivityTaskManager mActivityTaskManager;
125 
126     private ArrayList<UserRecord> mUsers = new ArrayList<>();
127     @VisibleForTesting
128     AlertDialog mExitGuestDialog;
129     @VisibleForTesting
130     Dialog mAddUserDialog;
131     private int mLastNonGuestUser = UserHandle.USER_SYSTEM;
132     private boolean mResumeUserOnGuestLogout = true;
133     private boolean mSimpleUserSwitcher;
134     // When false, there won't be any visual affordance to add a new user from the keyguard even if
135     // the user is unlocked
136     private boolean mAddUsersFromLockScreen;
137     @VisibleForTesting
138     boolean mPauseRefreshUsers;
139     private int mSecondaryUser = UserHandle.USER_NULL;
140     private Intent mSecondaryUserServiceIntent;
141     private SparseBooleanArray mForcePictureLoadForUserId = new SparseBooleanArray(2);
142     private final UiEventLogger mUiEventLogger;
143     public final DetailAdapter mUserDetailAdapter;
144     private final Executor mBgExecutor;
145     private final boolean mGuestUserAutoCreated;
146     private final AtomicBoolean mGuestIsResetting;
147     private final AtomicBoolean mGuestCreationScheduled;
148     private FalsingManager mFalsingManager;
149 
150     @Inject
UserSwitcherController(Context context, UserManager userManager, UserTracker userTracker, KeyguardStateController keyguardStateController, DeviceProvisionedController deviceProvisionedController, DevicePolicyManager devicePolicyManager, @Main Handler handler, ActivityStarter activityStarter, BroadcastDispatcher broadcastDispatcher, UiEventLogger uiEventLogger, FalsingManager falsingManager, TelephonyListenerManager telephonyListenerManager, IActivityTaskManager activityTaskManager, UserDetailAdapter userDetailAdapter, SecureSettings secureSettings, @Background Executor bgExecutor)151     public UserSwitcherController(Context context,
152             UserManager userManager,
153             UserTracker userTracker,
154             KeyguardStateController keyguardStateController,
155             DeviceProvisionedController deviceProvisionedController,
156             DevicePolicyManager devicePolicyManager,
157             @Main Handler handler,
158             ActivityStarter activityStarter,
159             BroadcastDispatcher broadcastDispatcher,
160             UiEventLogger uiEventLogger,
161             FalsingManager falsingManager,
162             TelephonyListenerManager telephonyListenerManager,
163             IActivityTaskManager activityTaskManager,
164             UserDetailAdapter userDetailAdapter,
165             SecureSettings secureSettings,
166             @Background Executor bgExecutor) {
167         mContext = context;
168         mUserTracker = userTracker;
169         mBroadcastDispatcher = broadcastDispatcher;
170         mTelephonyListenerManager = telephonyListenerManager;
171         mActivityTaskManager = activityTaskManager;
172         mUiEventLogger = uiEventLogger;
173         mFalsingManager = falsingManager;
174         mGuestResumeSessionReceiver = new GuestResumeSessionReceiver(
175                 this, mUserTracker, mUiEventLogger, secureSettings);
176         mUserDetailAdapter = userDetailAdapter;
177         mBgExecutor = bgExecutor;
178         if (!UserManager.isGuestUserEphemeral()) {
179             mGuestResumeSessionReceiver.register(mBroadcastDispatcher);
180         }
181         mGuestUserAutoCreated = mContext.getResources().getBoolean(
182                 com.android.internal.R.bool.config_guestUserAutoCreated);
183         mGuestIsResetting = new AtomicBoolean();
184         mGuestCreationScheduled = new AtomicBoolean();
185         mKeyguardStateController = keyguardStateController;
186         mDeviceProvisionedController = deviceProvisionedController;
187         mDevicePolicyManager = devicePolicyManager;
188         mHandler = handler;
189         mActivityStarter = activityStarter;
190         mUserManager = userManager;
191         IntentFilter filter = new IntentFilter();
192         filter.addAction(Intent.ACTION_USER_ADDED);
193         filter.addAction(Intent.ACTION_USER_REMOVED);
194         filter.addAction(Intent.ACTION_USER_INFO_CHANGED);
195         filter.addAction(Intent.ACTION_USER_SWITCHED);
196         filter.addAction(Intent.ACTION_USER_STOPPED);
197         filter.addAction(Intent.ACTION_USER_UNLOCKED);
198         mBroadcastDispatcher.registerReceiver(
199                 mReceiver, filter, null /* handler */, UserHandle.SYSTEM);
200 
201         mSimpleUserSwitcher = shouldUseSimpleUserSwitcher();
202 
203         mSecondaryUserServiceIntent = new Intent(context, SystemUISecondaryUserService.class);
204 
205         filter = new IntentFilter();
206         mContext.registerReceiverAsUser(mReceiver, UserHandle.SYSTEM, filter,
207                 PERMISSION_SELF, null /* scheduler */);
208 
209         mSettingsObserver = new ContentObserver(mHandler) {
210             @Override
211             public void onChange(boolean selfChange) {
212                 mSimpleUserSwitcher = shouldUseSimpleUserSwitcher();
213                 mAddUsersFromLockScreen = Settings.Global.getInt(mContext.getContentResolver(),
214                         Settings.Global.ADD_USERS_WHEN_LOCKED, 0) != 0;
215                 refreshUsers(UserHandle.USER_NULL);
216             };
217         };
218         mContext.getContentResolver().registerContentObserver(
219                 Settings.Global.getUriFor(SIMPLE_USER_SWITCHER_GLOBAL_SETTING), true,
220                 mSettingsObserver);
221         mContext.getContentResolver().registerContentObserver(
222                 Settings.Global.getUriFor(Settings.Global.ADD_USERS_WHEN_LOCKED), true,
223                 mSettingsObserver);
224         mContext.getContentResolver().registerContentObserver(
225                 Settings.Global.getUriFor(
226                         Settings.Global.ALLOW_USER_SWITCHING_WHEN_SYSTEM_USER_LOCKED),
227                 true, mSettingsObserver);
228         // Fetch initial values.
229         mSettingsObserver.onChange(false);
230 
231         keyguardStateController.addCallback(mCallback);
232         listenForCallState();
233 
234         refreshUsers(UserHandle.USER_NULL);
235     }
236 
237     /**
238      * Refreshes users from UserManager.
239      *
240      * The pictures are only loaded if they have not been loaded yet.
241      *
242      * @param forcePictureLoadForId forces the picture of the given user to be reloaded.
243      */
244     @SuppressWarnings("unchecked")
refreshUsers(int forcePictureLoadForId)245     private void refreshUsers(int forcePictureLoadForId) {
246         if (DEBUG) Log.d(TAG, "refreshUsers(forcePictureLoadForId=" + forcePictureLoadForId+")");
247         if (forcePictureLoadForId != UserHandle.USER_NULL) {
248             mForcePictureLoadForUserId.put(forcePictureLoadForId, true);
249         }
250 
251         if (mPauseRefreshUsers) {
252             return;
253         }
254 
255         boolean forceAllUsers = mForcePictureLoadForUserId.get(UserHandle.USER_ALL);
256         SparseArray<Bitmap> bitmaps = new SparseArray<>(mUsers.size());
257         final int N = mUsers.size();
258         for (int i = 0; i < N; i++) {
259             UserRecord r = mUsers.get(i);
260             if (r == null || r.picture == null || r.info == null || forceAllUsers
261                     || mForcePictureLoadForUserId.get(r.info.id)) {
262                 continue;
263             }
264             bitmaps.put(r.info.id, r.picture);
265         }
266         mForcePictureLoadForUserId.clear();
267 
268         final boolean addUsersWhenLocked = mAddUsersFromLockScreen;
269         new AsyncTask<SparseArray<Bitmap>, Void, ArrayList<UserRecord>>() {
270             @SuppressWarnings("unchecked")
271             @Override
272             protected ArrayList<UserRecord> doInBackground(SparseArray<Bitmap>... params) {
273                 final SparseArray<Bitmap> bitmaps = params[0];
274                 List<UserInfo> infos = mUserManager.getAliveUsers();
275                 if (infos == null) {
276                     return null;
277                 }
278                 ArrayList<UserRecord> records = new ArrayList<>(infos.size());
279                 int currentId = mUserTracker.getUserId();
280                 // Check user switchability of the foreground user since SystemUI is running in
281                 // User 0
282                 boolean canSwitchUsers = mUserManager.getUserSwitchability(
283                         UserHandle.of(mUserTracker.getUserId())) == SWITCHABILITY_STATUS_OK;
284                 UserInfo currentUserInfo = null;
285                 UserRecord guestRecord = null;
286 
287                 for (UserInfo info : infos) {
288                     boolean isCurrent = currentId == info.id;
289                     if (isCurrent) {
290                         currentUserInfo = info;
291                     }
292                     boolean switchToEnabled = canSwitchUsers || isCurrent;
293                     if (info.isEnabled()) {
294                         if (info.isGuest()) {
295                             // Tapping guest icon triggers remove and a user switch therefore
296                             // the icon shouldn't be enabled even if the user is current
297                             guestRecord = new UserRecord(info, null /* picture */,
298                                     true /* isGuest */, isCurrent, false /* isAddUser */,
299                                     false /* isRestricted */, canSwitchUsers);
300                         } else if (info.supportsSwitchToByUser()) {
301                             Bitmap picture = bitmaps.get(info.id);
302                             if (picture == null) {
303                                 picture = mUserManager.getUserIcon(info.id);
304 
305                                 if (picture != null) {
306                                     int avatarSize = mContext.getResources()
307                                             .getDimensionPixelSize(R.dimen.max_avatar_size);
308                                     picture = Bitmap.createScaledBitmap(
309                                             picture, avatarSize, avatarSize, true);
310                                 }
311                             }
312                             records.add(new UserRecord(info, picture, false /* isGuest */,
313                                     isCurrent, false /* isAddUser */, false /* isRestricted */,
314                                     switchToEnabled));
315                         }
316                     }
317                 }
318                 if (records.size() > 1 || guestRecord != null) {
319                     Prefs.putBoolean(mContext, Key.SEEN_MULTI_USER, true);
320                 }
321 
322                 boolean systemCanCreateUsers = !mUserManager.hasBaseUserRestriction(
323                                 UserManager.DISALLOW_ADD_USER, UserHandle.SYSTEM);
324                 boolean currentUserCanCreateUsers = currentUserInfo != null
325                         && (currentUserInfo.isAdmin()
326                                 || currentUserInfo.id == UserHandle.USER_SYSTEM)
327                         && systemCanCreateUsers;
328                 boolean anyoneCanCreateUsers = systemCanCreateUsers && addUsersWhenLocked;
329                 boolean canCreateGuest = (currentUserCanCreateUsers || anyoneCanCreateUsers)
330                         && guestRecord == null;
331                 boolean canCreateUser = (currentUserCanCreateUsers || anyoneCanCreateUsers)
332                         && mUserManager.canAddMoreUsers();
333                 boolean createIsRestricted = !addUsersWhenLocked;
334 
335                 if (guestRecord == null) {
336                     if (mGuestUserAutoCreated) {
337                         // If mGuestIsResetting=true, the switch should be disabled since
338                         // we will just use it as an indicator for "Resetting guest...".
339                         // Otherwise, default to canSwitchUsers.
340                         boolean isSwitchToGuestEnabled =
341                                 !mGuestIsResetting.get() && canSwitchUsers;
342                         guestRecord = new UserRecord(null /* info */, null /* picture */,
343                                 true /* isGuest */, false /* isCurrent */,
344                                 false /* isAddUser */, false /* isRestricted */,
345                                 isSwitchToGuestEnabled);
346                         checkIfAddUserDisallowedByAdminOnly(guestRecord);
347                         records.add(guestRecord);
348                     } else if (canCreateGuest) {
349                         guestRecord = new UserRecord(null /* info */, null /* picture */,
350                                 true /* isGuest */, false /* isCurrent */,
351                                 false /* isAddUser */, createIsRestricted, canSwitchUsers);
352                         checkIfAddUserDisallowedByAdminOnly(guestRecord);
353                         records.add(guestRecord);
354                     }
355                 } else {
356                     records.add(guestRecord);
357                 }
358 
359                 if (canCreateUser) {
360                     UserRecord addUserRecord = new UserRecord(null /* info */, null /* picture */,
361                             false /* isGuest */, false /* isCurrent */, true /* isAddUser */,
362                             createIsRestricted, canSwitchUsers);
363                     checkIfAddUserDisallowedByAdminOnly(addUserRecord);
364                     records.add(addUserRecord);
365                 }
366 
367                 return records;
368             }
369 
370             @Override
371             protected void onPostExecute(ArrayList<UserRecord> userRecords) {
372                 if (userRecords != null) {
373                     mUsers = userRecords;
374                     notifyAdapters();
375                 }
376             }
377         }.execute((SparseArray) bitmaps);
378     }
379 
pauseRefreshUsers()380     private void pauseRefreshUsers() {
381         if (!mPauseRefreshUsers) {
382             mHandler.postDelayed(mUnpauseRefreshUsers, PAUSE_REFRESH_USERS_TIMEOUT_MS);
383             mPauseRefreshUsers = true;
384         }
385     }
386 
notifyAdapters()387     private void notifyAdapters() {
388         for (int i = mAdapters.size() - 1; i >= 0; i--) {
389             BaseUserAdapter adapter = mAdapters.get(i).get();
390             if (adapter != null) {
391                 adapter.notifyDataSetChanged();
392             } else {
393                 mAdapters.remove(i);
394             }
395         }
396     }
397 
isSimpleUserSwitcher()398     public boolean isSimpleUserSwitcher() {
399         return mSimpleUserSwitcher;
400     }
401 
useFullscreenUserSwitcher()402     public boolean useFullscreenUserSwitcher() {
403         // Use adb to override:
404         // adb shell settings put system enable_fullscreen_user_switcher 0  # Turn it off.
405         // adb shell settings put system enable_fullscreen_user_switcher 1  # Turn it on.
406         // Restart SystemUI or adb reboot.
407         final int DEFAULT = -1;
408         final int overrideUseFullscreenUserSwitcher =
409                 whitelistIpcs(() -> Settings.System.getInt(mContext.getContentResolver(),
410                         "enable_fullscreen_user_switcher", DEFAULT));
411         if (overrideUseFullscreenUserSwitcher != DEFAULT) {
412             return overrideUseFullscreenUserSwitcher != 0;
413         }
414         // Otherwise default to the build setting.
415         return mContext.getResources().getBoolean(R.bool.config_enableFullscreenUserSwitcher);
416     }
417 
setResumeUserOnGuestLogout(boolean resume)418     public void setResumeUserOnGuestLogout(boolean resume) {
419         mResumeUserOnGuestLogout = resume;
420     }
421 
logoutCurrentUser()422     public void logoutCurrentUser() {
423         int currentUser = mUserTracker.getUserId();
424         if (currentUser != UserHandle.USER_SYSTEM) {
425             pauseRefreshUsers();
426             ActivityManager.logoutCurrentUser();
427         }
428     }
429 
removeUserId(int userId)430     public void removeUserId(int userId) {
431         if (userId == UserHandle.USER_SYSTEM) {
432             Log.w(TAG, "User " + userId + " could not removed.");
433             return;
434         }
435         if (mUserTracker.getUserId() == userId) {
436             switchToUserId(UserHandle.USER_SYSTEM);
437         }
438         if (mUserManager.removeUser(userId)) {
439             refreshUsers(UserHandle.USER_NULL);
440         }
441     }
442 
443     @VisibleForTesting
onUserListItemClicked(UserRecord record)444     void onUserListItemClicked(UserRecord record) {
445         int id;
446         if (record.isGuest && record.info == null) {
447             // No guest user. Create one.
448             int guestId = createGuest();
449             if (guestId == UserHandle.USER_NULL) {
450                 // This may happen if we haven't reloaded the user list yet.
451                 return;
452             }
453             mUiEventLogger.log(QSUserSwitcherEvent.QS_USER_GUEST_ADD);
454             id = guestId;
455         } else if (record.isAddUser) {
456             showAddUserDialog();
457             return;
458         } else {
459             id = record.info.id;
460         }
461 
462         int currUserId = mUserTracker.getUserId();
463         if (currUserId == id) {
464             if (record.isGuest) {
465                 showExitGuestDialog(id);
466             }
467             return;
468         }
469 
470         if (UserManager.isGuestUserEphemeral()) {
471             // If switching from guest, we want to bring up the guest exit dialog instead of switching
472             UserInfo currUserInfo = mUserManager.getUserInfo(currUserId);
473             if (currUserInfo != null && currUserInfo.isGuest()) {
474                 showExitGuestDialog(currUserId, record.resolveId());
475                 return;
476             }
477         }
478 
479         switchToUserId(id);
480     }
481 
switchToUserId(int id)482     protected void switchToUserId(int id) {
483         try {
484             pauseRefreshUsers();
485             ActivityManager.getService().switchUser(id);
486         } catch (RemoteException e) {
487             Log.e(TAG, "Couldn't switch user.", e);
488         }
489     }
490 
showExitGuestDialog(int id)491     protected void showExitGuestDialog(int id) {
492         int newId = UserHandle.USER_SYSTEM;
493         if (mResumeUserOnGuestLogout && mLastNonGuestUser != UserHandle.USER_SYSTEM) {
494             UserInfo info = mUserManager.getUserInfo(mLastNonGuestUser);
495             if (info != null && info.isEnabled() && info.supportsSwitchToByUser()) {
496                 newId = info.id;
497             }
498         }
499         showExitGuestDialog(id, newId);
500     }
501 
showExitGuestDialog(int id, int targetId)502     protected void showExitGuestDialog(int id, int targetId) {
503         if (mExitGuestDialog != null && mExitGuestDialog.isShowing()) {
504             mExitGuestDialog.cancel();
505         }
506         mExitGuestDialog = new ExitGuestDialog(mContext, id, targetId);
507         mExitGuestDialog.show();
508     }
509 
showAddUserDialog()510     public void showAddUserDialog() {
511         if (mAddUserDialog != null && mAddUserDialog.isShowing()) {
512             mAddUserDialog.cancel();
513         }
514         mAddUserDialog = new AddUserDialog(mContext);
515         mAddUserDialog.show();
516     }
517 
listenForCallState()518     private void listenForCallState() {
519         mTelephonyListenerManager.addCallStateListener(mPhoneStateListener);
520     }
521 
522     private final TelephonyCallback.CallStateListener mPhoneStateListener =
523             new TelephonyCallback.CallStateListener() {
524         private int mCallState;
525 
526         @Override
527         public void onCallStateChanged(int state) {
528             if (mCallState == state) return;
529             if (DEBUG) Log.v(TAG, "Call state changed: " + state);
530             mCallState = state;
531             refreshUsers(UserHandle.USER_NULL);
532         }
533     };
534 
535     private BroadcastReceiver mReceiver = new BroadcastReceiver() {
536         @Override
537         public void onReceive(Context context, Intent intent) {
538             if (DEBUG) {
539                 Log.v(TAG, "Broadcast: a=" + intent.getAction()
540                        + " user=" + intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1));
541             }
542 
543             boolean unpauseRefreshUsers = false;
544             int forcePictureLoadForId = UserHandle.USER_NULL;
545 
546             if (Intent.ACTION_USER_SWITCHED.equals(intent.getAction())) {
547                 if (mExitGuestDialog != null && mExitGuestDialog.isShowing()) {
548                     mExitGuestDialog.cancel();
549                     mExitGuestDialog = null;
550                 }
551 
552                 final int currentId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
553                 final UserInfo userInfo = mUserManager.getUserInfo(currentId);
554                 final int N = mUsers.size();
555                 for (int i = 0; i < N; i++) {
556                     UserRecord record = mUsers.get(i);
557                     if (record.info == null) continue;
558                     boolean shouldBeCurrent = record.info.id == currentId;
559                     if (record.isCurrent != shouldBeCurrent) {
560                         mUsers.set(i, record.copyWithIsCurrent(shouldBeCurrent));
561                     }
562                     if (shouldBeCurrent && !record.isGuest) {
563                         mLastNonGuestUser = record.info.id;
564                     }
565                     if ((userInfo == null || !userInfo.isAdmin()) && record.isRestricted) {
566                         // Immediately remove restricted records in case the AsyncTask is too slow.
567                         mUsers.remove(i);
568                         i--;
569                     }
570                 }
571                 notifyAdapters();
572 
573                 // Disconnect from the old secondary user's service
574                 if (mSecondaryUser != UserHandle.USER_NULL) {
575                     context.stopServiceAsUser(mSecondaryUserServiceIntent,
576                             UserHandle.of(mSecondaryUser));
577                     mSecondaryUser = UserHandle.USER_NULL;
578                 }
579                 // Connect to the new secondary user's service (purely to ensure that a persistent
580                 // SystemUI application is created for that user)
581                 if (userInfo != null && userInfo.id != UserHandle.USER_SYSTEM) {
582                     context.startServiceAsUser(mSecondaryUserServiceIntent,
583                             UserHandle.of(userInfo.id));
584                     mSecondaryUser = userInfo.id;
585                 }
586                 unpauseRefreshUsers = true;
587                 if (mGuestUserAutoCreated) {
588                     // Guest user must be scheduled for creation AFTER switching to the target user.
589                     // This avoids lock contention which will produce UX bugs on the keyguard
590                     // (b/193933686).
591                     // TODO(b/191067027): Move guest user recreation to system_server
592                     guaranteeGuestPresent();
593                 }
594             } else if (Intent.ACTION_USER_INFO_CHANGED.equals(intent.getAction())) {
595                 forcePictureLoadForId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE,
596                         UserHandle.USER_NULL);
597             } else if (Intent.ACTION_USER_UNLOCKED.equals(intent.getAction())) {
598                 // Unlocking the system user may require a refresh
599                 int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL);
600                 if (userId != UserHandle.USER_SYSTEM) {
601                     return;
602                 }
603             }
604             refreshUsers(forcePictureLoadForId);
605             if (unpauseRefreshUsers) {
606                 mUnpauseRefreshUsers.run();
607             }
608         }
609     };
610 
611     private final Runnable mUnpauseRefreshUsers = new Runnable() {
612         @Override
613         public void run() {
614             mHandler.removeCallbacks(this);
615             mPauseRefreshUsers = false;
616             refreshUsers(UserHandle.USER_NULL);
617         }
618     };
619 
620     @Override
dump(FileDescriptor fd, PrintWriter pw, String[] args)621     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
622         pw.println("UserSwitcherController state:");
623         pw.println("  mLastNonGuestUser=" + mLastNonGuestUser);
624         pw.print("  mUsers.size="); pw.println(mUsers.size());
625         for (int i = 0; i < mUsers.size(); i++) {
626             final UserRecord u = mUsers.get(i);
627             pw.print("    "); pw.println(u.toString());
628         }
629         pw.println("mSimpleUserSwitcher=" + mSimpleUserSwitcher);
630         pw.println("mGuestUserAutoCreated=" + mGuestUserAutoCreated);
631     }
632 
633     /** Returns the name of the current user of the phone. */
getCurrentUserName()634     public String getCurrentUserName() {
635         if (mUsers.isEmpty()) return null;
636         UserRecord item = mUsers.get(0);
637         if (item == null || item.info == null) return null;
638         if (item.isGuest) return mContext.getString(
639                 com.android.settingslib.R.string.guest_nickname);
640         return item.info.name;
641     }
642 
onDensityOrFontScaleChanged()643     public void onDensityOrFontScaleChanged() {
644         refreshUsers(UserHandle.USER_ALL);
645     }
646 
647     @VisibleForTesting
addAdapter(WeakReference<BaseUserAdapter> adapter)648     public void addAdapter(WeakReference<BaseUserAdapter> adapter) {
649         mAdapters.add(adapter);
650     }
651 
652     @VisibleForTesting
getUsers()653     public ArrayList<UserRecord> getUsers() {
654         return mUsers;
655     }
656 
657     /**
658      * Removes guest user and switches to target user. The guest must be the current user and its id
659      * must be {@code guestUserId}.
660      *
661      * <p>If {@code targetUserId} is {@link UserHandle.USER_NULL}, then create a new guest user in
662      * the foreground, and immediately switch to it. This is used for wiping the current guest and
663      * replacing it with a new one.
664      *
665      * <p>If {@code targetUserId} is specified, then remove the guest in the background while
666      * switching to {@code targetUserId}.
667      *
668      * <p>If device is configured with {@link
669      * com.android.internal.R.bool.config_guestUserAutoCreated}, then after guest user is removed, a
670      * new one is created in the background. This has no effect if {@code targetUserId} is {@link
671      * UserHandle.USER_NULL}.
672      *
673      * @param guestUserId id of the guest user to remove
674      * @param targetUserId id of the user to switch to after guest is removed. If {@link
675      * UserHandle.USER_NULL}, then switch immediately to the newly created guest user.
676      */
removeGuestUser(@serIdInt int guestUserId, @UserIdInt int targetUserId)677     public void removeGuestUser(@UserIdInt int guestUserId, @UserIdInt int targetUserId) {
678         UserInfo currentUser = mUserTracker.getUserInfo();
679         if (currentUser.id != guestUserId) {
680             Log.w(TAG, "User requesting to start a new session (" + guestUserId + ")"
681                     + " is not current user (" + currentUser.id + ")");
682             return;
683         }
684         if (!currentUser.isGuest()) {
685             Log.w(TAG, "User requesting to start a new session (" + guestUserId + ")"
686                     + " is not a guest");
687             return;
688         }
689 
690         boolean marked = mUserManager.markGuestForDeletion(currentUser.id);
691         if (!marked) {
692             Log.w(TAG, "Couldn't mark the guest for deletion for user " + guestUserId);
693             return;
694         }
695 
696         try {
697             if (targetUserId == UserHandle.USER_NULL) {
698                 // Create a new guest in the foreground, and then immediately switch to it
699                 int newGuestId = createGuest();
700                 if (newGuestId == UserHandle.USER_NULL) {
701                     Log.e(TAG, "Could not create new guest, switching back to system user");
702                     switchToUserId(UserHandle.USER_SYSTEM);
703                     mUserManager.removeUser(currentUser.id);
704                     WindowManagerGlobal.getWindowManagerService().lockNow(/* options= */ null);
705                     return;
706                 }
707                 switchToUserId(newGuestId);
708                 mUserManager.removeUser(currentUser.id);
709             } else {
710                 if (mGuestUserAutoCreated) {
711                     mGuestIsResetting.set(true);
712                 }
713                 switchToUserId(targetUserId);
714                 mUserManager.removeUser(currentUser.id);
715             }
716         } catch (RemoteException e) {
717             Log.e(TAG, "Couldn't remove guest because ActivityManager or WindowManager is dead");
718             return;
719         }
720     }
721 
scheduleGuestCreation()722     private void scheduleGuestCreation() {
723         if (!mGuestCreationScheduled.compareAndSet(false, true)) {
724             return;
725         }
726 
727         mBgExecutor.execute(() -> {
728             int newGuestId = createGuest();
729             mGuestCreationScheduled.set(false);
730             mGuestIsResetting.set(false);
731             if (newGuestId == UserHandle.USER_NULL) {
732                 Log.w(TAG, "Could not create new guest while exiting existing guest");
733                 // Refresh users so that we still display "Guest" if
734                 // config_guestUserAutoCreated=true
735                 refreshUsers(UserHandle.USER_NULL);
736             }
737         });
738 
739     }
740 
741     /**
742      * Guarantee guest is present only if the device is provisioned. Otherwise, create a content
743      * observer to wait until the device is provisioned, then schedule the guest creation.
744      */
schedulePostBootGuestCreation()745     public void schedulePostBootGuestCreation() {
746         if (isDeviceAllowedToAddGuest()) {
747             guaranteeGuestPresent();
748         } else {
749             mDeviceProvisionedController.addCallback(mGuaranteeGuestPresentAfterProvisioned);
750         }
751     }
752 
isDeviceAllowedToAddGuest()753     private boolean isDeviceAllowedToAddGuest() {
754         return mDeviceProvisionedController.isDeviceProvisioned()
755                 && !mDevicePolicyManager.isDeviceManaged();
756     }
757 
758     /**
759      * If there is no guest on the device, schedule creation of a new guest user in the background.
760      */
guaranteeGuestPresent()761     private void guaranteeGuestPresent() {
762         if (isDeviceAllowedToAddGuest() && mUserManager.findCurrentGuestUser() == null) {
763             scheduleGuestCreation();
764         }
765     }
766 
767     /**
768      * Creates a guest user and return its multi-user user ID.
769      *
770      * This method does not check if a guest already exists before it makes a call to
771      * {@link UserManager} to create a new one.
772      *
773      * @return The multi-user user ID of the newly created guest user, or
774      * {@link UserHandle.USER_NULL} if the guest couldn't be created.
775      */
createGuest()776     public @UserIdInt int createGuest() {
777         UserInfo guest;
778         try {
779             guest = mUserManager.createGuest(mContext,
780                     mContext.getString(com.android.settingslib.R.string.guest_nickname));
781         } catch (UserManager.UserOperationException e) {
782             Log.e(TAG, "Couldn't create guest user", e);
783             return UserHandle.USER_NULL;
784         }
785         if (guest == null) {
786             Log.e(TAG, "Couldn't create guest, most likely because there already exists one");
787             return UserHandle.USER_NULL;
788         }
789         return guest.id;
790     }
791 
792     public static abstract class BaseUserAdapter extends BaseAdapter {
793 
794         final UserSwitcherController mController;
795         private final KeyguardStateController mKeyguardStateController;
796 
BaseUserAdapter(UserSwitcherController controller)797         protected BaseUserAdapter(UserSwitcherController controller) {
798             mController = controller;
799             mKeyguardStateController = controller.mKeyguardStateController;
800             controller.addAdapter(new WeakReference<>(this));
801         }
802 
getUsers()803         protected ArrayList<UserRecord> getUsers() {
804             return mController.getUsers();
805         }
806 
getUserCount()807         public int getUserCount() {
808             return countUsers(false);
809         }
810 
811         @Override
getCount()812         public int getCount() {
813             return countUsers(true);
814         }
815 
countUsers(boolean includeGuest)816         private int countUsers(boolean includeGuest) {
817             boolean keyguardShowing = mKeyguardStateController.isShowing();
818             final int userSize = getUsers().size();
819             int count = 0;
820             for (int i = 0; i < userSize; i++) {
821                 if (getUsers().get(i).isGuest && !includeGuest) {
822                     continue;
823                 }
824                 if (getUsers().get(i).isRestricted && keyguardShowing) {
825                     break;
826                 }
827                 count++;
828             }
829             return count;
830         }
831 
832         @Override
getItem(int position)833         public UserRecord getItem(int position) {
834             return getUsers().get(position);
835         }
836 
837         @Override
getItemId(int position)838         public long getItemId(int position) {
839             return position;
840         }
841 
842         /**
843          * It handles click events on user list items.
844          */
onUserListItemClicked(UserRecord record)845         public void onUserListItemClicked(UserRecord record) {
846             mController.onUserListItemClicked(record);
847         }
848 
getName(Context context, UserRecord item)849         public String getName(Context context, UserRecord item) {
850             if (item.isGuest) {
851                 if (item.isCurrent) {
852                     return context.getString(mController.mGuestUserAutoCreated
853                             ? com.android.settingslib.R.string.guest_reset_guest
854                             : com.android.settingslib.R.string.guest_exit_guest);
855                 } else {
856                     if (item.info != null) {
857                         return context.getString(com.android.settingslib.R.string.guest_nickname);
858                     } else {
859                         if (mController.mGuestUserAutoCreated) {
860                             // If mGuestIsResetting=true, we expect the guest user to be created
861                             // shortly, so display a "Resetting guest..." as an indicator that we
862                             // are busy. Otherwise, if mGuestIsResetting=false, we probably failed
863                             // to create a guest at some point. In this case, always show guest
864                             // nickname instead of "Add guest" to make it seem as though the device
865                             // always has a guest ready for use.
866                             return context.getString(
867                                     mController.mGuestIsResetting.get()
868                                             ? com.android.settingslib.R.string.guest_resetting
869                                             : com.android.settingslib.R.string.guest_nickname);
870                         } else {
871                             return context.getString(
872                                     com.android.settingslib.R.string.guest_new_guest);
873                         }
874                     }
875                 }
876             } else if (item.isAddUser) {
877                 return context.getString(R.string.user_add_user);
878             } else {
879                 return item.info.name;
880             }
881         }
882 
getDisabledUserAvatarColorFilter()883         protected static ColorFilter getDisabledUserAvatarColorFilter() {
884             ColorMatrix matrix = new ColorMatrix();
885             matrix.setSaturation(0f);   // 0 - grayscale
886             return new ColorMatrixColorFilter(matrix);
887         }
888 
getIconDrawable(Context context, UserRecord item)889         protected static Drawable getIconDrawable(Context context, UserRecord item) {
890             int iconRes;
891             if (item.isAddUser) {
892                 iconRes = R.drawable.ic_add_circle;
893             } else if (item.isGuest) {
894                 iconRes = R.drawable.ic_avatar_guest_user;
895             } else {
896                 iconRes = R.drawable.ic_avatar_user;
897             }
898 
899             return context.getDrawable(iconRes);
900         }
901 
refresh()902         public void refresh() {
903             mController.refreshUsers(UserHandle.USER_NULL);
904         }
905     }
906 
checkIfAddUserDisallowedByAdminOnly(UserRecord record)907     private void checkIfAddUserDisallowedByAdminOnly(UserRecord record) {
908         EnforcedAdmin admin = RestrictedLockUtilsInternal.checkIfRestrictionEnforced(mContext,
909                 UserManager.DISALLOW_ADD_USER, mUserTracker.getUserId());
910         if (admin != null && !RestrictedLockUtilsInternal.hasBaseUserRestriction(mContext,
911                 UserManager.DISALLOW_ADD_USER, mUserTracker.getUserId())) {
912             record.isDisabledByAdmin = true;
913             record.enforcedAdmin = admin;
914         } else {
915             record.isDisabledByAdmin = false;
916             record.enforcedAdmin = null;
917         }
918     }
919 
shouldUseSimpleUserSwitcher()920     private boolean shouldUseSimpleUserSwitcher() {
921         int defaultSimpleUserSwitcher = mContext.getResources().getBoolean(
922                 com.android.internal.R.bool.config_expandLockScreenUserSwitcher) ? 1 : 0;
923         return Settings.Global.getInt(mContext.getContentResolver(),
924                 SIMPLE_USER_SWITCHER_GLOBAL_SETTING, defaultSimpleUserSwitcher) != 0;
925     }
926 
startActivity(Intent intent)927     public void startActivity(Intent intent) {
928         mActivityStarter.startActivity(intent, true);
929     }
930 
931     public static final class UserRecord {
932         public final UserInfo info;
933         public final Bitmap picture;
934         public final boolean isGuest;
935         public final boolean isCurrent;
936         public final boolean isAddUser;
937         /** If true, the record is only visible to the owner and only when unlocked. */
938         public final boolean isRestricted;
939         public boolean isDisabledByAdmin;
940         public EnforcedAdmin enforcedAdmin;
941         public boolean isSwitchToEnabled;
942 
UserRecord(UserInfo info, Bitmap picture, boolean isGuest, boolean isCurrent, boolean isAddUser, boolean isRestricted, boolean isSwitchToEnabled)943         public UserRecord(UserInfo info, Bitmap picture, boolean isGuest, boolean isCurrent,
944                 boolean isAddUser, boolean isRestricted, boolean isSwitchToEnabled) {
945             this.info = info;
946             this.picture = picture;
947             this.isGuest = isGuest;
948             this.isCurrent = isCurrent;
949             this.isAddUser = isAddUser;
950             this.isRestricted = isRestricted;
951             this.isSwitchToEnabled = isSwitchToEnabled;
952         }
953 
copyWithIsCurrent(boolean _isCurrent)954         public UserRecord copyWithIsCurrent(boolean _isCurrent) {
955             return new UserRecord(info, picture, isGuest, _isCurrent, isAddUser, isRestricted,
956                     isSwitchToEnabled);
957         }
958 
resolveId()959         public int resolveId() {
960             if (isGuest || info == null) {
961                 return UserHandle.USER_NULL;
962             }
963             return info.id;
964         }
965 
toString()966         public String toString() {
967             StringBuilder sb = new StringBuilder();
968             sb.append("UserRecord(");
969             if (info != null) {
970                 sb.append("name=\"").append(info.name).append("\" id=").append(info.id);
971             } else {
972                 if (isGuest) {
973                     sb.append("<add guest placeholder>");
974                 } else if (isAddUser) {
975                     sb.append("<add user placeholder>");
976                 }
977             }
978             if (isGuest) sb.append(" <isGuest>");
979             if (isAddUser) sb.append(" <isAddUser>");
980             if (isCurrent) sb.append(" <isCurrent>");
981             if (picture != null) sb.append(" <hasPicture>");
982             if (isRestricted) sb.append(" <isRestricted>");
983             if (isDisabledByAdmin) {
984                 sb.append(" <isDisabledByAdmin>");
985                 sb.append(" enforcedAdmin=").append(enforcedAdmin);
986             }
987             if (isSwitchToEnabled) {
988                 sb.append(" <isSwitchToEnabled>");
989             }
990             sb.append(')');
991             return sb.toString();
992         }
993     }
994 
995     public static class UserDetailAdapter implements DetailAdapter {
996         private final Intent USER_SETTINGS_INTENT = new Intent(Settings.ACTION_USER_SETTINGS);
997 
998         private final Context mContext;
999         private final Provider<UserDetailView.Adapter> mUserDetailViewAdapterProvider;
1000 
1001         @Inject
UserDetailAdapter(Context context, Provider<UserDetailView.Adapter> userDetailViewAdapterProvider)1002         UserDetailAdapter(Context context,
1003                 Provider<UserDetailView.Adapter> userDetailViewAdapterProvider) {
1004             mContext = context;
1005             mUserDetailViewAdapterProvider = userDetailViewAdapterProvider;
1006         }
1007 
1008         @Override
getTitle()1009         public CharSequence getTitle() {
1010             return mContext.getString(R.string.quick_settings_user_title);
1011         }
1012 
1013         @Override
createDetailView(Context context, View convertView, ViewGroup parent)1014         public View createDetailView(Context context, View convertView, ViewGroup parent) {
1015             UserDetailView v;
1016             if (!(convertView instanceof UserDetailView)) {
1017                 v = UserDetailView.inflate(context, parent, false);
1018                 v.setAdapter(mUserDetailViewAdapterProvider.get());
1019             } else {
1020                 v = (UserDetailView) convertView;
1021             }
1022             v.refreshAdapter();
1023             return v;
1024         }
1025 
1026         @Override
getSettingsIntent()1027         public Intent getSettingsIntent() {
1028             return USER_SETTINGS_INTENT;
1029         }
1030 
1031         @Override
getSettingsText()1032         public int getSettingsText() {
1033             return R.string.quick_settings_more_user_settings;
1034         }
1035 
1036         @Override
getToggleState()1037         public Boolean getToggleState() {
1038             return null;
1039         }
1040 
1041         @Override
setToggleState(boolean state)1042         public void setToggleState(boolean state) {
1043         }
1044 
1045         @Override
getMetricsCategory()1046         public int getMetricsCategory() {
1047             return MetricsEvent.QS_USERDETAIL;
1048         }
1049 
1050         @Override
openDetailEvent()1051         public UiEventLogger.UiEventEnum openDetailEvent() {
1052             return QSUserSwitcherEvent.QS_USER_DETAIL_OPEN;
1053         }
1054 
1055         @Override
closeDetailEvent()1056         public UiEventLogger.UiEventEnum closeDetailEvent() {
1057             return QSUserSwitcherEvent.QS_USER_DETAIL_CLOSE;
1058         }
1059 
1060         @Override
moreSettingsEvent()1061         public UiEventLogger.UiEventEnum moreSettingsEvent() {
1062             return QSUserSwitcherEvent.QS_USER_MORE_SETTINGS;
1063         }
1064     };
1065 
1066     private final KeyguardStateController.Callback mCallback =
1067             new KeyguardStateController.Callback() {
1068                 @Override
1069                 public void onKeyguardShowingChanged() {
1070 
1071                     // When Keyguard is going away, we don't need to update our items immediately
1072                     // which
1073                     // helps making the transition faster.
1074                     if (!mKeyguardStateController.isShowing()) {
1075                         mHandler.post(UserSwitcherController.this::notifyAdapters);
1076                     } else {
1077                         notifyAdapters();
1078                     }
1079                 }
1080             };
1081 
1082     private final DeviceProvisionedController.DeviceProvisionedListener
1083             mGuaranteeGuestPresentAfterProvisioned =
1084             new DeviceProvisionedController.DeviceProvisionedListener() {
1085                 @Override
1086                 public void onDeviceProvisionedChanged() {
1087                     if (isDeviceAllowedToAddGuest()) {
1088                         mBgExecutor.execute(
1089                                 () -> mDeviceProvisionedController.removeCallback(
1090                                         mGuaranteeGuestPresentAfterProvisioned));
1091                         guaranteeGuestPresent();
1092                     }
1093                 }
1094             };
1095 
1096 
1097     private final class ExitGuestDialog extends SystemUIDialog implements
1098             DialogInterface.OnClickListener {
1099 
1100         private final int mGuestId;
1101         private final int mTargetId;
1102 
ExitGuestDialog(Context context, int guestId, int targetId)1103         public ExitGuestDialog(Context context, int guestId, int targetId) {
1104             super(context);
1105             setTitle(mGuestUserAutoCreated
1106                     ? com.android.settingslib.R.string.guest_reset_guest_dialog_title
1107                     : R.string.guest_exit_guest_dialog_title);
1108             setMessage(context.getString(R.string.guest_exit_guest_dialog_message));
1109             setButton(DialogInterface.BUTTON_NEGATIVE,
1110                     context.getString(android.R.string.cancel), this);
1111             setButton(DialogInterface.BUTTON_POSITIVE,
1112                     context.getString(mGuestUserAutoCreated
1113                             ? com.android.settingslib.R.string.guest_reset_guest_confirm_button
1114                             : R.string.guest_exit_guest_dialog_remove), this);
1115             SystemUIDialog.setWindowOnTop(this);
1116             setCanceledOnTouchOutside(false);
1117             mGuestId = guestId;
1118             mTargetId = targetId;
1119         }
1120 
1121         @Override
onClick(DialogInterface dialog, int which)1122         public void onClick(DialogInterface dialog, int which) {
1123             int penalty = which == BUTTON_NEGATIVE ? FalsingManager.NO_PENALTY
1124                     : FalsingManager.HIGH_PENALTY;
1125             if (mFalsingManager.isFalseTap(penalty)) {
1126                 return;
1127             }
1128             if (which == BUTTON_NEGATIVE) {
1129                 cancel();
1130             } else {
1131                 mUiEventLogger.log(QSUserSwitcherEvent.QS_USER_GUEST_REMOVE);
1132                 dismiss();
1133                 removeGuestUser(mGuestId, mTargetId);
1134             }
1135         }
1136     }
1137 
1138     @VisibleForTesting
1139     final class AddUserDialog extends SystemUIDialog implements
1140             DialogInterface.OnClickListener {
1141 
AddUserDialog(Context context)1142         public AddUserDialog(Context context) {
1143             super(context);
1144             setTitle(R.string.user_add_user_title);
1145             setMessage(context.getString(R.string.user_add_user_message_short));
1146             setButton(DialogInterface.BUTTON_NEGATIVE,
1147                     context.getString(android.R.string.cancel), this);
1148             setButton(DialogInterface.BUTTON_POSITIVE,
1149                     context.getString(android.R.string.ok), this);
1150             SystemUIDialog.setWindowOnTop(this);
1151         }
1152 
1153         @Override
onClick(DialogInterface dialog, int which)1154         public void onClick(DialogInterface dialog, int which) {
1155             int penalty = which == BUTTON_NEGATIVE ? FalsingManager.NO_PENALTY
1156                     : FalsingManager.MODERATE_PENALTY;
1157             if (mFalsingManager.isFalseTap(penalty)) {
1158                 return;
1159             }
1160             if (which == BUTTON_NEGATIVE) {
1161                 cancel();
1162             } else {
1163                 dismiss();
1164                 if (ActivityManager.isUserAMonkey()) {
1165                     return;
1166                 }
1167                 Intent intent = CreateUserActivity.createIntentForStart(getContext());
1168 
1169                 // There are some differences between ActivityStarter and ActivityTaskManager in
1170                 // terms of how they start an activity. ActivityStarter hides the notification bar
1171                 // before starting the activity to make sure nothing is in front of the new
1172                 // activity. ActivityStarter also tries to unlock the device if it's locked.
1173                 // When locked with PIN/pattern/password then it shows the prompt, if there are no
1174                 // security steps then it dismisses the keyguard and then starts the activity.
1175                 // ActivityTaskManager doesn't hide the notification bar or unlocks the device, but
1176                 // it can start an activity on top of the locked screen.
1177                 if (!mKeyguardStateController.isUnlocked()
1178                         && !mKeyguardStateController.canDismissLockScreen()) {
1179                     // Device is locked and can't be unlocked without a PIN/pattern/password so we
1180                     // need to use ActivityTaskManager to start the activity on top of the locked
1181                     // screen.
1182                     try {
1183                         mActivityTaskManager.startActivity(null,
1184                                 mContext.getBasePackageName(), mContext.getAttributionTag(), intent,
1185                                 intent.resolveTypeIfNeeded(mContext.getContentResolver()), null,
1186                                 null, 0, 0, null, null);
1187                     } catch (RemoteException e) {
1188                         e.printStackTrace();
1189                         Log.e(TAG, "Couldn't start create user activity", e);
1190                     }
1191                 } else {
1192                     mActivityStarter.startActivity(intent, true);
1193                 }
1194             }
1195         }
1196     }
1197 }
1198