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
17package com.android.systemui.statusbar.policy;
18
19import android.app.ActivityManager;
20import android.app.ActivityManagerNative;
21import android.app.Dialog;
22import android.app.Notification;
23import android.app.NotificationManager;
24import android.app.PendingIntent;
25import android.content.BroadcastReceiver;
26import android.content.Context;
27import android.content.DialogInterface;
28import android.content.Intent;
29import android.content.IntentFilter;
30import android.content.pm.UserInfo;
31import android.database.ContentObserver;
32import android.graphics.Bitmap;
33import android.graphics.drawable.Drawable;
34import android.os.AsyncTask;
35import android.os.Handler;
36import android.os.RemoteException;
37import android.os.UserHandle;
38import android.os.UserManager;
39import android.provider.Settings;
40import android.util.Log;
41import android.util.SparseArray;
42import android.util.SparseBooleanArray;
43import android.util.SparseIntArray;
44import android.view.View;
45import android.view.ViewGroup;
46import android.widget.BaseAdapter;
47
48import com.android.internal.logging.MetricsLogger;
49import com.android.internal.util.UserIcons;
50import 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;
55import com.android.systemui.statusbar.phone.SystemUIDialog;
56
57import java.io.FileDescriptor;
58import java.io.PrintWriter;
59import java.lang.ref.WeakReference;
60import java.util.ArrayList;
61import java.util.List;
62
63/**
64 * Keeps a list of all users on the device for user switching.
65 */
66public class UserSwitcherController {
67
68    private static final String TAG = "UserSwitcherController";
69    private static final boolean DEBUG = false;
70    private static final String SIMPLE_USER_SWITCHER_GLOBAL_SETTING =
71            "lockscreenSimpleUserSwitcher";
72    private static final String ACTION_REMOVE_GUEST = "com.android.systemui.REMOVE_GUEST";
73    private static final int PAUSE_REFRESH_USERS_TIMEOUT_MS = 3000;
74
75    private static final int ID_REMOVE_GUEST = 1010;
76    private static final String TAG_REMOVE_GUEST = "remove_guest";
77    private static final String PERMISSION_SELF = "com.android.systemui.permission.SELF";
78
79    private final Context mContext;
80    private final UserManager mUserManager;
81    private final ArrayList<WeakReference<BaseUserAdapter>> mAdapters = new ArrayList<>();
82    private final GuestResumeSessionReceiver mGuestResumeSessionReceiver
83            = new GuestResumeSessionReceiver();
84    private final KeyguardMonitor mKeyguardMonitor;
85    private final Handler mHandler;
86
87    private ArrayList<UserRecord> mUsers = new ArrayList<>();
88    private Dialog mExitGuestDialog;
89    private Dialog mAddUserDialog;
90    private int mLastNonGuestUser = UserHandle.USER_OWNER;
91    private boolean mSimpleUserSwitcher;
92    private boolean mAddUsersWhenLocked;
93    private boolean mPauseRefreshUsers;
94    private SparseBooleanArray mForcePictureLoadForUserId = new SparseBooleanArray(2);
95
96    public UserSwitcherController(Context context, KeyguardMonitor keyguardMonitor,
97            Handler handler) {
98        mContext = context;
99        mGuestResumeSessionReceiver.register(context);
100        mKeyguardMonitor = keyguardMonitor;
101        mHandler = handler;
102        mUserManager = UserManager.get(context);
103        IntentFilter filter = new IntentFilter();
104        filter.addAction(Intent.ACTION_USER_ADDED);
105        filter.addAction(Intent.ACTION_USER_REMOVED);
106        filter.addAction(Intent.ACTION_USER_INFO_CHANGED);
107        filter.addAction(Intent.ACTION_USER_SWITCHED);
108        filter.addAction(Intent.ACTION_USER_STOPPING);
109        mContext.registerReceiverAsUser(mReceiver, UserHandle.OWNER, filter,
110                null /* permission */, null /* scheduler */);
111
112        filter = new IntentFilter();
113        filter.addAction(ACTION_REMOVE_GUEST);
114        mContext.registerReceiverAsUser(mReceiver, UserHandle.OWNER, filter,
115                PERMISSION_SELF, null /* scheduler */);
116
117        mContext.getContentResolver().registerContentObserver(
118                Settings.Global.getUriFor(SIMPLE_USER_SWITCHER_GLOBAL_SETTING), true,
119                mSettingsObserver);
120        mContext.getContentResolver().registerContentObserver(
121                Settings.Global.getUriFor(Settings.Global.ADD_USERS_WHEN_LOCKED), true,
122                mSettingsObserver);
123        // Fetch initial values.
124        mSettingsObserver.onChange(false);
125
126        keyguardMonitor.addCallback(mCallback);
127
128        refreshUsers(UserHandle.USER_NULL);
129    }
130
131    /**
132     * Refreshes users from UserManager.
133     *
134     * The pictures are only loaded if they have not been loaded yet.
135     *
136     * @param forcePictureLoadForId forces the picture of the given user to be reloaded.
137     */
138    @SuppressWarnings("unchecked")
139    private void refreshUsers(int forcePictureLoadForId) {
140        if (DEBUG) Log.d(TAG, "refreshUsers(forcePictureLoadForId=" + forcePictureLoadForId+")");
141        if (forcePictureLoadForId != UserHandle.USER_NULL) {
142            mForcePictureLoadForUserId.put(forcePictureLoadForId, true);
143        }
144
145        if (mPauseRefreshUsers) {
146            return;
147        }
148
149        SparseArray<Bitmap> bitmaps = new SparseArray<>(mUsers.size());
150        final int N = mUsers.size();
151        for (int i = 0; i < N; i++) {
152            UserRecord r = mUsers.get(i);
153            if (r == null || r.picture == null ||
154                    r.info == null || mForcePictureLoadForUserId.get(r.info.id)) {
155                continue;
156            }
157            bitmaps.put(r.info.id, r.picture);
158        }
159        mForcePictureLoadForUserId.clear();
160
161        final boolean addUsersWhenLocked = mAddUsersWhenLocked;
162        new AsyncTask<SparseArray<Bitmap>, Void, ArrayList<UserRecord>>() {
163            @SuppressWarnings("unchecked")
164            @Override
165            protected ArrayList<UserRecord> doInBackground(SparseArray<Bitmap>... params) {
166                final SparseArray<Bitmap> bitmaps = params[0];
167                List<UserInfo> infos = mUserManager.getUsers(true);
168                if (infos == null) {
169                    return null;
170                }
171                ArrayList<UserRecord> records = new ArrayList<>(infos.size());
172                int currentId = ActivityManager.getCurrentUser();
173                UserRecord guestRecord = null;
174                int avatarSize = mContext.getResources()
175                        .getDimensionPixelSize(R.dimen.max_avatar_size);
176
177                for (UserInfo info : infos) {
178                    boolean isCurrent = currentId == info.id;
179                    if (info.isGuest()) {
180                        guestRecord = new UserRecord(info, null /* picture */,
181                                true /* isGuest */, isCurrent, false /* isAddUser */,
182                                false /* isRestricted */);
183                    } else if (info.supportsSwitchTo()) {
184                        Bitmap picture = bitmaps.get(info.id);
185                        if (picture == null) {
186                            picture = mUserManager.getUserIcon(info.id);
187
188                            if (picture != null) {
189                                picture = BitmapHelper.createCircularClip(
190                                        picture, avatarSize, avatarSize);
191                            }
192                        }
193                        int index = isCurrent ? 0 : records.size();
194                        records.add(index, new UserRecord(info, picture, false /* isGuest */,
195                                isCurrent, false /* isAddUser */, false /* isRestricted */));
196                    }
197                }
198
199                boolean ownerCanCreateUsers = !mUserManager.hasUserRestriction(
200                        UserManager.DISALLOW_ADD_USER, UserHandle.OWNER);
201                boolean currentUserCanCreateUsers =
202                        (currentId == UserHandle.USER_OWNER) && ownerCanCreateUsers;
203                boolean anyoneCanCreateUsers = ownerCanCreateUsers && addUsersWhenLocked;
204                boolean canCreateGuest = (currentUserCanCreateUsers || anyoneCanCreateUsers)
205                        && guestRecord == null;
206                boolean canCreateUser = (currentUserCanCreateUsers || anyoneCanCreateUsers)
207                        && mUserManager.canAddMoreUsers();
208                boolean createIsRestricted = !addUsersWhenLocked;
209
210                if (!mSimpleUserSwitcher) {
211                    if (guestRecord == null) {
212                        if (canCreateGuest) {
213                            records.add(new UserRecord(null /* info */, null /* picture */,
214                                    true /* isGuest */, false /* isCurrent */,
215                                    false /* isAddUser */, createIsRestricted));
216                        }
217                    } else {
218                        int index = guestRecord.isCurrent ? 0 : records.size();
219                        records.add(index, guestRecord);
220                    }
221                }
222
223                if (!mSimpleUserSwitcher && canCreateUser) {
224                    records.add(new UserRecord(null /* info */, null /* picture */,
225                            false /* isGuest */, false /* isCurrent */, true /* isAddUser */,
226                            createIsRestricted));
227                }
228
229                return records;
230            }
231
232            @Override
233            protected void onPostExecute(ArrayList<UserRecord> userRecords) {
234                if (userRecords != null) {
235                    mUsers = userRecords;
236                    notifyAdapters();
237                }
238            }
239        }.execute((SparseArray) bitmaps);
240    }
241
242    private void pauseRefreshUsers() {
243        if (!mPauseRefreshUsers) {
244            mHandler.postDelayed(mUnpauseRefreshUsers, PAUSE_REFRESH_USERS_TIMEOUT_MS);
245            mPauseRefreshUsers = true;
246        }
247    }
248
249    private void notifyAdapters() {
250        for (int i = mAdapters.size() - 1; i >= 0; i--) {
251            BaseUserAdapter adapter = mAdapters.get(i).get();
252            if (adapter != null) {
253                adapter.notifyDataSetChanged();
254            } else {
255                mAdapters.remove(i);
256            }
257        }
258    }
259
260    public boolean isSimpleUserSwitcher() {
261        return mSimpleUserSwitcher;
262    }
263
264    public void switchTo(UserRecord record) {
265        int id;
266        if (record.isGuest && record.info == null) {
267            // No guest user. Create one.
268            UserInfo guest = mUserManager.createGuest(
269                    mContext, mContext.getString(R.string.guest_nickname));
270            if (guest == null) {
271                // Couldn't create guest, most likely because there already exists one, we just
272                // haven't reloaded the user list yet.
273                return;
274            }
275            id = guest.id;
276        } else if (record.isAddUser) {
277            showAddUserDialog();
278            return;
279        } else {
280            id = record.info.id;
281        }
282
283        if (ActivityManager.getCurrentUser() == id) {
284            if (record.isGuest) {
285                showExitGuestDialog(id);
286            }
287            return;
288        }
289
290        switchToUserId(id);
291    }
292
293    private void switchToUserId(int id) {
294        try {
295            pauseRefreshUsers();
296            ActivityManagerNative.getDefault().switchUser(id);
297        } catch (RemoteException e) {
298            Log.e(TAG, "Couldn't switch user.", e);
299        }
300    }
301
302    private void showExitGuestDialog(int id) {
303        if (mExitGuestDialog != null && mExitGuestDialog.isShowing()) {
304            mExitGuestDialog.cancel();
305        }
306        mExitGuestDialog = new ExitGuestDialog(mContext, id);
307        mExitGuestDialog.show();
308    }
309
310    private void showAddUserDialog() {
311        if (mAddUserDialog != null && mAddUserDialog.isShowing()) {
312            mAddUserDialog.cancel();
313        }
314        mAddUserDialog = new AddUserDialog(mContext);
315        mAddUserDialog.show();
316    }
317
318    private void exitGuest(int id) {
319        int newId = UserHandle.USER_OWNER;
320        if (mLastNonGuestUser != UserHandle.USER_OWNER) {
321            UserInfo info = mUserManager.getUserInfo(mLastNonGuestUser);
322            if (info != null && info.isEnabled() && info.supportsSwitchTo()) {
323                newId = info.id;
324            }
325        }
326        switchToUserId(newId);
327        mUserManager.removeUser(id);
328    }
329
330    private BroadcastReceiver mReceiver = new BroadcastReceiver() {
331        @Override
332        public void onReceive(Context context, Intent intent) {
333            if (DEBUG) {
334                Log.v(TAG, "Broadcast: a=" + intent.getAction()
335                       + " user=" + intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1));
336            }
337
338            boolean unpauseRefreshUsers = false;
339            int forcePictureLoadForId = UserHandle.USER_NULL;
340
341            if (ACTION_REMOVE_GUEST.equals(intent.getAction())) {
342                int currentUser = ActivityManager.getCurrentUser();
343                UserInfo userInfo = mUserManager.getUserInfo(currentUser);
344                if (userInfo != null && userInfo.isGuest()) {
345                    showExitGuestDialog(currentUser);
346                }
347                return;
348            } else if (Intent.ACTION_USER_ADDED.equals(intent.getAction())) {
349                final int currentId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
350                UserInfo userInfo = mUserManager.getUserInfo(currentId);
351                if (userInfo != null && userInfo.isGuest()) {
352                    showGuestNotification(currentId);
353                }
354            } else if (Intent.ACTION_USER_SWITCHED.equals(intent.getAction())) {
355                if (mExitGuestDialog != null && mExitGuestDialog.isShowing()) {
356                    mExitGuestDialog.cancel();
357                    mExitGuestDialog = null;
358                }
359
360                final int currentId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
361                final int N = mUsers.size();
362                for (int i = 0; i < N; i++) {
363                    UserRecord record = mUsers.get(i);
364                    if (record.info == null) continue;
365                    boolean shouldBeCurrent = record.info.id == currentId;
366                    if (record.isCurrent != shouldBeCurrent) {
367                        mUsers.set(i, record.copyWithIsCurrent(shouldBeCurrent));
368                    }
369                    if (shouldBeCurrent && !record.isGuest) {
370                        mLastNonGuestUser = record.info.id;
371                    }
372                    if (currentId != UserHandle.USER_OWNER && record.isRestricted) {
373                        // Immediately remove restricted records in case the AsyncTask is too slow.
374                        mUsers.remove(i);
375                        i--;
376                    }
377                }
378                notifyAdapters();
379                unpauseRefreshUsers = true;
380            } else if (Intent.ACTION_USER_INFO_CHANGED.equals(intent.getAction())) {
381                forcePictureLoadForId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE,
382                        UserHandle.USER_NULL);
383            }
384            refreshUsers(forcePictureLoadForId);
385            if (unpauseRefreshUsers) {
386                mUnpauseRefreshUsers.run();
387            }
388        }
389
390        private void showGuestNotification(int guestUserId) {
391            PendingIntent removeGuestPI = PendingIntent.getBroadcastAsUser(mContext,
392                    0, new Intent(ACTION_REMOVE_GUEST), 0, UserHandle.OWNER);
393            Notification notification = new Notification.Builder(mContext)
394                    .setVisibility(Notification.VISIBILITY_SECRET)
395                    .setPriority(Notification.PRIORITY_MIN)
396                    .setSmallIcon(R.drawable.ic_person)
397                    .setContentTitle(mContext.getString(R.string.guest_notification_title))
398                    .setContentText(mContext.getString(R.string.guest_notification_text))
399                    .setShowWhen(false)
400                    .addAction(R.drawable.ic_delete,
401                            mContext.getString(R.string.guest_notification_remove_action),
402                            removeGuestPI)
403                    .build();
404            NotificationManager.from(mContext).notifyAsUser(TAG_REMOVE_GUEST, ID_REMOVE_GUEST,
405                    notification, new UserHandle(guestUserId));
406        }
407    };
408
409    private final Runnable mUnpauseRefreshUsers = new Runnable() {
410        @Override
411        public void run() {
412            mHandler.removeCallbacks(this);
413            mPauseRefreshUsers = false;
414            refreshUsers(UserHandle.USER_NULL);
415        }
416    };
417
418    private final ContentObserver mSettingsObserver = new ContentObserver(new Handler()) {
419        public void onChange(boolean selfChange) {
420            mSimpleUserSwitcher = Settings.Global.getInt(mContext.getContentResolver(),
421                    SIMPLE_USER_SWITCHER_GLOBAL_SETTING, 0) != 0;
422            mAddUsersWhenLocked = Settings.Global.getInt(mContext.getContentResolver(),
423                    Settings.Global.ADD_USERS_WHEN_LOCKED, 0) != 0;
424            refreshUsers(UserHandle.USER_NULL);
425        };
426    };
427
428    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
429        pw.println("UserSwitcherController state:");
430        pw.println("  mLastNonGuestUser=" + mLastNonGuestUser);
431        pw.print("  mUsers.size="); pw.println(mUsers.size());
432        for (int i = 0; i < mUsers.size(); i++) {
433            final UserRecord u = mUsers.get(i);
434            pw.print("    "); pw.println(u.toString());
435        }
436    }
437
438    public String getCurrentUserName(Context context) {
439        if (mUsers.isEmpty()) return null;
440        UserRecord item = mUsers.get(0);
441        if (item == null || item.info == null) return null;
442        if (item.isGuest) return context.getString(R.string.guest_nickname);
443        return item.info.name;
444    }
445
446    public static abstract class BaseUserAdapter extends BaseAdapter {
447
448        final UserSwitcherController mController;
449
450        protected BaseUserAdapter(UserSwitcherController controller) {
451            mController = controller;
452            controller.mAdapters.add(new WeakReference<>(this));
453        }
454
455        @Override
456        public int getCount() {
457            boolean secureKeyguardShowing = mController.mKeyguardMonitor.isShowing()
458                    && mController.mKeyguardMonitor.isSecure()
459                    && !mController.mKeyguardMonitor.canSkipBouncer();
460            if (!secureKeyguardShowing) {
461                return mController.mUsers.size();
462            }
463            // The lock screen is secure and showing. Filter out restricted records.
464            final int N = mController.mUsers.size();
465            int count = 0;
466            for (int i = 0; i < N; i++) {
467                if (mController.mUsers.get(i).isRestricted) {
468                    break;
469                } else {
470                    count++;
471                }
472            }
473            return count;
474        }
475
476        @Override
477        public UserRecord getItem(int position) {
478            return mController.mUsers.get(position);
479        }
480
481        @Override
482        public long getItemId(int position) {
483            return position;
484        }
485
486        public void switchTo(UserRecord record) {
487            mController.switchTo(record);
488        }
489
490        public String getName(Context context, UserRecord item) {
491            if (item.isGuest) {
492                if (item.isCurrent) {
493                    return context.getString(R.string.guest_exit_guest);
494                } else {
495                    return context.getString(
496                            item.info == null ? R.string.guest_new_guest : R.string.guest_nickname);
497                }
498            } else if (item.isAddUser) {
499                return context.getString(R.string.user_add_user);
500            } else {
501                return item.info.name;
502            }
503        }
504
505        public Drawable getDrawable(Context context, UserRecord item) {
506            if (item.isAddUser) {
507                return context.getDrawable(R.drawable.ic_add_circle_qs);
508            }
509            return UserIcons.getDefaultUserIcon(item.isGuest ? UserHandle.USER_NULL : item.info.id,
510                    /* light= */ true);
511        }
512
513        public void refresh() {
514            mController.refreshUsers(UserHandle.USER_NULL);
515        }
516    }
517
518    public static final class UserRecord {
519        public final UserInfo info;
520        public final Bitmap picture;
521        public final boolean isGuest;
522        public final boolean isCurrent;
523        public final boolean isAddUser;
524        /** If true, the record is only visible to the owner and only when unlocked. */
525        public final boolean isRestricted;
526
527        public UserRecord(UserInfo info, Bitmap picture, boolean isGuest, boolean isCurrent,
528                boolean isAddUser, boolean isRestricted) {
529            this.info = info;
530            this.picture = picture;
531            this.isGuest = isGuest;
532            this.isCurrent = isCurrent;
533            this.isAddUser = isAddUser;
534            this.isRestricted = isRestricted;
535        }
536
537        public UserRecord copyWithIsCurrent(boolean _isCurrent) {
538            return new UserRecord(info, picture, isGuest, _isCurrent, isAddUser, isRestricted);
539        }
540
541        public String toString() {
542            StringBuilder sb = new StringBuilder();
543            sb.append("UserRecord(");
544            if (info != null) {
545                sb.append("name=\"" + info.name + "\" id=" + info.id);
546            } else {
547                if (isGuest) {
548                    sb.append("<add guest placeholder>");
549                } else if (isAddUser) {
550                    sb.append("<add user placeholder>");
551                }
552            }
553            if (isGuest) sb.append(" <isGuest>");
554            if (isAddUser) sb.append(" <isAddUser>");
555            if (isCurrent) sb.append(" <isCurrent>");
556            if (picture != null) sb.append(" <hasPicture>");
557            if (isRestricted) sb.append(" <isRestricted>");
558            sb.append(')');
559            return sb.toString();
560        }
561    }
562
563    public final QSTile.DetailAdapter userDetailAdapter = new QSTile.DetailAdapter() {
564        private final Intent USER_SETTINGS_INTENT = new Intent("android.settings.USER_SETTINGS");
565
566        @Override
567        public int getTitle() {
568            return R.string.quick_settings_user_title;
569        }
570
571        @Override
572        public View createDetailView(Context context, View convertView, ViewGroup parent) {
573            UserDetailView v;
574            if (!(convertView instanceof UserDetailView)) {
575                v = UserDetailView.inflate(context, parent, false);
576                v.createAndSetAdapter(UserSwitcherController.this);
577            } else {
578                v = (UserDetailView) convertView;
579            }
580            v.refreshAdapter();
581            return v;
582        }
583
584        @Override
585        public Intent getSettingsIntent() {
586            return USER_SETTINGS_INTENT;
587        }
588
589        @Override
590        public Boolean getToggleState() {
591            return null;
592        }
593
594        @Override
595        public void setToggleState(boolean state) {
596        }
597
598        @Override
599        public int getMetricsCategory() {
600            return MetricsLogger.QS_USERDETAIL;
601        }
602    };
603
604    private final KeyguardMonitor.Callback mCallback = new KeyguardMonitor.Callback() {
605        @Override
606        public void onKeyguardChanged() {
607            notifyAdapters();
608        }
609    };
610
611    private final class ExitGuestDialog extends SystemUIDialog implements
612            DialogInterface.OnClickListener {
613
614        private final int mGuestId;
615
616        public ExitGuestDialog(Context context, int guestId) {
617            super(context);
618            setTitle(R.string.guest_exit_guest_dialog_title);
619            setMessage(context.getString(R.string.guest_exit_guest_dialog_message));
620            setButton(DialogInterface.BUTTON_NEGATIVE,
621                    context.getString(android.R.string.cancel), this);
622            setButton(DialogInterface.BUTTON_POSITIVE,
623                    context.getString(R.string.guest_exit_guest_dialog_remove), this);
624            setCanceledOnTouchOutside(false);
625            mGuestId = guestId;
626        }
627
628        @Override
629        public void onClick(DialogInterface dialog, int which) {
630            if (which == BUTTON_NEGATIVE) {
631                cancel();
632            } else {
633                dismiss();
634                exitGuest(mGuestId);
635            }
636        }
637    }
638
639    private final class AddUserDialog extends SystemUIDialog implements
640            DialogInterface.OnClickListener {
641
642        public AddUserDialog(Context context) {
643            super(context);
644            setTitle(R.string.user_add_user_title);
645            setMessage(context.getString(R.string.user_add_user_message_short));
646            setButton(DialogInterface.BUTTON_NEGATIVE,
647                    context.getString(android.R.string.cancel), this);
648            setButton(DialogInterface.BUTTON_POSITIVE,
649                    context.getString(android.R.string.ok), this);
650        }
651
652        @Override
653        public void onClick(DialogInterface dialog, int which) {
654            if (which == BUTTON_NEGATIVE) {
655                cancel();
656            } else {
657                dismiss();
658                if (ActivityManager.isUserAMonkey()) {
659                    return;
660                }
661                UserInfo user = mUserManager.createSecondaryUser(
662                        mContext.getString(R.string.user_new_user_name), 0 /* flags */);
663                if (user == null) {
664                    // Couldn't create user, most likely because there are too many, but we haven't
665                    // been able to reload the list yet.
666                    return;
667                }
668                int id = user.id;
669                Bitmap icon = UserIcons.convertToBitmap(UserIcons.getDefaultUserIcon(
670                        id, /* light= */ false));
671                mUserManager.setUserIcon(id, icon);
672                switchToUserId(id);
673            }
674        }
675    }
676
677    public static boolean isUserSwitcherAvailable(UserManager um) {
678        return UserManager.supportsMultipleUsers() && um.isUserSwitcherEnabled();
679    }
680
681}
682