UserSwitcherController.java revision 5e6c0ffd3e91cf0c5872de3e2d99e225ad1468f4
100a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos/*
200a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos * Copyright (C) 2014 The Android Open Source Project
300a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos *
400a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos * Licensed under the Apache License, Version 2.0 (the "License");
500a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos * you may not use this file except in compliance with the License.
600a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos * You may obtain a copy of the License at
700a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos *
800a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos *      http://www.apache.org/licenses/LICENSE-2.0
900a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos *
1000a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos * Unless required by applicable law or agreed to in writing, software
1100a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos * distributed under the License is distributed on an "AS IS" BASIS,
1200a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1300a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos * See the License for the specific language governing permissions and
1400a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos * limitations under the License
1500a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos */
1600a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos
1700a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roospackage com.android.systemui.statusbar.policy;
1800a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos
19ec015d5cb510d26d4e951feb240be8025f477ff5Xiaohui Chenimport static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
20ec015d5cb510d26d4e951feb240be8025f477ff5Xiaohui Chen
2100a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roosimport android.app.ActivityManager;
225005244f10442e75c1f48973fdddce5facf3f360Adrian Roosimport android.app.Dialog;
23f4d6ad26636760163083ae84c40d5b19cb6650f6Fyodor Kupolovimport android.app.Notification;
24f4d6ad26636760163083ae84c40d5b19cb6650f6Fyodor Kupolovimport android.app.NotificationManager;
25f4d6ad26636760163083ae84c40d5b19cb6650f6Fyodor Kupolovimport android.app.PendingIntent;
2600a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roosimport android.content.BroadcastReceiver;
2700a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roosimport android.content.Context;
285005244f10442e75c1f48973fdddce5facf3f360Adrian Roosimport android.content.DialogInterface;
2900a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roosimport android.content.Intent;
3000a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roosimport android.content.IntentFilter;
3100a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roosimport android.content.pm.UserInfo;
322daf62ce400fe58c7f0495dda432ba568a75f579Jason Monkimport android.database.ContentObserver;
3300a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roosimport android.graphics.Bitmap;
34ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roosimport android.graphics.drawable.Drawable;
3500a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roosimport android.os.AsyncTask;
362daf62ce400fe58c7f0495dda432ba568a75f579Jason Monkimport android.os.Handler;
3700a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roosimport android.os.RemoteException;
38e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roosimport android.os.UserHandle;
3900a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roosimport android.os.UserManager;
402daf62ce400fe58c7f0495dda432ba568a75f579Jason Monkimport android.provider.Settings;
41523c404612c634f6901205fee4f4cae594f62982Fyodor Kupolovimport android.telephony.PhoneStateListener;
42523c404612c634f6901205fee4f4cae594f62982Fyodor Kupolovimport android.telephony.TelephonyManager;
4300a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roosimport android.util.Log;
44e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roosimport android.util.SparseArray;
4588b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roosimport android.util.SparseBooleanArray;
4600a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roosimport android.view.View;
4700a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roosimport android.view.ViewGroup;
4800a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roosimport android.widget.BaseAdapter;
4900a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos
50383db5ebcc3a4a615faf249bf4f126f42e80b82eTamas Berghammerimport com.android.internal.logging.nano.MetricsProto.MetricsEvent;
518852905b0b3837e326127c6dfef6f699124ce715Jason Monkimport com.android.internal.annotations.VisibleForTesting;
525e6c0ffd3e91cf0c5872de3e2d99e225ad1468f4Chris Wrenimport com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
5364d4dca63f65e4c7d4a829c85ff6670bdd34e2ebAlexandra Gherghinaimport com.android.internal.util.UserIcons;
541c7cda8bbfb848961536a4adbf2c81c5ffddae16Sudheer Shankaimport com.android.settingslib.RestrictedLockUtils;
5564d4dca63f65e4c7d4a829c85ff6670bdd34e2ebAlexandra Gherghinaimport com.android.systemui.GuestResumeSessionReceiver;
5664d4dca63f65e4c7d4a829c85ff6670bdd34e2ebAlexandra Gherghinaimport com.android.systemui.R;
57e25c18da7d2cc3e02620dadfcb976521821bc9d8Adrian Roosimport com.android.systemui.SystemUI;
583c2c34bb039e92d68f466b7d194cbbe8241d8d60Winsonimport com.android.systemui.SystemUISecondaryUserService;
590ceef211875515c2a7531f9baeae46339e700f3aJason Monkimport com.android.systemui.plugins.qs.QS.DetailAdapter;
6064d4dca63f65e4c7d4a829c85ff6670bdd34e2ebAlexandra Gherghinaimport com.android.systemui.qs.tiles.UserDetailView;
610ceef211875515c2a7531f9baeae46339e700f3aJason Monkimport com.android.systemui.plugins.qs.QS.ActivityStarter;
6264d4dca63f65e4c7d4a829c85ff6670bdd34e2ebAlexandra Gherghinaimport com.android.systemui.statusbar.phone.SystemUIDialog;
6364d4dca63f65e4c7d4a829c85ff6670bdd34e2ebAlexandra Gherghina
6400a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roosimport java.io.FileDescriptor;
6500a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roosimport java.io.PrintWriter;
6600a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roosimport java.lang.ref.WeakReference;
6700a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roosimport java.util.ArrayList;
6800a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roosimport java.util.List;
6900a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos
7000a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos/**
7100a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos * Keeps a list of all users on the device for user switching.
7200a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos */
7300a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roospublic class UserSwitcherController {
7400a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos
7500a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos    private static final String TAG = "UserSwitcherController";
765005244f10442e75c1f48973fdddce5facf3f360Adrian Roos    private static final boolean DEBUG = false;
772daf62ce400fe58c7f0495dda432ba568a75f579Jason Monk    private static final String SIMPLE_USER_SWITCHER_GLOBAL_SETTING =
782daf62ce400fe58c7f0495dda432ba568a75f579Jason Monk            "lockscreenSimpleUserSwitcher";
79f4d6ad26636760163083ae84c40d5b19cb6650f6Fyodor Kupolov    private static final String ACTION_REMOVE_GUEST = "com.android.systemui.REMOVE_GUEST";
80860397f6521249f1e2733e65ccebe0c0e781b82aXiaohui Chen    private static final String ACTION_LOGOUT_USER = "com.android.systemui.LOGOUT_USER";
8188b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos    private static final int PAUSE_REFRESH_USERS_TIMEOUT_MS = 3000;
8200a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos
83d81f8270bec71ec9a569c8308c42cacd7aba0d23Amith Yamasani    private static final String TAG_REMOVE_GUEST = "remove_guest";
84860397f6521249f1e2733e65ccebe0c0e781b82aXiaohui Chen    private static final String TAG_LOGOUT_USER = "logout_user";
85860397f6521249f1e2733e65ccebe0c0e781b82aXiaohui Chen
86d81f8270bec71ec9a569c8308c42cacd7aba0d23Amith Yamasani    private static final String PERMISSION_SELF = "com.android.systemui.permission.SELF";
87d81f8270bec71ec9a569c8308c42cacd7aba0d23Amith Yamasani
8813a58a91d362e74933b3064a65be4bf4449cfdc4Evan Rosky    protected final Context mContext;
8913a58a91d362e74933b3064a65be4bf4449cfdc4Evan Rosky    protected final UserManager mUserManager;
9000a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos    private final ArrayList<WeakReference<BaseUserAdapter>> mAdapters = new ArrayList<>();
915005244f10442e75c1f48973fdddce5facf3f360Adrian Roos    private final GuestResumeSessionReceiver mGuestResumeSessionReceiver
925005244f10442e75c1f48973fdddce5facf3f360Adrian Roos            = new GuestResumeSessionReceiver();
93ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos    private final KeyguardMonitor mKeyguardMonitor;
9413a58a91d362e74933b3064a65be4bf4449cfdc4Evan Rosky    protected final Handler mHandler;
951c7cda8bbfb848961536a4adbf2c81c5ffddae16Sudheer Shanka    private final ActivityStarter mActivityStarter;
9600a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos
9700a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos    private ArrayList<UserRecord> mUsers = new ArrayList<>();
985005244f10442e75c1f48973fdddce5facf3f360Adrian Roos    private Dialog mExitGuestDialog;
990c6763a19f32f73f8a940aaee7abecb2a04d1889Adrian Roos    private Dialog mAddUserDialog;
1007cb69df507f5f7956c52a2868a0d6e89aec6dde2Xiaohui Chen    private int mLastNonGuestUser = UserHandle.USER_SYSTEM;
10137c76807a047193338e3af317fb39373d69c7561Evan Rosky    private boolean mResumeUserOnGuestLogout = true;
102ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos    private boolean mSimpleUserSwitcher;
103ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos    private boolean mAddUsersWhenLocked;
10488b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos    private boolean mPauseRefreshUsers;
1053c2c34bb039e92d68f466b7d194cbbe8241d8d60Winson    private int mSecondaryUser = UserHandle.USER_NULL;
1063c2c34bb039e92d68f466b7d194cbbe8241d8d60Winson    private Intent mSecondaryUserServiceIntent;
10788b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos    private SparseBooleanArray mForcePictureLoadForUserId = new SparseBooleanArray(2);
10800a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos
10988b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos    public UserSwitcherController(Context context, KeyguardMonitor keyguardMonitor,
1101c7cda8bbfb848961536a4adbf2c81c5ffddae16Sudheer Shanka            Handler handler, ActivityStarter activityStarter) {
11100a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        mContext = context;
1125005244f10442e75c1f48973fdddce5facf3f360Adrian Roos        mGuestResumeSessionReceiver.register(context);
113ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos        mKeyguardMonitor = keyguardMonitor;
11488b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos        mHandler = handler;
1151c7cda8bbfb848961536a4adbf2c81c5ffddae16Sudheer Shanka        mActivityStarter = activityStarter;
11600a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        mUserManager = UserManager.get(context);
11700a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        IntentFilter filter = new IntentFilter();
11800a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        filter.addAction(Intent.ACTION_USER_ADDED);
11900a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        filter.addAction(Intent.ACTION_USER_REMOVED);
12000a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        filter.addAction(Intent.ACTION_USER_INFO_CHANGED);
12100a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        filter.addAction(Intent.ACTION_USER_SWITCHED);
122ad2e4bf9f36cf612db6c397feca8effb125ee541Amith Yamasani        filter.addAction(Intent.ACTION_USER_STOPPED);
12307140f7ffd56bf9d4946eba4e48b21a748125659Fyodor Kupolov        filter.addAction(Intent.ACTION_USER_UNLOCKED);
1247cb69df507f5f7956c52a2868a0d6e89aec6dde2Xiaohui Chen        mContext.registerReceiverAsUser(mReceiver, UserHandle.SYSTEM, filter,
125e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos                null /* permission */, null /* scheduler */);
1262daf62ce400fe58c7f0495dda432ba568a75f579Jason Monk
1273c2c34bb039e92d68f466b7d194cbbe8241d8d60Winson        mSecondaryUserServiceIntent = new Intent(context, SystemUISecondaryUserService.class);
1283c2c34bb039e92d68f466b7d194cbbe8241d8d60Winson
129d81f8270bec71ec9a569c8308c42cacd7aba0d23Amith Yamasani        filter = new IntentFilter();
130d81f8270bec71ec9a569c8308c42cacd7aba0d23Amith Yamasani        filter.addAction(ACTION_REMOVE_GUEST);
131860397f6521249f1e2733e65ccebe0c0e781b82aXiaohui Chen        filter.addAction(ACTION_LOGOUT_USER);
1325891a346abbde5bfe95a52633d05533406cc6a2eAmith Yamasani        mContext.registerReceiverAsUser(mReceiver, UserHandle.SYSTEM, filter,
133d81f8270bec71ec9a569c8308c42cacd7aba0d23Amith Yamasani                PERMISSION_SELF, null /* scheduler */);
134ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos
1352daf62ce400fe58c7f0495dda432ba568a75f579Jason Monk        mContext.getContentResolver().registerContentObserver(
1362daf62ce400fe58c7f0495dda432ba568a75f579Jason Monk                Settings.Global.getUriFor(SIMPLE_USER_SWITCHER_GLOBAL_SETTING), true,
137ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos                mSettingsObserver);
138ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos        mContext.getContentResolver().registerContentObserver(
139ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos                Settings.Global.getUriFor(Settings.Global.ADD_USERS_WHEN_LOCKED), true,
140ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos                mSettingsObserver);
14107140f7ffd56bf9d4946eba4e48b21a748125659Fyodor Kupolov        mContext.getContentResolver().registerContentObserver(
14207140f7ffd56bf9d4946eba4e48b21a748125659Fyodor Kupolov                Settings.Global.getUriFor(
14307140f7ffd56bf9d4946eba4e48b21a748125659Fyodor Kupolov                        Settings.Global.ALLOW_USER_SWITCHING_WHEN_SYSTEM_USER_LOCKED),
14407140f7ffd56bf9d4946eba4e48b21a748125659Fyodor Kupolov                true, mSettingsObserver);
145ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos        // Fetch initial values.
146ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos        mSettingsObserver.onChange(false);
147ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos
148ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos        keyguardMonitor.addCallback(mCallback);
149523c404612c634f6901205fee4f4cae594f62982Fyodor Kupolov        listenForCallState();
1502daf62ce400fe58c7f0495dda432ba568a75f579Jason Monk
151e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos        refreshUsers(UserHandle.USER_NULL);
15200a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos    }
15300a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos
154e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos    /**
155e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos     * Refreshes users from UserManager.
156e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos     *
157e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos     * The pictures are only loaded if they have not been loaded yet.
158e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos     *
159e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos     * @param forcePictureLoadForId forces the picture of the given user to be reloaded.
160e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos     */
16195ab7849444125387dc88088bb5197ee463d8c17Amith Yamasani    @SuppressWarnings("unchecked")
162e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos    private void refreshUsers(int forcePictureLoadForId) {
16388b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos        if (DEBUG) Log.d(TAG, "refreshUsers(forcePictureLoadForId=" + forcePictureLoadForId+")");
16488b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos        if (forcePictureLoadForId != UserHandle.USER_NULL) {
16588b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos            mForcePictureLoadForUserId.put(forcePictureLoadForId, true);
16688b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos        }
16788b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos
16888b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos        if (mPauseRefreshUsers) {
16988b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos            return;
17088b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos        }
171c5db390f5b5c6c685267dd22cf3b2926f54fba35Adrian Roos
172d390b893eafae634844d7b8b84efaa7baa199119Adrian Roos        boolean forceAllUsers = mForcePictureLoadForUserId.get(UserHandle.USER_ALL);
173c5db390f5b5c6c685267dd22cf3b2926f54fba35Adrian Roos        SparseArray<Bitmap> bitmaps = new SparseArray<>(mUsers.size());
174c5db390f5b5c6c685267dd22cf3b2926f54fba35Adrian Roos        final int N = mUsers.size();
175c5db390f5b5c6c685267dd22cf3b2926f54fba35Adrian Roos        for (int i = 0; i < N; i++) {
176c5db390f5b5c6c685267dd22cf3b2926f54fba35Adrian Roos            UserRecord r = mUsers.get(i);
177d390b893eafae634844d7b8b84efaa7baa199119Adrian Roos            if (r == null || r.picture == null || r.info == null || forceAllUsers
178d390b893eafae634844d7b8b84efaa7baa199119Adrian Roos                    || mForcePictureLoadForUserId.get(r.info.id)) {
179c5db390f5b5c6c685267dd22cf3b2926f54fba35Adrian Roos                continue;
180e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos            }
181c5db390f5b5c6c685267dd22cf3b2926f54fba35Adrian Roos            bitmaps.put(r.info.id, r.picture);
182e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos        }
18388b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos        mForcePictureLoadForUserId.clear();
184e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos
185ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos        final boolean addUsersWhenLocked = mAddUsersWhenLocked;
186e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos        new AsyncTask<SparseArray<Bitmap>, Void, ArrayList<UserRecord>>() {
187e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos            @SuppressWarnings("unchecked")
18800a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos            @Override
189e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos            protected ArrayList<UserRecord> doInBackground(SparseArray<Bitmap>... params) {
190e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos                final SparseArray<Bitmap> bitmaps = params[0];
19100a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos                List<UserInfo> infos = mUserManager.getUsers(true);
19200a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos                if (infos == null) {
19300a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos                    return null;
19400a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos                }
19500a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos                ArrayList<UserRecord> records = new ArrayList<>(infos.size());
19600a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos                int currentId = ActivityManager.getCurrentUser();
197523c404612c634f6901205fee4f4cae594f62982Fyodor Kupolov                boolean canSwitchUsers = mUserManager.canSwitchUsers();
1987cb69df507f5f7956c52a2868a0d6e89aec6dde2Xiaohui Chen                UserInfo currentUserInfo = null;
19900a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos                UserRecord guestRecord = null;
20000a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos
20100a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos                for (UserInfo info : infos) {
20200a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos                    boolean isCurrent = currentId == info.id;
2037cb69df507f5f7956c52a2868a0d6e89aec6dde2Xiaohui Chen                    if (isCurrent) {
2047cb69df507f5f7956c52a2868a0d6e89aec6dde2Xiaohui Chen                        currentUserInfo = info;
2057cb69df507f5f7956c52a2868a0d6e89aec6dde2Xiaohui Chen                    }
206523c404612c634f6901205fee4f4cae594f62982Fyodor Kupolov                    boolean switchToEnabled = canSwitchUsers || isCurrent;
2071ddda4793c26fd249590fd3549cf060ecb7c157bLenka Trochtova                    if (info.isEnabled()) {
2081ddda4793c26fd249590fd3549cf060ecb7c157bLenka Trochtova                        if (info.isGuest()) {
209523c404612c634f6901205fee4f4cae594f62982Fyodor Kupolov                            // Tapping guest icon triggers remove and a user switch therefore
210523c404612c634f6901205fee4f4cae594f62982Fyodor Kupolov                            // the icon shouldn't be enabled even if the user is current
2111ddda4793c26fd249590fd3549cf060ecb7c157bLenka Trochtova                            guestRecord = new UserRecord(info, null /* picture */,
2121ddda4793c26fd249590fd3549cf060ecb7c157bLenka Trochtova                                    true /* isGuest */, isCurrent, false /* isAddUser */,
213523c404612c634f6901205fee4f4cae594f62982Fyodor Kupolov                                    false /* isRestricted */, canSwitchUsers);
2141ddda4793c26fd249590fd3549cf060ecb7c157bLenka Trochtova                        } else if (info.supportsSwitchToByUser()) {
2151ddda4793c26fd249590fd3549cf060ecb7c157bLenka Trochtova                            Bitmap picture = bitmaps.get(info.id);
2161ddda4793c26fd249590fd3549cf060ecb7c157bLenka Trochtova                            if (picture == null) {
2171ddda4793c26fd249590fd3549cf060ecb7c157bLenka Trochtova                                picture = mUserManager.getUserIcon(info.id);
2181ddda4793c26fd249590fd3549cf060ecb7c157bLenka Trochtova
2191ddda4793c26fd249590fd3549cf060ecb7c157bLenka Trochtova                                if (picture != null) {
220aa7f51fe8c6e54485f0b5037c17777b4695d19e0Evan Rosky                                    int avatarSize = mContext.getResources()
221aa7f51fe8c6e54485f0b5037c17777b4695d19e0Evan Rosky                                            .getDimensionPixelSize(R.dimen.max_avatar_size);
222aa7f51fe8c6e54485f0b5037c17777b4695d19e0Evan Rosky                                    picture = Bitmap.createScaledBitmap(
223aa7f51fe8c6e54485f0b5037c17777b4695d19e0Evan Rosky                                            picture, avatarSize, avatarSize, true);
2241ddda4793c26fd249590fd3549cf060ecb7c157bLenka Trochtova                                }
225cba0faadbe1c8cf7c6b264b761d747f7381a2f93Adrian Roos                            }
2261ddda4793c26fd249590fd3549cf060ecb7c157bLenka Trochtova                            int index = isCurrent ? 0 : records.size();
2271ddda4793c26fd249590fd3549cf060ecb7c157bLenka Trochtova                            records.add(index, new UserRecord(info, picture, false /* isGuest */,
2281ddda4793c26fd249590fd3549cf060ecb7c157bLenka Trochtova                                    isCurrent, false /* isAddUser */, false /* isRestricted */,
2291ddda4793c26fd249590fd3549cf060ecb7c157bLenka Trochtova                                    switchToEnabled));
2304d75c079f35d85b687d8349e5e2940447d01198eDan Sandler                        }
23100a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos                    }
23200a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos                }
23300a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos
234a8fbbb30eae03b9ed7a3e6ea78da13480a53b73dSudheer Shanka                boolean systemCanCreateUsers = !mUserManager.hasBaseUserRestriction(
235a8fbbb30eae03b9ed7a3e6ea78da13480a53b73dSudheer Shanka                                UserManager.DISALLOW_ADD_USER, UserHandle.SYSTEM);
2367cb69df507f5f7956c52a2868a0d6e89aec6dde2Xiaohui Chen                boolean currentUserCanCreateUsers = currentUserInfo != null
2377cb69df507f5f7956c52a2868a0d6e89aec6dde2Xiaohui Chen                        && (currentUserInfo.isAdmin()
238a8fbbb30eae03b9ed7a3e6ea78da13480a53b73dSudheer Shanka                                || currentUserInfo.id == UserHandle.USER_SYSTEM)
239a8fbbb30eae03b9ed7a3e6ea78da13480a53b73dSudheer Shanka                        && systemCanCreateUsers;
240a8fbbb30eae03b9ed7a3e6ea78da13480a53b73dSudheer Shanka                boolean anyoneCanCreateUsers = systemCanCreateUsers && addUsersWhenLocked;
241a8fbbb30eae03b9ed7a3e6ea78da13480a53b73dSudheer Shanka                boolean canCreateGuest = (currentUserCanCreateUsers || anyoneCanCreateUsers)
242ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos                        && guestRecord == null;
243a8fbbb30eae03b9ed7a3e6ea78da13480a53b73dSudheer Shanka                boolean canCreateUser = (currentUserCanCreateUsers || anyoneCanCreateUsers)
24495ab7849444125387dc88088bb5197ee463d8c17Amith Yamasani                        && mUserManager.canAddMoreUsers();
245ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos                boolean createIsRestricted = !addUsersWhenLocked;
246ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos
2472daf62ce400fe58c7f0495dda432ba568a75f579Jason Monk                if (!mSimpleUserSwitcher) {
2482daf62ce400fe58c7f0495dda432ba568a75f579Jason Monk                    if (guestRecord == null) {
249ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos                        if (canCreateGuest) {
2501c7cda8bbfb848961536a4adbf2c81c5ffddae16Sudheer Shanka                            guestRecord = new UserRecord(null /* info */, null /* picture */,
251ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos                                    true /* isGuest */, false /* isCurrent */,
252523c404612c634f6901205fee4f4cae594f62982Fyodor Kupolov                                    false /* isAddUser */, createIsRestricted, canSwitchUsers);
253a8fbbb30eae03b9ed7a3e6ea78da13480a53b73dSudheer Shanka                            checkIfAddUserDisallowedByAdminOnly(guestRecord);
2541c7cda8bbfb848961536a4adbf2c81c5ffddae16Sudheer Shanka                            records.add(guestRecord);
255ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos                        }
2562daf62ce400fe58c7f0495dda432ba568a75f579Jason Monk                    } else {
257bed6e3bedc8845e8f9cd59ad436d140b0875cb6bAdrian Roos                        int index = guestRecord.isCurrent ? 0 : records.size();
258bed6e3bedc8845e8f9cd59ad436d140b0875cb6bAdrian Roos                        records.add(index, guestRecord);
2592daf62ce400fe58c7f0495dda432ba568a75f579Jason Monk                    }
26000a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos                }
26100a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos
262092be7de024b8b1a050ad247a016febc795546afJason Monk                if (!mSimpleUserSwitcher && canCreateUser) {
2631c7cda8bbfb848961536a4adbf2c81c5ffddae16Sudheer Shanka                    UserRecord addUserRecord = new UserRecord(null /* info */, null /* picture */,
264ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos                            false /* isGuest */, false /* isCurrent */, true /* isAddUser */,
265523c404612c634f6901205fee4f4cae594f62982Fyodor Kupolov                            createIsRestricted, canSwitchUsers);
266a8fbbb30eae03b9ed7a3e6ea78da13480a53b73dSudheer Shanka                    checkIfAddUserDisallowedByAdminOnly(addUserRecord);
2671c7cda8bbfb848961536a4adbf2c81c5ffddae16Sudheer Shanka                    records.add(addUserRecord);
268ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos                }
269ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos
27000a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos                return records;
27100a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos            }
27200a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos
27300a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos            @Override
27400a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos            protected void onPostExecute(ArrayList<UserRecord> userRecords) {
27500a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos                if (userRecords != null) {
27600a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos                    mUsers = userRecords;
27700a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos                    notifyAdapters();
27800a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos                }
27900a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos            }
280ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos        }.execute((SparseArray) bitmaps);
28100a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos    }
28200a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos
28388b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos    private void pauseRefreshUsers() {
28488b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos        if (!mPauseRefreshUsers) {
28588b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos            mHandler.postDelayed(mUnpauseRefreshUsers, PAUSE_REFRESH_USERS_TIMEOUT_MS);
28688b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos            mPauseRefreshUsers = true;
28788b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos        }
28888b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos    }
28988b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos
29000a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos    private void notifyAdapters() {
29100a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        for (int i = mAdapters.size() - 1; i >= 0; i--) {
29200a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos            BaseUserAdapter adapter = mAdapters.get(i).get();
29300a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos            if (adapter != null) {
29400a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos                adapter.notifyDataSetChanged();
29500a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos            } else {
29600a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos                mAdapters.remove(i);
29700a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos            }
29800a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        }
29900a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos    }
30000a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos
3012daf62ce400fe58c7f0495dda432ba568a75f579Jason Monk    public boolean isSimpleUserSwitcher() {
3022daf62ce400fe58c7f0495dda432ba568a75f579Jason Monk        return mSimpleUserSwitcher;
3032daf62ce400fe58c7f0495dda432ba568a75f579Jason Monk    }
3042daf62ce400fe58c7f0495dda432ba568a75f579Jason Monk
305cc3a74f6ef13ca9a783845e7a04ca6561035c98bXiyuan Xia    public boolean useFullscreenUserSwitcher() {
306cc3a74f6ef13ca9a783845e7a04ca6561035c98bXiyuan Xia        // Use adb to override:
307cc3a74f6ef13ca9a783845e7a04ca6561035c98bXiyuan Xia        // adb shell settings put system enable_fullscreen_user_switcher 0  # Turn it off.
308cc3a74f6ef13ca9a783845e7a04ca6561035c98bXiyuan Xia        // adb shell settings put system enable_fullscreen_user_switcher 1  # Turn it on.
309cc3a74f6ef13ca9a783845e7a04ca6561035c98bXiyuan Xia        // Restart SystemUI or adb reboot.
310cc3a74f6ef13ca9a783845e7a04ca6561035c98bXiyuan Xia        final int DEFAULT = -1;
311cc3a74f6ef13ca9a783845e7a04ca6561035c98bXiyuan Xia        final int overrideUseFullscreenUserSwitcher =
312cc3a74f6ef13ca9a783845e7a04ca6561035c98bXiyuan Xia                Settings.System.getInt(mContext.getContentResolver(),
313cc3a74f6ef13ca9a783845e7a04ca6561035c98bXiyuan Xia                        "enable_fullscreen_user_switcher", DEFAULT);
314cc3a74f6ef13ca9a783845e7a04ca6561035c98bXiyuan Xia        if (overrideUseFullscreenUserSwitcher != DEFAULT) {
315cc3a74f6ef13ca9a783845e7a04ca6561035c98bXiyuan Xia            return overrideUseFullscreenUserSwitcher != 0;
316cc3a74f6ef13ca9a783845e7a04ca6561035c98bXiyuan Xia        }
317cc3a74f6ef13ca9a783845e7a04ca6561035c98bXiyuan Xia        // Otherwise default to the build setting.
31840f9dabaa880eaff54099a3763224b241a6668e6Xiyuan Xia        return mContext.getResources().getBoolean(R.bool.config_enableFullscreenUserSwitcher);
319cc3a74f6ef13ca9a783845e7a04ca6561035c98bXiyuan Xia    }
320cc3a74f6ef13ca9a783845e7a04ca6561035c98bXiyuan Xia
32137c76807a047193338e3af317fb39373d69c7561Evan Rosky    public void setResumeUserOnGuestLogout(boolean resume) {
32237c76807a047193338e3af317fb39373d69c7561Evan Rosky        mResumeUserOnGuestLogout = resume;
32337c76807a047193338e3af317fb39373d69c7561Evan Rosky    }
32437c76807a047193338e3af317fb39373d69c7561Evan Rosky
3251b30f79cffbe9e0c2b974fa3ee48001edcdd6c05Xiyuan Xia    public void logoutCurrentUser() {
3261b30f79cffbe9e0c2b974fa3ee48001edcdd6c05Xiyuan Xia        int currentUser = ActivityManager.getCurrentUser();
3271b30f79cffbe9e0c2b974fa3ee48001edcdd6c05Xiyuan Xia        if (currentUser != UserHandle.USER_SYSTEM) {
328b5690bc3086af1d1f064a080c728090de24d6f96Fyodor Kupolov            pauseRefreshUsers();
329b5690bc3086af1d1f064a080c728090de24d6f96Fyodor Kupolov            ActivityManager.logoutCurrentUser();
3301b30f79cffbe9e0c2b974fa3ee48001edcdd6c05Xiyuan Xia        }
3311b30f79cffbe9e0c2b974fa3ee48001edcdd6c05Xiyuan Xia    }
3321b30f79cffbe9e0c2b974fa3ee48001edcdd6c05Xiyuan Xia
333cc3a74f6ef13ca9a783845e7a04ca6561035c98bXiyuan Xia    public void removeUserId(int userId) {
334cc3a74f6ef13ca9a783845e7a04ca6561035c98bXiyuan Xia        if (userId == UserHandle.USER_SYSTEM) {
335cc3a74f6ef13ca9a783845e7a04ca6561035c98bXiyuan Xia            Log.w(TAG, "User " + userId + " could not removed.");
336cc3a74f6ef13ca9a783845e7a04ca6561035c98bXiyuan Xia            return;
337cc3a74f6ef13ca9a783845e7a04ca6561035c98bXiyuan Xia        }
338cc3a74f6ef13ca9a783845e7a04ca6561035c98bXiyuan Xia        if (ActivityManager.getCurrentUser() == userId) {
339cc3a74f6ef13ca9a783845e7a04ca6561035c98bXiyuan Xia            switchToUserId(UserHandle.USER_SYSTEM);
340cc3a74f6ef13ca9a783845e7a04ca6561035c98bXiyuan Xia        }
341cc3a74f6ef13ca9a783845e7a04ca6561035c98bXiyuan Xia        if (mUserManager.removeUser(userId)) {
342cc3a74f6ef13ca9a783845e7a04ca6561035c98bXiyuan Xia            refreshUsers(UserHandle.USER_NULL);
343cc3a74f6ef13ca9a783845e7a04ca6561035c98bXiyuan Xia        }
344cc3a74f6ef13ca9a783845e7a04ca6561035c98bXiyuan Xia    }
345cc3a74f6ef13ca9a783845e7a04ca6561035c98bXiyuan Xia
34600a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos    public void switchTo(UserRecord record) {
34700a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        int id;
34800a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        if (record.isGuest && record.info == null) {
34900a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos            // No guest user. Create one.
350f99727cb878f9709f6c0263c0283257decbaebadAdrian Roos            UserInfo guest = mUserManager.createGuest(
351f99727cb878f9709f6c0263c0283257decbaebadAdrian Roos                    mContext, mContext.getString(R.string.guest_nickname));
352f99727cb878f9709f6c0263c0283257decbaebadAdrian Roos            if (guest == null) {
353f99727cb878f9709f6c0263c0283257decbaebadAdrian Roos                // Couldn't create guest, most likely because there already exists one, we just
354f99727cb878f9709f6c0263c0283257decbaebadAdrian Roos                // haven't reloaded the user list yet.
355f99727cb878f9709f6c0263c0283257decbaebadAdrian Roos                return;
356f99727cb878f9709f6c0263c0283257decbaebadAdrian Roos            }
357f99727cb878f9709f6c0263c0283257decbaebadAdrian Roos            id = guest.id;
358ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos        } else if (record.isAddUser) {
3590c6763a19f32f73f8a940aaee7abecb2a04d1889Adrian Roos            showAddUserDialog();
3600c6763a19f32f73f8a940aaee7abecb2a04d1889Adrian Roos            return;
36100a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        } else {
36200a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos            id = record.info.id;
36300a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        }
36400a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos
36513a58a91d362e74933b3064a65be4bf4449cfdc4Evan Rosky        int currUserId = ActivityManager.getCurrentUser();
36613a58a91d362e74933b3064a65be4bf4449cfdc4Evan Rosky        if (currUserId == id) {
367e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos            if (record.isGuest) {
3685005244f10442e75c1f48973fdddce5facf3f360Adrian Roos                showExitGuestDialog(id);
369e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos            }
37000a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos            return;
37100a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        }
37200a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos
37313a58a91d362e74933b3064a65be4bf4449cfdc4Evan Rosky        if (UserManager.isGuestUserEphemeral()) {
37413a58a91d362e74933b3064a65be4bf4449cfdc4Evan Rosky            // If switching from guest, we want to bring up the guest exit dialog instead of switching
37513a58a91d362e74933b3064a65be4bf4449cfdc4Evan Rosky            UserInfo currUserInfo = mUserManager.getUserInfo(currUserId);
37613a58a91d362e74933b3064a65be4bf4449cfdc4Evan Rosky            if (currUserInfo != null && currUserInfo.isGuest()) {
37713a58a91d362e74933b3064a65be4bf4449cfdc4Evan Rosky                showExitGuestDialog(currUserId, record.resolveId());
37813a58a91d362e74933b3064a65be4bf4449cfdc4Evan Rosky                return;
37913a58a91d362e74933b3064a65be4bf4449cfdc4Evan Rosky            }
38013a58a91d362e74933b3064a65be4bf4449cfdc4Evan Rosky        }
38113a58a91d362e74933b3064a65be4bf4449cfdc4Evan Rosky
382e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos        switchToUserId(id);
383e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos    }
384e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos
385caab2666bd8dbf1e499c309a62f4dff0056d2948Fyodor Kupolov    public void switchTo(int userId) {
386caab2666bd8dbf1e499c309a62f4dff0056d2948Fyodor Kupolov        final int count = mUsers.size();
387caab2666bd8dbf1e499c309a62f4dff0056d2948Fyodor Kupolov        for (int i = 0; i < count; ++i) {
388caab2666bd8dbf1e499c309a62f4dff0056d2948Fyodor Kupolov            UserRecord record = mUsers.get(i);
389caab2666bd8dbf1e499c309a62f4dff0056d2948Fyodor Kupolov            if (record.info != null && record.info.id == userId) {
390caab2666bd8dbf1e499c309a62f4dff0056d2948Fyodor Kupolov                switchTo(record);
391caab2666bd8dbf1e499c309a62f4dff0056d2948Fyodor Kupolov                return;
392caab2666bd8dbf1e499c309a62f4dff0056d2948Fyodor Kupolov            }
393caab2666bd8dbf1e499c309a62f4dff0056d2948Fyodor Kupolov        }
394caab2666bd8dbf1e499c309a62f4dff0056d2948Fyodor Kupolov
395caab2666bd8dbf1e499c309a62f4dff0056d2948Fyodor Kupolov        Log.e(TAG, "Couldn't switch to user, id=" + userId);
396caab2666bd8dbf1e499c309a62f4dff0056d2948Fyodor Kupolov    }
397caab2666bd8dbf1e499c309a62f4dff0056d2948Fyodor Kupolov
3988ba446c9bad94e91cf83c579261298552d51d249Daniel Nishi    public int getSwitchableUserCount() {
3998ba446c9bad94e91cf83c579261298552d51d249Daniel Nishi        int count = 0;
4008ba446c9bad94e91cf83c579261298552d51d249Daniel Nishi        final int N = mUsers.size();
4018ba446c9bad94e91cf83c579261298552d51d249Daniel Nishi        for (int i = 0; i < N; ++i) {
4028ba446c9bad94e91cf83c579261298552d51d249Daniel Nishi            UserRecord record = mUsers.get(i);
4038ba446c9bad94e91cf83c579261298552d51d249Daniel Nishi            if (record.info != null && record.info.supportsSwitchTo()) {
4048ba446c9bad94e91cf83c579261298552d51d249Daniel Nishi                count++;
4058ba446c9bad94e91cf83c579261298552d51d249Daniel Nishi            }
4068ba446c9bad94e91cf83c579261298552d51d249Daniel Nishi        }
4078ba446c9bad94e91cf83c579261298552d51d249Daniel Nishi        return count;
4088ba446c9bad94e91cf83c579261298552d51d249Daniel Nishi    }
4098ba446c9bad94e91cf83c579261298552d51d249Daniel Nishi
41013a58a91d362e74933b3064a65be4bf4449cfdc4Evan Rosky    protected void switchToUserId(int id) {
41100a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        try {
41288b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos            pauseRefreshUsers();
413dc589ac82b5fe2063f4cfd94c8ae26d43d5420a0Sudheer Shanka            ActivityManager.getService().switchUser(id);
41400a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        } catch (RemoteException e) {
41500a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos            Log.e(TAG, "Couldn't switch user.", e);
41600a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        }
41700a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos    }
41800a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos
4195005244f10442e75c1f48973fdddce5facf3f360Adrian Roos    private void showExitGuestDialog(int id) {
42013a58a91d362e74933b3064a65be4bf4449cfdc4Evan Rosky        int newId = UserHandle.USER_SYSTEM;
42113a58a91d362e74933b3064a65be4bf4449cfdc4Evan Rosky        if (mResumeUserOnGuestLogout && mLastNonGuestUser != UserHandle.USER_SYSTEM) {
42213a58a91d362e74933b3064a65be4bf4449cfdc4Evan Rosky            UserInfo info = mUserManager.getUserInfo(mLastNonGuestUser);
42313a58a91d362e74933b3064a65be4bf4449cfdc4Evan Rosky            if (info != null && info.isEnabled() && info.supportsSwitchToByUser()) {
42413a58a91d362e74933b3064a65be4bf4449cfdc4Evan Rosky                newId = info.id;
42513a58a91d362e74933b3064a65be4bf4449cfdc4Evan Rosky            }
42613a58a91d362e74933b3064a65be4bf4449cfdc4Evan Rosky        }
42713a58a91d362e74933b3064a65be4bf4449cfdc4Evan Rosky        showExitGuestDialog(id, newId);
42813a58a91d362e74933b3064a65be4bf4449cfdc4Evan Rosky    }
42913a58a91d362e74933b3064a65be4bf4449cfdc4Evan Rosky
43013a58a91d362e74933b3064a65be4bf4449cfdc4Evan Rosky    protected void showExitGuestDialog(int id, int targetId) {
4315005244f10442e75c1f48973fdddce5facf3f360Adrian Roos        if (mExitGuestDialog != null && mExitGuestDialog.isShowing()) {
4325005244f10442e75c1f48973fdddce5facf3f360Adrian Roos            mExitGuestDialog.cancel();
4335005244f10442e75c1f48973fdddce5facf3f360Adrian Roos        }
43413a58a91d362e74933b3064a65be4bf4449cfdc4Evan Rosky        mExitGuestDialog = new ExitGuestDialog(mContext, id, targetId);
4355005244f10442e75c1f48973fdddce5facf3f360Adrian Roos        mExitGuestDialog.show();
4365005244f10442e75c1f48973fdddce5facf3f360Adrian Roos    }
4375005244f10442e75c1f48973fdddce5facf3f360Adrian Roos
43892c91412ba099f5b5d17a7e28123629a1f7410c8Muyuan Li    public void showAddUserDialog() {
4390c6763a19f32f73f8a940aaee7abecb2a04d1889Adrian Roos        if (mAddUserDialog != null && mAddUserDialog.isShowing()) {
4400c6763a19f32f73f8a940aaee7abecb2a04d1889Adrian Roos            mAddUserDialog.cancel();
4410c6763a19f32f73f8a940aaee7abecb2a04d1889Adrian Roos        }
4420c6763a19f32f73f8a940aaee7abecb2a04d1889Adrian Roos        mAddUserDialog = new AddUserDialog(mContext);
4430c6763a19f32f73f8a940aaee7abecb2a04d1889Adrian Roos        mAddUserDialog.show();
4440c6763a19f32f73f8a940aaee7abecb2a04d1889Adrian Roos    }
4450c6763a19f32f73f8a940aaee7abecb2a04d1889Adrian Roos
44613a58a91d362e74933b3064a65be4bf4449cfdc4Evan Rosky    protected void exitGuest(int id, int targetId) {
44713a58a91d362e74933b3064a65be4bf4449cfdc4Evan Rosky        switchToUserId(targetId);
448e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos        mUserManager.removeUser(id);
449e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos    }
450e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos
451523c404612c634f6901205fee4f4cae594f62982Fyodor Kupolov    private void listenForCallState() {
452705a4bc62341d70a9b75b28f68c64efc88321438Jason Monk        TelephonyManager.from(mContext).listen(mPhoneStateListener,
453705a4bc62341d70a9b75b28f68c64efc88321438Jason Monk                PhoneStateListener.LISTEN_CALL_STATE);
454523c404612c634f6901205fee4f4cae594f62982Fyodor Kupolov    }
455523c404612c634f6901205fee4f4cae594f62982Fyodor Kupolov
456705a4bc62341d70a9b75b28f68c64efc88321438Jason Monk    private final PhoneStateListener mPhoneStateListener = new PhoneStateListener() {
457705a4bc62341d70a9b75b28f68c64efc88321438Jason Monk        private int mCallState;
458705a4bc62341d70a9b75b28f68c64efc88321438Jason Monk
459705a4bc62341d70a9b75b28f68c64efc88321438Jason Monk        @Override
460705a4bc62341d70a9b75b28f68c64efc88321438Jason Monk        public void onCallStateChanged(int state, String incomingNumber) {
461705a4bc62341d70a9b75b28f68c64efc88321438Jason Monk            if (mCallState == state) return;
462705a4bc62341d70a9b75b28f68c64efc88321438Jason Monk            if (DEBUG) Log.v(TAG, "Call state changed: " + state);
463705a4bc62341d70a9b75b28f68c64efc88321438Jason Monk            mCallState = state;
464705a4bc62341d70a9b75b28f68c64efc88321438Jason Monk            int currentUserId = ActivityManager.getCurrentUser();
465705a4bc62341d70a9b75b28f68c64efc88321438Jason Monk            UserInfo userInfo = mUserManager.getUserInfo(currentUserId);
466705a4bc62341d70a9b75b28f68c64efc88321438Jason Monk            if (userInfo != null && userInfo.isGuest()) {
467705a4bc62341d70a9b75b28f68c64efc88321438Jason Monk                showGuestNotification(currentUserId);
468705a4bc62341d70a9b75b28f68c64efc88321438Jason Monk            }
469705a4bc62341d70a9b75b28f68c64efc88321438Jason Monk            refreshUsers(UserHandle.USER_NULL);
470705a4bc62341d70a9b75b28f68c64efc88321438Jason Monk        }
471705a4bc62341d70a9b75b28f68c64efc88321438Jason Monk    };
472705a4bc62341d70a9b75b28f68c64efc88321438Jason Monk
47300a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos    private BroadcastReceiver mReceiver = new BroadcastReceiver() {
47400a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        @Override
47500a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        public void onReceive(Context context, Intent intent) {
4765005244f10442e75c1f48973fdddce5facf3f360Adrian Roos            if (DEBUG) {
4775005244f10442e75c1f48973fdddce5facf3f360Adrian Roos                Log.v(TAG, "Broadcast: a=" + intent.getAction()
4785005244f10442e75c1f48973fdddce5facf3f360Adrian Roos                       + " user=" + intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1));
4795005244f10442e75c1f48973fdddce5facf3f360Adrian Roos            }
48088b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos
48188b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos            boolean unpauseRefreshUsers = false;
48288b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos            int forcePictureLoadForId = UserHandle.USER_NULL;
48388b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos
484f4d6ad26636760163083ae84c40d5b19cb6650f6Fyodor Kupolov            if (ACTION_REMOVE_GUEST.equals(intent.getAction())) {
485f4d6ad26636760163083ae84c40d5b19cb6650f6Fyodor Kupolov                int currentUser = ActivityManager.getCurrentUser();
486f4d6ad26636760163083ae84c40d5b19cb6650f6Fyodor Kupolov                UserInfo userInfo = mUserManager.getUserInfo(currentUser);
487f4d6ad26636760163083ae84c40d5b19cb6650f6Fyodor Kupolov                if (userInfo != null && userInfo.isGuest()) {
488f4d6ad26636760163083ae84c40d5b19cb6650f6Fyodor Kupolov                    showExitGuestDialog(currentUser);
489f4d6ad26636760163083ae84c40d5b19cb6650f6Fyodor Kupolov                }
490f4d6ad26636760163083ae84c40d5b19cb6650f6Fyodor Kupolov                return;
49180996bbf40ff192117c391074ed2f9b2cde4e69aAdrian Roos            } else if (ACTION_LOGOUT_USER.equals(intent.getAction())) {
4921b30f79cffbe9e0c2b974fa3ee48001edcdd6c05Xiyuan Xia                logoutCurrentUser();
49388b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos            } else if (Intent.ACTION_USER_SWITCHED.equals(intent.getAction())) {
4945005244f10442e75c1f48973fdddce5facf3f360Adrian Roos                if (mExitGuestDialog != null && mExitGuestDialog.isShowing()) {
4955005244f10442e75c1f48973fdddce5facf3f360Adrian Roos                    mExitGuestDialog.cancel();
4965005244f10442e75c1f48973fdddce5facf3f360Adrian Roos                    mExitGuestDialog = null;
4975005244f10442e75c1f48973fdddce5facf3f360Adrian Roos                }
4985005244f10442e75c1f48973fdddce5facf3f360Adrian Roos
49900a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos                final int currentId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
5007cb69df507f5f7956c52a2868a0d6e89aec6dde2Xiaohui Chen                final UserInfo userInfo = mUserManager.getUserInfo(currentId);
50100a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos                final int N = mUsers.size();
50200a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos                for (int i = 0; i < N; i++) {
50300a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos                    UserRecord record = mUsers.get(i);
504e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos                    if (record.info == null) continue;
50500a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos                    boolean shouldBeCurrent = record.info.id == currentId;
50600a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos                    if (record.isCurrent != shouldBeCurrent) {
50700a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos                        mUsers.set(i, record.copyWithIsCurrent(shouldBeCurrent));
50800a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos                    }
50970441467f4dc232cd8e6142f0afc117787dc979bAdrian Roos                    if (shouldBeCurrent && !record.isGuest) {
51070441467f4dc232cd8e6142f0afc117787dc979bAdrian Roos                        mLastNonGuestUser = record.info.id;
51170441467f4dc232cd8e6142f0afc117787dc979bAdrian Roos                    }
5127cb69df507f5f7956c52a2868a0d6e89aec6dde2Xiaohui Chen                    if ((userInfo == null || !userInfo.isAdmin()) && record.isRestricted) {
513ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos                        // Immediately remove restricted records in case the AsyncTask is too slow.
514ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos                        mUsers.remove(i);
515ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos                        i--;
516ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos                    }
51700a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos                }
51800a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos                notifyAdapters();
519860397f6521249f1e2733e65ccebe0c0e781b82aXiaohui Chen
5203c2c34bb039e92d68f466b7d194cbbe8241d8d60Winson                // Disconnect from the old secondary user's service
5213c2c34bb039e92d68f466b7d194cbbe8241d8d60Winson                if (mSecondaryUser != UserHandle.USER_NULL) {
5223c2c34bb039e92d68f466b7d194cbbe8241d8d60Winson                    context.stopServiceAsUser(mSecondaryUserServiceIntent,
5233c2c34bb039e92d68f466b7d194cbbe8241d8d60Winson                            UserHandle.of(mSecondaryUser));
5243c2c34bb039e92d68f466b7d194cbbe8241d8d60Winson                    mSecondaryUser = UserHandle.USER_NULL;
5253c2c34bb039e92d68f466b7d194cbbe8241d8d60Winson                }
5263c2c34bb039e92d68f466b7d194cbbe8241d8d60Winson                // Connect to the new secondary user's service (purely to ensure that a persistent
5273c2c34bb039e92d68f466b7d194cbbe8241d8d60Winson                // SystemUI application is created for that user)
528ec015d5cb510d26d4e951feb240be8025f477ff5Xiaohui Chen                if (userInfo != null && userInfo.id != UserHandle.USER_SYSTEM) {
5293c2c34bb039e92d68f466b7d194cbbe8241d8d60Winson                    context.startServiceAsUser(mSecondaryUserServiceIntent,
5303c2c34bb039e92d68f466b7d194cbbe8241d8d60Winson                            UserHandle.of(userInfo.id));
5313c2c34bb039e92d68f466b7d194cbbe8241d8d60Winson                    mSecondaryUser = userInfo.id;
5323c2c34bb039e92d68f466b7d194cbbe8241d8d60Winson                }
5333c2c34bb039e92d68f466b7d194cbbe8241d8d60Winson
534860397f6521249f1e2733e65ccebe0c0e781b82aXiaohui Chen                if (UserManager.isSplitSystemUser() && userInfo != null && !userInfo.isGuest()
535860397f6521249f1e2733e65ccebe0c0e781b82aXiaohui Chen                        && userInfo.id != UserHandle.USER_SYSTEM) {
536860397f6521249f1e2733e65ccebe0c0e781b82aXiaohui Chen                    showLogoutNotification(currentId);
537860397f6521249f1e2733e65ccebe0c0e781b82aXiaohui Chen                }
538ce161861c3507c91c25b2491abac1e7611d14c5cFyodor Kupolov                if (userInfo != null && userInfo.isGuest()) {
539ce161861c3507c91c25b2491abac1e7611d14c5cFyodor Kupolov                    showGuestNotification(currentId);
540ce161861c3507c91c25b2491abac1e7611d14c5cFyodor Kupolov                }
54188b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos                unpauseRefreshUsers = true;
54288b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos            } else if (Intent.ACTION_USER_INFO_CHANGED.equals(intent.getAction())) {
543e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos                forcePictureLoadForId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE,
544e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos                        UserHandle.USER_NULL);
54507140f7ffd56bf9d4946eba4e48b21a748125659Fyodor Kupolov            } else if (Intent.ACTION_USER_UNLOCKED.equals(intent.getAction())) {
54607140f7ffd56bf9d4946eba4e48b21a748125659Fyodor Kupolov                // Unlocking the system user may require a refresh
54707140f7ffd56bf9d4946eba4e48b21a748125659Fyodor Kupolov                int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL);
54807140f7ffd56bf9d4946eba4e48b21a748125659Fyodor Kupolov                if (userId != UserHandle.USER_SYSTEM) {
54907140f7ffd56bf9d4946eba4e48b21a748125659Fyodor Kupolov                    return;
55007140f7ffd56bf9d4946eba4e48b21a748125659Fyodor Kupolov                }
551e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos            }
552e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos            refreshUsers(forcePictureLoadForId);
55388b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos            if (unpauseRefreshUsers) {
55488b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos                mUnpauseRefreshUsers.run();
55588b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos            }
55600a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        }
557f4d6ad26636760163083ae84c40d5b19cb6650f6Fyodor Kupolov
558860397f6521249f1e2733e65ccebe0c0e781b82aXiaohui Chen        private void showLogoutNotification(int userId) {
559860397f6521249f1e2733e65ccebe0c0e781b82aXiaohui Chen            PendingIntent logoutPI = PendingIntent.getBroadcastAsUser(mContext,
560860397f6521249f1e2733e65ccebe0c0e781b82aXiaohui Chen                    0, new Intent(ACTION_LOGOUT_USER), 0, UserHandle.SYSTEM);
561e25c18da7d2cc3e02620dadfcb976521821bc9d8Adrian Roos            Notification.Builder builder = new Notification.Builder(mContext)
562860397f6521249f1e2733e65ccebe0c0e781b82aXiaohui Chen                    .setVisibility(Notification.VISIBILITY_SECRET)
563860397f6521249f1e2733e65ccebe0c0e781b82aXiaohui Chen                    .setPriority(Notification.PRIORITY_MIN)
564860397f6521249f1e2733e65ccebe0c0e781b82aXiaohui Chen                    .setSmallIcon(R.drawable.ic_person)
565860397f6521249f1e2733e65ccebe0c0e781b82aXiaohui Chen                    .setContentTitle(mContext.getString(R.string.user_logout_notification_title))
566860397f6521249f1e2733e65ccebe0c0e781b82aXiaohui Chen                    .setContentText(mContext.getString(R.string.user_logout_notification_text))
56752408f4fb5dab950847aa12e3bea44399ccd0d6eFyodor Kupolov                    .setContentIntent(logoutPI)
568ce161861c3507c91c25b2491abac1e7611d14c5cFyodor Kupolov                    .setOngoing(true)
569860397f6521249f1e2733e65ccebe0c0e781b82aXiaohui Chen                    .setShowWhen(false)
570860397f6521249f1e2733e65ccebe0c0e781b82aXiaohui Chen                    .addAction(R.drawable.ic_delete,
571860397f6521249f1e2733e65ccebe0c0e781b82aXiaohui Chen                            mContext.getString(R.string.user_logout_notification_action),
572e25c18da7d2cc3e02620dadfcb976521821bc9d8Adrian Roos                            logoutPI);
573e25c18da7d2cc3e02620dadfcb976521821bc9d8Adrian Roos            SystemUI.overrideNotificationAppName(mContext, builder);
5745e6c0ffd3e91cf0c5872de3e2d99e225ad1468f4Chris Wren            NotificationManager.from(mContext).notifyAsUser(TAG_LOGOUT_USER,
5755e6c0ffd3e91cf0c5872de3e2d99e225ad1468f4Chris Wren                    SystemMessage.NOTE_LOGOUT_USER, builder.build(), new UserHandle(userId));
576860397f6521249f1e2733e65ccebe0c0e781b82aXiaohui Chen        }
57700a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos    };
57800a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos
579523c404612c634f6901205fee4f4cae594f62982Fyodor Kupolov    private void showGuestNotification(int guestUserId) {
580523c404612c634f6901205fee4f4cae594f62982Fyodor Kupolov        boolean canSwitchUsers = mUserManager.canSwitchUsers();
581523c404612c634f6901205fee4f4cae594f62982Fyodor Kupolov        // Disable 'Remove guest' action if cannot switch users right now
582523c404612c634f6901205fee4f4cae594f62982Fyodor Kupolov        PendingIntent removeGuestPI = canSwitchUsers ? PendingIntent.getBroadcastAsUser(mContext,
583523c404612c634f6901205fee4f4cae594f62982Fyodor Kupolov                0, new Intent(ACTION_REMOVE_GUEST), 0, UserHandle.SYSTEM) : null;
584523c404612c634f6901205fee4f4cae594f62982Fyodor Kupolov
585e25c18da7d2cc3e02620dadfcb976521821bc9d8Adrian Roos        Notification.Builder builder = new Notification.Builder(mContext)
586523c404612c634f6901205fee4f4cae594f62982Fyodor Kupolov                .setVisibility(Notification.VISIBILITY_SECRET)
587523c404612c634f6901205fee4f4cae594f62982Fyodor Kupolov                .setPriority(Notification.PRIORITY_MIN)
588523c404612c634f6901205fee4f4cae594f62982Fyodor Kupolov                .setSmallIcon(R.drawable.ic_person)
589523c404612c634f6901205fee4f4cae594f62982Fyodor Kupolov                .setContentTitle(mContext.getString(R.string.guest_notification_title))
590523c404612c634f6901205fee4f4cae594f62982Fyodor Kupolov                .setContentText(mContext.getString(R.string.guest_notification_text))
591523c404612c634f6901205fee4f4cae594f62982Fyodor Kupolov                .setContentIntent(removeGuestPI)
592523c404612c634f6901205fee4f4cae594f62982Fyodor Kupolov                .setShowWhen(false)
593523c404612c634f6901205fee4f4cae594f62982Fyodor Kupolov                .addAction(R.drawable.ic_delete,
594523c404612c634f6901205fee4f4cae594f62982Fyodor Kupolov                        mContext.getString(R.string.guest_notification_remove_action),
595e25c18da7d2cc3e02620dadfcb976521821bc9d8Adrian Roos                        removeGuestPI);
596e25c18da7d2cc3e02620dadfcb976521821bc9d8Adrian Roos        SystemUI.overrideNotificationAppName(mContext, builder);
5975e6c0ffd3e91cf0c5872de3e2d99e225ad1468f4Chris Wren        NotificationManager.from(mContext).notifyAsUser(TAG_REMOVE_GUEST,
5985e6c0ffd3e91cf0c5872de3e2d99e225ad1468f4Chris Wren                SystemMessage.NOTE_REMOVE_GUEST, builder.build(), new UserHandle(guestUserId));
599523c404612c634f6901205fee4f4cae594f62982Fyodor Kupolov    }
600523c404612c634f6901205fee4f4cae594f62982Fyodor Kupolov
60188b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos    private final Runnable mUnpauseRefreshUsers = new Runnable() {
60288b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos        @Override
60388b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos        public void run() {
60488b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos            mHandler.removeCallbacks(this);
60588b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos            mPauseRefreshUsers = false;
60688b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos            refreshUsers(UserHandle.USER_NULL);
60788b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos        }
60888b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos    };
60988b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos
610ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos    private final ContentObserver mSettingsObserver = new ContentObserver(new Handler()) {
6112daf62ce400fe58c7f0495dda432ba568a75f579Jason Monk        public void onChange(boolean selfChange) {
6122daf62ce400fe58c7f0495dda432ba568a75f579Jason Monk            mSimpleUserSwitcher = Settings.Global.getInt(mContext.getContentResolver(),
6132daf62ce400fe58c7f0495dda432ba568a75f579Jason Monk                    SIMPLE_USER_SWITCHER_GLOBAL_SETTING, 0) != 0;
614ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos            mAddUsersWhenLocked = Settings.Global.getInt(mContext.getContentResolver(),
615ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos                    Settings.Global.ADD_USERS_WHEN_LOCKED, 0) != 0;
6162daf62ce400fe58c7f0495dda432ba568a75f579Jason Monk            refreshUsers(UserHandle.USER_NULL);
6172daf62ce400fe58c7f0495dda432ba568a75f579Jason Monk        };
6182daf62ce400fe58c7f0495dda432ba568a75f579Jason Monk    };
6192daf62ce400fe58c7f0495dda432ba568a75f579Jason Monk
62000a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
62100a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        pw.println("UserSwitcherController state:");
62270441467f4dc232cd8e6142f0afc117787dc979bAdrian Roos        pw.println("  mLastNonGuestUser=" + mLastNonGuestUser);
62300a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        pw.print("  mUsers.size="); pw.println(mUsers.size());
62400a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        for (int i = 0; i < mUsers.size(); i++) {
62500a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos            final UserRecord u = mUsers.get(i);
62600a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos            pw.print("    "); pw.println(u.toString());
62700a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        }
62800a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos    }
62900a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos
63057cf5702e0634b8cb25daa8f2f73292428ec4e08Adrian Roos    public String getCurrentUserName(Context context) {
63157cf5702e0634b8cb25daa8f2f73292428ec4e08Adrian Roos        if (mUsers.isEmpty()) return null;
63257cf5702e0634b8cb25daa8f2f73292428ec4e08Adrian Roos        UserRecord item = mUsers.get(0);
63357cf5702e0634b8cb25daa8f2f73292428ec4e08Adrian Roos        if (item == null || item.info == null) return null;
63457cf5702e0634b8cb25daa8f2f73292428ec4e08Adrian Roos        if (item.isGuest) return context.getString(R.string.guest_nickname);
63557cf5702e0634b8cb25daa8f2f73292428ec4e08Adrian Roos        return item.info.name;
63657cf5702e0634b8cb25daa8f2f73292428ec4e08Adrian Roos    }
63757cf5702e0634b8cb25daa8f2f73292428ec4e08Adrian Roos
638d390b893eafae634844d7b8b84efaa7baa199119Adrian Roos    public void onDensityOrFontScaleChanged() {
639d390b893eafae634844d7b8b84efaa7baa199119Adrian Roos        refreshUsers(UserHandle.USER_ALL);
640d390b893eafae634844d7b8b84efaa7baa199119Adrian Roos    }
641d390b893eafae634844d7b8b84efaa7baa199119Adrian Roos
6428852905b0b3837e326127c6dfef6f699124ce715Jason Monk    @VisibleForTesting
6438852905b0b3837e326127c6dfef6f699124ce715Jason Monk    public void addAdapter(WeakReference<BaseUserAdapter> adapter) {
6448852905b0b3837e326127c6dfef6f699124ce715Jason Monk        mAdapters.add(adapter);
6458852905b0b3837e326127c6dfef6f699124ce715Jason Monk    }
6468852905b0b3837e326127c6dfef6f699124ce715Jason Monk
6478852905b0b3837e326127c6dfef6f699124ce715Jason Monk    @VisibleForTesting
6488852905b0b3837e326127c6dfef6f699124ce715Jason Monk    public KeyguardMonitor getKeyguardMonitor() {
6498852905b0b3837e326127c6dfef6f699124ce715Jason Monk        return mKeyguardMonitor;
6508852905b0b3837e326127c6dfef6f699124ce715Jason Monk    }
6518852905b0b3837e326127c6dfef6f699124ce715Jason Monk
6528852905b0b3837e326127c6dfef6f699124ce715Jason Monk    @VisibleForTesting
6538852905b0b3837e326127c6dfef6f699124ce715Jason Monk    public ArrayList<UserRecord> getUsers() {
6548852905b0b3837e326127c6dfef6f699124ce715Jason Monk        return mUsers;
6558852905b0b3837e326127c6dfef6f699124ce715Jason Monk    }
6568852905b0b3837e326127c6dfef6f699124ce715Jason Monk
65700a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos    public static abstract class BaseUserAdapter extends BaseAdapter {
65800a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos
65900a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        final UserSwitcherController mController;
66000a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos
66100a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        protected BaseUserAdapter(UserSwitcherController controller) {
66200a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos            mController = controller;
6638852905b0b3837e326127c6dfef6f699124ce715Jason Monk            controller.addAdapter(new WeakReference<>(this));
66400a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        }
66500a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos
66600a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        @Override
66700a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        public int getCount() {
6688852905b0b3837e326127c6dfef6f699124ce715Jason Monk            boolean secureKeyguardShowing = mController.getKeyguardMonitor().isShowing()
6698852905b0b3837e326127c6dfef6f699124ce715Jason Monk                    && mController.getKeyguardMonitor().isSecure()
6708852905b0b3837e326127c6dfef6f699124ce715Jason Monk                    && !mController.getKeyguardMonitor().canSkipBouncer();
671ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos            if (!secureKeyguardShowing) {
6728852905b0b3837e326127c6dfef6f699124ce715Jason Monk                return mController.getUsers().size();
673ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos            }
674ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos            // The lock screen is secure and showing. Filter out restricted records.
6758852905b0b3837e326127c6dfef6f699124ce715Jason Monk            final int N = mController.getUsers().size();
676ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos            int count = 0;
677ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos            for (int i = 0; i < N; i++) {
6788852905b0b3837e326127c6dfef6f699124ce715Jason Monk                if (mController.getUsers().get(i).isRestricted) {
679ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos                    break;
680ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos                } else {
681ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos                    count++;
682ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos                }
683ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos            }
684ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos            return count;
68500a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        }
68600a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos
68700a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        @Override
68800a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        public UserRecord getItem(int position) {
6898852905b0b3837e326127c6dfef6f699124ce715Jason Monk            return mController.getUsers().get(position);
69000a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        }
69100a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos
69200a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        @Override
69300a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        public long getItemId(int position) {
694e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos            return position;
69500a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        }
69600a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos
69700a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        public void switchTo(UserRecord record) {
69800a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos            mController.switchTo(record);
69900a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        }
700e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos
701e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos        public String getName(Context context, UserRecord item) {
702e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos            if (item.isGuest) {
703e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos                if (item.isCurrent) {
704e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos                    return context.getString(R.string.guest_exit_guest);
705e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos                } else {
706e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos                    return context.getString(
707e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos                            item.info == null ? R.string.guest_new_guest : R.string.guest_nickname);
708e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos                }
709ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos            } else if (item.isAddUser) {
710ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos                return context.getString(R.string.user_add_user);
711e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos            } else {
712e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos                return item.info.name;
713e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos            }
714e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos        }
715723632ea1ae30b33e9c2055194a4464f00c48c61Adrian Roos
716ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos        public Drawable getDrawable(Context context, UserRecord item) {
717ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos            if (item.isAddUser) {
718ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos                return context.getDrawable(R.drawable.ic_add_circle_qs);
719ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos            }
720aa7f51fe8c6e54485f0b5037c17777b4695d19e0Evan Rosky            return UserIcons.getDefaultUserIcon(item.resolveId(), /* light= */ true);
721ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos        }
722844c92b444dca7f5ef4d0943fb14e2cbeee49701Adrian Roos
723844c92b444dca7f5ef4d0943fb14e2cbeee49701Adrian Roos        public void refresh() {
724844c92b444dca7f5ef4d0943fb14e2cbeee49701Adrian Roos            mController.refreshUsers(UserHandle.USER_NULL);
725844c92b444dca7f5ef4d0943fb14e2cbeee49701Adrian Roos        }
72600a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos    }
72700a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos
728a8fbbb30eae03b9ed7a3e6ea78da13480a53b73dSudheer Shanka    private void checkIfAddUserDisallowedByAdminOnly(UserRecord record) {
729ad143c09dfbae2f4bb26be8b2a9425edf0562b46Sudheer Shanka        EnforcedAdmin admin = RestrictedLockUtils.checkIfRestrictionEnforced(mContext,
730ad143c09dfbae2f4bb26be8b2a9425edf0562b46Sudheer Shanka                UserManager.DISALLOW_ADD_USER, ActivityManager.getCurrentUser());
731ad143c09dfbae2f4bb26be8b2a9425edf0562b46Sudheer Shanka        if (admin != null && !RestrictedLockUtils.hasBaseUserRestriction(mContext,
732ad143c09dfbae2f4bb26be8b2a9425edf0562b46Sudheer Shanka                UserManager.DISALLOW_ADD_USER, ActivityManager.getCurrentUser())) {
7331c7cda8bbfb848961536a4adbf2c81c5ffddae16Sudheer Shanka            record.isDisabledByAdmin = true;
734ad143c09dfbae2f4bb26be8b2a9425edf0562b46Sudheer Shanka            record.enforcedAdmin = admin;
7351c7cda8bbfb848961536a4adbf2c81c5ffddae16Sudheer Shanka        } else {
7361c7cda8bbfb848961536a4adbf2c81c5ffddae16Sudheer Shanka            record.isDisabledByAdmin = false;
7371c7cda8bbfb848961536a4adbf2c81c5ffddae16Sudheer Shanka            record.enforcedAdmin = null;
7381c7cda8bbfb848961536a4adbf2c81c5ffddae16Sudheer Shanka        }
7391c7cda8bbfb848961536a4adbf2c81c5ffddae16Sudheer Shanka    }
7401c7cda8bbfb848961536a4adbf2c81c5ffddae16Sudheer Shanka
7411c7cda8bbfb848961536a4adbf2c81c5ffddae16Sudheer Shanka    public void startActivity(Intent intent) {
7421c7cda8bbfb848961536a4adbf2c81c5ffddae16Sudheer Shanka        mActivityStarter.startActivity(intent, true);
7431c7cda8bbfb848961536a4adbf2c81c5ffddae16Sudheer Shanka    }
7441c7cda8bbfb848961536a4adbf2c81c5ffddae16Sudheer Shanka
74500a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos    public static final class UserRecord {
74600a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        public final UserInfo info;
74700a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        public final Bitmap picture;
74800a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        public final boolean isGuest;
74900a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        public final boolean isCurrent;
750ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos        public final boolean isAddUser;
751ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos        /** If true, the record is only visible to the owner and only when unlocked. */
752ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos        public final boolean isRestricted;
7531c7cda8bbfb848961536a4adbf2c81c5ffddae16Sudheer Shanka        public boolean isDisabledByAdmin;
7541c7cda8bbfb848961536a4adbf2c81c5ffddae16Sudheer Shanka        public EnforcedAdmin enforcedAdmin;
75507140f7ffd56bf9d4946eba4e48b21a748125659Fyodor Kupolov        public boolean isSwitchToEnabled;
75600a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos
757ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos        public UserRecord(UserInfo info, Bitmap picture, boolean isGuest, boolean isCurrent,
75807140f7ffd56bf9d4946eba4e48b21a748125659Fyodor Kupolov                boolean isAddUser, boolean isRestricted, boolean isSwitchToEnabled) {
75900a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos            this.info = info;
76000a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos            this.picture = picture;
76100a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos            this.isGuest = isGuest;
76200a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos            this.isCurrent = isCurrent;
763ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos            this.isAddUser = isAddUser;
764ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos            this.isRestricted = isRestricted;
76507140f7ffd56bf9d4946eba4e48b21a748125659Fyodor Kupolov            this.isSwitchToEnabled = isSwitchToEnabled;
76600a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        }
76700a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos
76800a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        public UserRecord copyWithIsCurrent(boolean _isCurrent) {
76907140f7ffd56bf9d4946eba4e48b21a748125659Fyodor Kupolov            return new UserRecord(info, picture, isGuest, _isCurrent, isAddUser, isRestricted,
77007140f7ffd56bf9d4946eba4e48b21a748125659Fyodor Kupolov                    isSwitchToEnabled);
77100a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        }
77200a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos
773aa7f51fe8c6e54485f0b5037c17777b4695d19e0Evan Rosky        public int resolveId() {
774aa7f51fe8c6e54485f0b5037c17777b4695d19e0Evan Rosky            if (isGuest || info == null) {
775aa7f51fe8c6e54485f0b5037c17777b4695d19e0Evan Rosky                return UserHandle.USER_NULL;
776aa7f51fe8c6e54485f0b5037c17777b4695d19e0Evan Rosky            }
777aa7f51fe8c6e54485f0b5037c17777b4695d19e0Evan Rosky            return info.id;
778aa7f51fe8c6e54485f0b5037c17777b4695d19e0Evan Rosky        }
779aa7f51fe8c6e54485f0b5037c17777b4695d19e0Evan Rosky
78000a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        public String toString() {
78100a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos            StringBuilder sb = new StringBuilder();
78200a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos            sb.append("UserRecord(");
78300a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos            if (info != null) {
78407140f7ffd56bf9d4946eba4e48b21a748125659Fyodor Kupolov                sb.append("name=\"").append(info.name).append("\" id=").append(info.id);
78500a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos            } else {
786ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos                if (isGuest) {
787ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos                    sb.append("<add guest placeholder>");
788ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos                } else if (isAddUser) {
789ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos                    sb.append("<add user placeholder>");
790ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos                }
79100a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos            }
792ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos            if (isGuest) sb.append(" <isGuest>");
793ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos            if (isAddUser) sb.append(" <isAddUser>");
794ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos            if (isCurrent) sb.append(" <isCurrent>");
795ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos            if (picture != null) sb.append(" <hasPicture>");
796ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos            if (isRestricted) sb.append(" <isRestricted>");
7971c7cda8bbfb848961536a4adbf2c81c5ffddae16Sudheer Shanka            if (isDisabledByAdmin) {
7981c7cda8bbfb848961536a4adbf2c81c5ffddae16Sudheer Shanka                sb.append(" <isDisabledByAdmin>");
79907140f7ffd56bf9d4946eba4e48b21a748125659Fyodor Kupolov                sb.append(" enforcedAdmin=").append(enforcedAdmin);
80007140f7ffd56bf9d4946eba4e48b21a748125659Fyodor Kupolov            }
80107140f7ffd56bf9d4946eba4e48b21a748125659Fyodor Kupolov            if (isSwitchToEnabled) {
80207140f7ffd56bf9d4946eba4e48b21a748125659Fyodor Kupolov                sb.append(" <isSwitchToEnabled>");
8031c7cda8bbfb848961536a4adbf2c81c5ffddae16Sudheer Shanka            }
80400a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos            sb.append(')');
80500a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos            return sb.toString();
80600a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        }
80700a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos    }
80800a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos
80946767b77c004a3541c614f8e21d6a871dd148e54Jason Monk    public final DetailAdapter userDetailAdapter = new DetailAdapter() {
81076c67aa361f65dfb2f5e03d06cc1ccebce9cecd9Jason Monk        private final Intent USER_SETTINGS_INTENT = new Intent(Settings.ACTION_USER_SETTINGS);
81100a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos
81200a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        @Override
813c06fbb12984a3d3e4c80ab9f819841acae5b0133Jason Monk        public CharSequence getTitle() {
814c06fbb12984a3d3e4c80ab9f819841acae5b0133Jason Monk            return mContext.getString(R.string.quick_settings_user_title);
81500a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        }
81600a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos
81700a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        @Override
81800a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        public View createDetailView(Context context, View convertView, ViewGroup parent) {
8191940892d891c1d2538f51608b6618af646ab7481Adrian Roos            UserDetailView v;
82000a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos            if (!(convertView instanceof UserDetailView)) {
8211940892d891c1d2538f51608b6618af646ab7481Adrian Roos                v = UserDetailView.inflate(context, parent, false);
82200a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos                v.createAndSetAdapter(UserSwitcherController.this);
8231940892d891c1d2538f51608b6618af646ab7481Adrian Roos            } else {
8241940892d891c1d2538f51608b6618af646ab7481Adrian Roos                v = (UserDetailView) convertView;
82500a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos            }
826844c92b444dca7f5ef4d0943fb14e2cbeee49701Adrian Roos            v.refreshAdapter();
82700a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos            return v;
82800a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        }
82900a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos
83000a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        @Override
83100a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        public Intent getSettingsIntent() {
83200a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos            return USER_SETTINGS_INTENT;
83300a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        }
83400a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos
83500a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        @Override
83600a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        public Boolean getToggleState() {
83700a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos            return null;
83800a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        }
83900a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos
84000a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        @Override
84100a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        public void setToggleState(boolean state) {
84200a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        }
843457a21cdeac04565a0c40ad8c43a928c1182ddd1Chris Wren
844457a21cdeac04565a0c40ad8c43a928c1182ddd1Chris Wren        @Override
845457a21cdeac04565a0c40ad8c43a928c1182ddd1Chris Wren        public int getMetricsCategory() {
846f6e9228b8a97603d3ceb8f0d61e8d87cf19bd21fChris Wren            return MetricsEvent.QS_USERDETAIL;
847457a21cdeac04565a0c40ad8c43a928c1182ddd1Chris Wren        }
84800a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos    };
8495005244f10442e75c1f48973fdddce5facf3f360Adrian Roos
850ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos    private final KeyguardMonitor.Callback mCallback = new KeyguardMonitor.Callback() {
851ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos        @Override
852ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos        public void onKeyguardChanged() {
853ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos            notifyAdapters();
854ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos        }
855ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos    };
856ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos
8575005244f10442e75c1f48973fdddce5facf3f360Adrian Roos    private final class ExitGuestDialog extends SystemUIDialog implements
8585005244f10442e75c1f48973fdddce5facf3f360Adrian Roos            DialogInterface.OnClickListener {
8595005244f10442e75c1f48973fdddce5facf3f360Adrian Roos
8605005244f10442e75c1f48973fdddce5facf3f360Adrian Roos        private final int mGuestId;
86113a58a91d362e74933b3064a65be4bf4449cfdc4Evan Rosky        private final int mTargetId;
8625005244f10442e75c1f48973fdddce5facf3f360Adrian Roos
86313a58a91d362e74933b3064a65be4bf4449cfdc4Evan Rosky        public ExitGuestDialog(Context context, int guestId, int targetId) {
8645005244f10442e75c1f48973fdddce5facf3f360Adrian Roos            super(context);
8655005244f10442e75c1f48973fdddce5facf3f360Adrian Roos            setTitle(R.string.guest_exit_guest_dialog_title);
8665005244f10442e75c1f48973fdddce5facf3f360Adrian Roos            setMessage(context.getString(R.string.guest_exit_guest_dialog_message));
8675005244f10442e75c1f48973fdddce5facf3f360Adrian Roos            setButton(DialogInterface.BUTTON_NEGATIVE,
868e5b274ac612400a7bc9f258d4ef3c366cfa1bc11Amith Yamasani                    context.getString(android.R.string.cancel), this);
8695005244f10442e75c1f48973fdddce5facf3f360Adrian Roos            setButton(DialogInterface.BUTTON_POSITIVE,
870e5b274ac612400a7bc9f258d4ef3c366cfa1bc11Amith Yamasani                    context.getString(R.string.guest_exit_guest_dialog_remove), this);
8715005244f10442e75c1f48973fdddce5facf3f360Adrian Roos            setCanceledOnTouchOutside(false);
8725005244f10442e75c1f48973fdddce5facf3f360Adrian Roos            mGuestId = guestId;
87313a58a91d362e74933b3064a65be4bf4449cfdc4Evan Rosky            mTargetId = targetId;
8745005244f10442e75c1f48973fdddce5facf3f360Adrian Roos        }
8755005244f10442e75c1f48973fdddce5facf3f360Adrian Roos
8765005244f10442e75c1f48973fdddce5facf3f360Adrian Roos        @Override
8775005244f10442e75c1f48973fdddce5facf3f360Adrian Roos        public void onClick(DialogInterface dialog, int which) {
8785005244f10442e75c1f48973fdddce5facf3f360Adrian Roos            if (which == BUTTON_NEGATIVE) {
8795005244f10442e75c1f48973fdddce5facf3f360Adrian Roos                cancel();
8805005244f10442e75c1f48973fdddce5facf3f360Adrian Roos            } else {
8815005244f10442e75c1f48973fdddce5facf3f360Adrian Roos                dismiss();
88213a58a91d362e74933b3064a65be4bf4449cfdc4Evan Rosky                exitGuest(mGuestId, mTargetId);
8835005244f10442e75c1f48973fdddce5facf3f360Adrian Roos            }
8845005244f10442e75c1f48973fdddce5facf3f360Adrian Roos        }
8855005244f10442e75c1f48973fdddce5facf3f360Adrian Roos    }
8860c6763a19f32f73f8a940aaee7abecb2a04d1889Adrian Roos
8870c6763a19f32f73f8a940aaee7abecb2a04d1889Adrian Roos    private final class AddUserDialog extends SystemUIDialog implements
8880c6763a19f32f73f8a940aaee7abecb2a04d1889Adrian Roos            DialogInterface.OnClickListener {
8890c6763a19f32f73f8a940aaee7abecb2a04d1889Adrian Roos
8900c6763a19f32f73f8a940aaee7abecb2a04d1889Adrian Roos        public AddUserDialog(Context context) {
8910c6763a19f32f73f8a940aaee7abecb2a04d1889Adrian Roos            super(context);
8920c6763a19f32f73f8a940aaee7abecb2a04d1889Adrian Roos            setTitle(R.string.user_add_user_title);
8930c6763a19f32f73f8a940aaee7abecb2a04d1889Adrian Roos            setMessage(context.getString(R.string.user_add_user_message_short));
8940c6763a19f32f73f8a940aaee7abecb2a04d1889Adrian Roos            setButton(DialogInterface.BUTTON_NEGATIVE,
8950c6763a19f32f73f8a940aaee7abecb2a04d1889Adrian Roos                    context.getString(android.R.string.cancel), this);
8960c6763a19f32f73f8a940aaee7abecb2a04d1889Adrian Roos            setButton(DialogInterface.BUTTON_POSITIVE,
8970c6763a19f32f73f8a940aaee7abecb2a04d1889Adrian Roos                    context.getString(android.R.string.ok), this);
8980c6763a19f32f73f8a940aaee7abecb2a04d1889Adrian Roos        }
8990c6763a19f32f73f8a940aaee7abecb2a04d1889Adrian Roos
9000c6763a19f32f73f8a940aaee7abecb2a04d1889Adrian Roos        @Override
9010c6763a19f32f73f8a940aaee7abecb2a04d1889Adrian Roos        public void onClick(DialogInterface dialog, int which) {
9020c6763a19f32f73f8a940aaee7abecb2a04d1889Adrian Roos            if (which == BUTTON_NEGATIVE) {
9030c6763a19f32f73f8a940aaee7abecb2a04d1889Adrian Roos                cancel();
9040c6763a19f32f73f8a940aaee7abecb2a04d1889Adrian Roos            } else {
9050c6763a19f32f73f8a940aaee7abecb2a04d1889Adrian Roos                dismiss();
906ccbeb61ac21527839deb115199cbe98fa2b73c05Guang Zhu                if (ActivityManager.isUserAMonkey()) {
907ccbeb61ac21527839deb115199cbe98fa2b73c05Guang Zhu                    return;
908ccbeb61ac21527839deb115199cbe98fa2b73c05Guang Zhu                }
909cfe64c8afa9f30d8874c72440c3992e79fdb60c9Xiaohui Chen                UserInfo user = mUserManager.createUser(
910f99727cb878f9709f6c0263c0283257decbaebadAdrian Roos                        mContext.getString(R.string.user_new_user_name), 0 /* flags */);
911f99727cb878f9709f6c0263c0283257decbaebadAdrian Roos                if (user == null) {
912f99727cb878f9709f6c0263c0283257decbaebadAdrian Roos                    // Couldn't create user, most likely because there are too many, but we haven't
913f99727cb878f9709f6c0263c0283257decbaebadAdrian Roos                    // been able to reload the list yet.
914f99727cb878f9709f6c0263c0283257decbaebadAdrian Roos                    return;
915f99727cb878f9709f6c0263c0283257decbaebadAdrian Roos                }
916f99727cb878f9709f6c0263c0283257decbaebadAdrian Roos                int id = user.id;
91764d4dca63f65e4c7d4a829c85ff6670bdd34e2ebAlexandra Gherghina                Bitmap icon = UserIcons.convertToBitmap(UserIcons.getDefaultUserIcon(
91864d4dca63f65e4c7d4a829c85ff6670bdd34e2ebAlexandra Gherghina                        id, /* light= */ false));
91964d4dca63f65e4c7d4a829c85ff6670bdd34e2ebAlexandra Gherghina                mUserManager.setUserIcon(id, icon);
9200c6763a19f32f73f8a940aaee7abecb2a04d1889Adrian Roos                switchToUserId(id);
9210c6763a19f32f73f8a940aaee7abecb2a04d1889Adrian Roos            }
9220c6763a19f32f73f8a940aaee7abecb2a04d1889Adrian Roos        }
9230c6763a19f32f73f8a940aaee7abecb2a04d1889Adrian Roos    }
92400a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos}
925