UserSwitcherController.java revision c06fbb12984a3d3e4c80ab9f819841acae5b0133
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
1900a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roosimport android.app.ActivityManager;
2000a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roosimport android.app.ActivityManagerNative;
215005244f10442e75c1f48973fdddce5facf3f360Adrian Roosimport android.app.Dialog;
22f4d6ad26636760163083ae84c40d5b19cb6650f6Fyodor Kupolovimport android.app.Notification;
23f4d6ad26636760163083ae84c40d5b19cb6650f6Fyodor Kupolovimport android.app.NotificationManager;
24f4d6ad26636760163083ae84c40d5b19cb6650f6Fyodor Kupolovimport android.app.PendingIntent;
2500a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roosimport android.content.BroadcastReceiver;
2600a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roosimport android.content.Context;
275005244f10442e75c1f48973fdddce5facf3f360Adrian Roosimport android.content.DialogInterface;
2800a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roosimport android.content.Intent;
2900a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roosimport android.content.IntentFilter;
3000a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roosimport android.content.pm.UserInfo;
312daf62ce400fe58c7f0495dda432ba568a75f579Jason Monkimport android.database.ContentObserver;
3200a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roosimport android.graphics.Bitmap;
33ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roosimport android.graphics.drawable.Drawable;
3400a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roosimport android.os.AsyncTask;
35cc3a74f6ef13ca9a783845e7a04ca6561035c98bXiyuan Xiaimport android.os.Build;
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;
4100a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roosimport android.util.Log;
42e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roosimport android.util.SparseArray;
4388b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roosimport android.util.SparseBooleanArray;
4488b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roosimport android.util.SparseIntArray;
4500a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roosimport android.view.View;
4600a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roosimport android.view.ViewGroup;
4700a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roosimport android.widget.BaseAdapter;
4800a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos
49457a21cdeac04565a0c40ad8c43a928c1182ddd1Chris Wrenimport com.android.internal.logging.MetricsLogger;
5064d4dca63f65e4c7d4a829c85ff6670bdd34e2ebAlexandra Gherghinaimport com.android.internal.util.UserIcons;
5164d4dca63f65e4c7d4a829c85ff6670bdd34e2ebAlexandra Gherghinaimport com.android.systemui.BitmapHelper;
5264d4dca63f65e4c7d4a829c85ff6670bdd34e2ebAlexandra Gherghinaimport com.android.systemui.GuestResumeSessionReceiver;
5364d4dca63f65e4c7d4a829c85ff6670bdd34e2ebAlexandra Gherghinaimport com.android.systemui.R;
5464d4dca63f65e4c7d4a829c85ff6670bdd34e2ebAlexandra Gherghinaimport com.android.systemui.qs.QSTile;
5564d4dca63f65e4c7d4a829c85ff6670bdd34e2ebAlexandra Gherghinaimport com.android.systemui.qs.tiles.UserDetailView;
5664d4dca63f65e4c7d4a829c85ff6670bdd34e2ebAlexandra Gherghinaimport com.android.systemui.statusbar.phone.SystemUIDialog;
5764d4dca63f65e4c7d4a829c85ff6670bdd34e2ebAlexandra Gherghina
5800a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roosimport java.io.FileDescriptor;
5900a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roosimport java.io.PrintWriter;
6000a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roosimport java.lang.ref.WeakReference;
6100a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roosimport java.util.ArrayList;
6200a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roosimport java.util.List;
6300a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos
6400a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos/**
6500a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos * Keeps a list of all users on the device for user switching.
6600a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos */
6700a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roospublic class UserSwitcherController {
6800a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos
6900a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos    private static final String TAG = "UserSwitcherController";
705005244f10442e75c1f48973fdddce5facf3f360Adrian Roos    private static final boolean DEBUG = false;
712daf62ce400fe58c7f0495dda432ba568a75f579Jason Monk    private static final String SIMPLE_USER_SWITCHER_GLOBAL_SETTING =
722daf62ce400fe58c7f0495dda432ba568a75f579Jason Monk            "lockscreenSimpleUserSwitcher";
73f4d6ad26636760163083ae84c40d5b19cb6650f6Fyodor Kupolov    private static final String ACTION_REMOVE_GUEST = "com.android.systemui.REMOVE_GUEST";
74860397f6521249f1e2733e65ccebe0c0e781b82aXiaohui Chen    private static final String ACTION_LOGOUT_USER = "com.android.systemui.LOGOUT_USER";
7588b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos    private static final int PAUSE_REFRESH_USERS_TIMEOUT_MS = 3000;
7600a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos
77d81f8270bec71ec9a569c8308c42cacd7aba0d23Amith Yamasani    private static final int ID_REMOVE_GUEST = 1010;
78860397f6521249f1e2733e65ccebe0c0e781b82aXiaohui Chen    private static final int ID_LOGOUT_USER = 1011;
79d81f8270bec71ec9a569c8308c42cacd7aba0d23Amith Yamasani    private static final String TAG_REMOVE_GUEST = "remove_guest";
80860397f6521249f1e2733e65ccebe0c0e781b82aXiaohui Chen    private static final String TAG_LOGOUT_USER = "logout_user";
81860397f6521249f1e2733e65ccebe0c0e781b82aXiaohui Chen
82d81f8270bec71ec9a569c8308c42cacd7aba0d23Amith Yamasani    private static final String PERMISSION_SELF = "com.android.systemui.permission.SELF";
83d81f8270bec71ec9a569c8308c42cacd7aba0d23Amith Yamasani
8400a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos    private final Context mContext;
8500a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos    private final UserManager mUserManager;
8600a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos    private final ArrayList<WeakReference<BaseUserAdapter>> mAdapters = new ArrayList<>();
875005244f10442e75c1f48973fdddce5facf3f360Adrian Roos    private final GuestResumeSessionReceiver mGuestResumeSessionReceiver
885005244f10442e75c1f48973fdddce5facf3f360Adrian Roos            = new GuestResumeSessionReceiver();
89ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos    private final KeyguardMonitor mKeyguardMonitor;
9088b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos    private final Handler mHandler;
9100a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos
9200a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos    private ArrayList<UserRecord> mUsers = new ArrayList<>();
935005244f10442e75c1f48973fdddce5facf3f360Adrian Roos    private Dialog mExitGuestDialog;
940c6763a19f32f73f8a940aaee7abecb2a04d1889Adrian Roos    private Dialog mAddUserDialog;
957cb69df507f5f7956c52a2868a0d6e89aec6dde2Xiaohui Chen    private int mLastNonGuestUser = UserHandle.USER_SYSTEM;
96ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos    private boolean mSimpleUserSwitcher;
97ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos    private boolean mAddUsersWhenLocked;
9888b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos    private boolean mPauseRefreshUsers;
9988b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos    private SparseBooleanArray mForcePictureLoadForUserId = new SparseBooleanArray(2);
10000a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos
10188b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos    public UserSwitcherController(Context context, KeyguardMonitor keyguardMonitor,
10288b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos            Handler handler) {
10300a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        mContext = context;
1045005244f10442e75c1f48973fdddce5facf3f360Adrian Roos        mGuestResumeSessionReceiver.register(context);
105ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos        mKeyguardMonitor = keyguardMonitor;
10688b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos        mHandler = handler;
10700a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        mUserManager = UserManager.get(context);
10800a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        IntentFilter filter = new IntentFilter();
10900a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        filter.addAction(Intent.ACTION_USER_ADDED);
11000a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        filter.addAction(Intent.ACTION_USER_REMOVED);
11100a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        filter.addAction(Intent.ACTION_USER_INFO_CHANGED);
11200a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        filter.addAction(Intent.ACTION_USER_SWITCHED);
113e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos        filter.addAction(Intent.ACTION_USER_STOPPING);
1147cb69df507f5f7956c52a2868a0d6e89aec6dde2Xiaohui Chen        mContext.registerReceiverAsUser(mReceiver, UserHandle.SYSTEM, filter,
115e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos                null /* permission */, null /* scheduler */);
1162daf62ce400fe58c7f0495dda432ba568a75f579Jason Monk
117d81f8270bec71ec9a569c8308c42cacd7aba0d23Amith Yamasani        filter = new IntentFilter();
118d81f8270bec71ec9a569c8308c42cacd7aba0d23Amith Yamasani        filter.addAction(ACTION_REMOVE_GUEST);
119860397f6521249f1e2733e65ccebe0c0e781b82aXiaohui Chen        filter.addAction(ACTION_LOGOUT_USER);
1205891a346abbde5bfe95a52633d05533406cc6a2eAmith Yamasani        mContext.registerReceiverAsUser(mReceiver, UserHandle.SYSTEM, filter,
121d81f8270bec71ec9a569c8308c42cacd7aba0d23Amith Yamasani                PERMISSION_SELF, null /* scheduler */);
122ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos
1232daf62ce400fe58c7f0495dda432ba568a75f579Jason Monk        mContext.getContentResolver().registerContentObserver(
1242daf62ce400fe58c7f0495dda432ba568a75f579Jason Monk                Settings.Global.getUriFor(SIMPLE_USER_SWITCHER_GLOBAL_SETTING), true,
125ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos                mSettingsObserver);
126ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos        mContext.getContentResolver().registerContentObserver(
127ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos                Settings.Global.getUriFor(Settings.Global.ADD_USERS_WHEN_LOCKED), true,
128ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos                mSettingsObserver);
129ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos        // Fetch initial values.
130ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos        mSettingsObserver.onChange(false);
131ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos
132ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos        keyguardMonitor.addCallback(mCallback);
1332daf62ce400fe58c7f0495dda432ba568a75f579Jason Monk
134e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos        refreshUsers(UserHandle.USER_NULL);
13500a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos    }
13600a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos
137e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos    /**
138e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos     * Refreshes users from UserManager.
139e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos     *
140e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos     * The pictures are only loaded if they have not been loaded yet.
141e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos     *
142e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos     * @param forcePictureLoadForId forces the picture of the given user to be reloaded.
143e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos     */
14495ab7849444125387dc88088bb5197ee463d8c17Amith Yamasani    @SuppressWarnings("unchecked")
145e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos    private void refreshUsers(int forcePictureLoadForId) {
14688b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos        if (DEBUG) Log.d(TAG, "refreshUsers(forcePictureLoadForId=" + forcePictureLoadForId+")");
14788b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos        if (forcePictureLoadForId != UserHandle.USER_NULL) {
14888b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos            mForcePictureLoadForUserId.put(forcePictureLoadForId, true);
14988b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos        }
15088b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos
15188b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos        if (mPauseRefreshUsers) {
15288b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos            return;
15388b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos        }
154c5db390f5b5c6c685267dd22cf3b2926f54fba35Adrian Roos
155c5db390f5b5c6c685267dd22cf3b2926f54fba35Adrian Roos        SparseArray<Bitmap> bitmaps = new SparseArray<>(mUsers.size());
156c5db390f5b5c6c685267dd22cf3b2926f54fba35Adrian Roos        final int N = mUsers.size();
157c5db390f5b5c6c685267dd22cf3b2926f54fba35Adrian Roos        for (int i = 0; i < N; i++) {
158c5db390f5b5c6c685267dd22cf3b2926f54fba35Adrian Roos            UserRecord r = mUsers.get(i);
15988b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos            if (r == null || r.picture == null ||
16088b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos                    r.info == null || mForcePictureLoadForUserId.get(r.info.id)) {
161c5db390f5b5c6c685267dd22cf3b2926f54fba35Adrian Roos                continue;
162e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos            }
163c5db390f5b5c6c685267dd22cf3b2926f54fba35Adrian Roos            bitmaps.put(r.info.id, r.picture);
164e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos        }
16588b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos        mForcePictureLoadForUserId.clear();
166e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos
167ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos        final boolean addUsersWhenLocked = mAddUsersWhenLocked;
168e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos        new AsyncTask<SparseArray<Bitmap>, Void, ArrayList<UserRecord>>() {
169e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos            @SuppressWarnings("unchecked")
17000a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos            @Override
171e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos            protected ArrayList<UserRecord> doInBackground(SparseArray<Bitmap>... params) {
172e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos                final SparseArray<Bitmap> bitmaps = params[0];
17300a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos                List<UserInfo> infos = mUserManager.getUsers(true);
17400a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos                if (infos == null) {
17500a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos                    return null;
17600a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos                }
17700a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos                ArrayList<UserRecord> records = new ArrayList<>(infos.size());
17800a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos                int currentId = ActivityManager.getCurrentUser();
1797cb69df507f5f7956c52a2868a0d6e89aec6dde2Xiaohui Chen                UserInfo currentUserInfo = null;
18000a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos                UserRecord guestRecord = null;
1814d75c079f35d85b687d8349e5e2940447d01198eDan Sandler                int avatarSize = mContext.getResources()
1824d75c079f35d85b687d8349e5e2940447d01198eDan Sandler                        .getDimensionPixelSize(R.dimen.max_avatar_size);
18300a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos
18400a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos                for (UserInfo info : infos) {
18500a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos                    boolean isCurrent = currentId == info.id;
1867cb69df507f5f7956c52a2868a0d6e89aec6dde2Xiaohui Chen                    if (isCurrent) {
1877cb69df507f5f7956c52a2868a0d6e89aec6dde2Xiaohui Chen                        currentUserInfo = info;
1887cb69df507f5f7956c52a2868a0d6e89aec6dde2Xiaohui Chen                    }
18900a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos                    if (info.isGuest()) {
19000a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos                        guestRecord = new UserRecord(info, null /* picture */,
191ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos                                true /* isGuest */, isCurrent, false /* isAddUser */,
192ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos                                false /* isRestricted */);
193cc3a74f6ef13ca9a783845e7a04ca6561035c98bXiyuan Xia                    } else if (info.isEnabled() && info.supportsSwitchToByUser()) {
194c5db390f5b5c6c685267dd22cf3b2926f54fba35Adrian Roos                        Bitmap picture = bitmaps.get(info.id);
195c5db390f5b5c6c685267dd22cf3b2926f54fba35Adrian Roos                        if (picture == null) {
196c5db390f5b5c6c685267dd22cf3b2926f54fba35Adrian Roos                            picture = mUserManager.getUserIcon(info.id);
197cba0faadbe1c8cf7c6b264b761d747f7381a2f93Adrian Roos
198c5db390f5b5c6c685267dd22cf3b2926f54fba35Adrian Roos                            if (picture != null) {
199cba0faadbe1c8cf7c6b264b761d747f7381a2f93Adrian Roos                                picture = BitmapHelper.createCircularClip(
200c5db390f5b5c6c685267dd22cf3b2926f54fba35Adrian Roos                                        picture, avatarSize, avatarSize);
201cba0faadbe1c8cf7c6b264b761d747f7381a2f93Adrian Roos                            }
2024d75c079f35d85b687d8349e5e2940447d01198eDan Sandler                        }
203bed6e3bedc8845e8f9cd59ad436d140b0875cb6bAdrian Roos                        int index = isCurrent ? 0 : records.size();
204bed6e3bedc8845e8f9cd59ad436d140b0875cb6bAdrian Roos                        records.add(index, new UserRecord(info, picture, false /* isGuest */,
205bed6e3bedc8845e8f9cd59ad436d140b0875cb6bAdrian Roos                                isCurrent, false /* isAddUser */, false /* isRestricted */));
20600a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos                    }
20700a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos                }
20800a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos
2097cb69df507f5f7956c52a2868a0d6e89aec6dde2Xiaohui Chen                boolean systemCanCreateUsers = !mUserManager.hasUserRestriction(
2107cb69df507f5f7956c52a2868a0d6e89aec6dde2Xiaohui Chen                                UserManager.DISALLOW_ADD_USER, UserHandle.SYSTEM);
2117cb69df507f5f7956c52a2868a0d6e89aec6dde2Xiaohui Chen                boolean currentUserCanCreateUsers = currentUserInfo != null
2127cb69df507f5f7956c52a2868a0d6e89aec6dde2Xiaohui Chen                        && (currentUserInfo.isAdmin()
2137cb69df507f5f7956c52a2868a0d6e89aec6dde2Xiaohui Chen                                || currentUserInfo.id == UserHandle.USER_SYSTEM)
2147cb69df507f5f7956c52a2868a0d6e89aec6dde2Xiaohui Chen                        && systemCanCreateUsers;
2157cb69df507f5f7956c52a2868a0d6e89aec6dde2Xiaohui Chen                boolean anyoneCanCreateUsers = systemCanCreateUsers && addUsersWhenLocked;
216ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos                boolean canCreateGuest = (currentUserCanCreateUsers || anyoneCanCreateUsers)
217ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos                        && guestRecord == null;
218ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos                boolean canCreateUser = (currentUserCanCreateUsers || anyoneCanCreateUsers)
21995ab7849444125387dc88088bb5197ee463d8c17Amith Yamasani                        && mUserManager.canAddMoreUsers();
220ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos                boolean createIsRestricted = !addUsersWhenLocked;
221ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos
2222daf62ce400fe58c7f0495dda432ba568a75f579Jason Monk                if (!mSimpleUserSwitcher) {
2232daf62ce400fe58c7f0495dda432ba568a75f579Jason Monk                    if (guestRecord == null) {
224ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos                        if (canCreateGuest) {
225ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos                            records.add(new UserRecord(null /* info */, null /* picture */,
226ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos                                    true /* isGuest */, false /* isCurrent */,
227ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos                                    false /* isAddUser */, createIsRestricted));
228ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos                        }
2292daf62ce400fe58c7f0495dda432ba568a75f579Jason Monk                    } else {
230bed6e3bedc8845e8f9cd59ad436d140b0875cb6bAdrian Roos                        int index = guestRecord.isCurrent ? 0 : records.size();
231bed6e3bedc8845e8f9cd59ad436d140b0875cb6bAdrian Roos                        records.add(index, guestRecord);
2322daf62ce400fe58c7f0495dda432ba568a75f579Jason Monk                    }
23300a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos                }
23400a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos
235092be7de024b8b1a050ad247a016febc795546afJason Monk                if (!mSimpleUserSwitcher && canCreateUser) {
236ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos                    records.add(new UserRecord(null /* info */, null /* picture */,
237ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos                            false /* isGuest */, false /* isCurrent */, true /* isAddUser */,
238ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos                            createIsRestricted));
239ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos                }
240ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos
24100a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos                return records;
24200a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos            }
24300a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos
24400a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos            @Override
24500a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos            protected void onPostExecute(ArrayList<UserRecord> userRecords) {
24600a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos                if (userRecords != null) {
24700a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos                    mUsers = userRecords;
24800a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos                    notifyAdapters();
24900a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos                }
25000a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos            }
251ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos        }.execute((SparseArray) bitmaps);
25200a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos    }
25300a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos
25488b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos    private void pauseRefreshUsers() {
25588b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos        if (!mPauseRefreshUsers) {
25688b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos            mHandler.postDelayed(mUnpauseRefreshUsers, PAUSE_REFRESH_USERS_TIMEOUT_MS);
25788b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos            mPauseRefreshUsers = true;
25888b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos        }
25988b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos    }
26088b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos
26100a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos    private void notifyAdapters() {
26200a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        for (int i = mAdapters.size() - 1; i >= 0; i--) {
26300a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos            BaseUserAdapter adapter = mAdapters.get(i).get();
26400a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos            if (adapter != null) {
26500a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos                adapter.notifyDataSetChanged();
26600a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos            } else {
26700a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos                mAdapters.remove(i);
26800a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos            }
26900a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        }
27000a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos    }
27100a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos
2722daf62ce400fe58c7f0495dda432ba568a75f579Jason Monk    public boolean isSimpleUserSwitcher() {
2732daf62ce400fe58c7f0495dda432ba568a75f579Jason Monk        return mSimpleUserSwitcher;
2742daf62ce400fe58c7f0495dda432ba568a75f579Jason Monk    }
2752daf62ce400fe58c7f0495dda432ba568a75f579Jason Monk
276cc3a74f6ef13ca9a783845e7a04ca6561035c98bXiyuan Xia    public boolean useFullscreenUserSwitcher() {
277cc3a74f6ef13ca9a783845e7a04ca6561035c98bXiyuan Xia        // Use adb to override:
278cc3a74f6ef13ca9a783845e7a04ca6561035c98bXiyuan Xia        // adb shell settings put system enable_fullscreen_user_switcher 0  # Turn it off.
279cc3a74f6ef13ca9a783845e7a04ca6561035c98bXiyuan Xia        // adb shell settings put system enable_fullscreen_user_switcher 1  # Turn it on.
280cc3a74f6ef13ca9a783845e7a04ca6561035c98bXiyuan Xia        // Restart SystemUI or adb reboot.
281cc3a74f6ef13ca9a783845e7a04ca6561035c98bXiyuan Xia        final int DEFAULT = -1;
282cc3a74f6ef13ca9a783845e7a04ca6561035c98bXiyuan Xia        final int overrideUseFullscreenUserSwitcher =
283cc3a74f6ef13ca9a783845e7a04ca6561035c98bXiyuan Xia                Settings.System.getInt(mContext.getContentResolver(),
284cc3a74f6ef13ca9a783845e7a04ca6561035c98bXiyuan Xia                        "enable_fullscreen_user_switcher", DEFAULT);
285cc3a74f6ef13ca9a783845e7a04ca6561035c98bXiyuan Xia        if (overrideUseFullscreenUserSwitcher != DEFAULT) {
286cc3a74f6ef13ca9a783845e7a04ca6561035c98bXiyuan Xia            return overrideUseFullscreenUserSwitcher != 0;
287cc3a74f6ef13ca9a783845e7a04ca6561035c98bXiyuan Xia        }
288cc3a74f6ef13ca9a783845e7a04ca6561035c98bXiyuan Xia        // Otherwise default to the build setting.
28940f9dabaa880eaff54099a3763224b241a6668e6Xiyuan Xia        return mContext.getResources().getBoolean(R.bool.config_enableFullscreenUserSwitcher);
290cc3a74f6ef13ca9a783845e7a04ca6561035c98bXiyuan Xia    }
291cc3a74f6ef13ca9a783845e7a04ca6561035c98bXiyuan Xia
292cc3a74f6ef13ca9a783845e7a04ca6561035c98bXiyuan Xia    public void removeUserId(int userId) {
293cc3a74f6ef13ca9a783845e7a04ca6561035c98bXiyuan Xia        if (userId == UserHandle.USER_SYSTEM) {
294cc3a74f6ef13ca9a783845e7a04ca6561035c98bXiyuan Xia            Log.w(TAG, "User " + userId + " could not removed.");
295cc3a74f6ef13ca9a783845e7a04ca6561035c98bXiyuan Xia            return;
296cc3a74f6ef13ca9a783845e7a04ca6561035c98bXiyuan Xia        }
297cc3a74f6ef13ca9a783845e7a04ca6561035c98bXiyuan Xia        if (ActivityManager.getCurrentUser() == userId) {
298cc3a74f6ef13ca9a783845e7a04ca6561035c98bXiyuan Xia            switchToUserId(UserHandle.USER_SYSTEM);
299cc3a74f6ef13ca9a783845e7a04ca6561035c98bXiyuan Xia        }
300cc3a74f6ef13ca9a783845e7a04ca6561035c98bXiyuan Xia        if (mUserManager.removeUser(userId)) {
301cc3a74f6ef13ca9a783845e7a04ca6561035c98bXiyuan Xia            refreshUsers(UserHandle.USER_NULL);
302cc3a74f6ef13ca9a783845e7a04ca6561035c98bXiyuan Xia        }
303cc3a74f6ef13ca9a783845e7a04ca6561035c98bXiyuan Xia    }
304cc3a74f6ef13ca9a783845e7a04ca6561035c98bXiyuan Xia
30500a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos    public void switchTo(UserRecord record) {
30600a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        int id;
30700a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        if (record.isGuest && record.info == null) {
30800a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos            // No guest user. Create one.
309f99727cb878f9709f6c0263c0283257decbaebadAdrian Roos            UserInfo guest = mUserManager.createGuest(
310f99727cb878f9709f6c0263c0283257decbaebadAdrian Roos                    mContext, mContext.getString(R.string.guest_nickname));
311f99727cb878f9709f6c0263c0283257decbaebadAdrian Roos            if (guest == null) {
312f99727cb878f9709f6c0263c0283257decbaebadAdrian Roos                // Couldn't create guest, most likely because there already exists one, we just
313f99727cb878f9709f6c0263c0283257decbaebadAdrian Roos                // haven't reloaded the user list yet.
314f99727cb878f9709f6c0263c0283257decbaebadAdrian Roos                return;
315f99727cb878f9709f6c0263c0283257decbaebadAdrian Roos            }
316f99727cb878f9709f6c0263c0283257decbaebadAdrian Roos            id = guest.id;
317ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos        } else if (record.isAddUser) {
3180c6763a19f32f73f8a940aaee7abecb2a04d1889Adrian Roos            showAddUserDialog();
3190c6763a19f32f73f8a940aaee7abecb2a04d1889Adrian Roos            return;
32000a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        } else {
32100a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos            id = record.info.id;
32200a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        }
32300a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos
32400a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        if (ActivityManager.getCurrentUser() == id) {
325e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos            if (record.isGuest) {
3265005244f10442e75c1f48973fdddce5facf3f360Adrian Roos                showExitGuestDialog(id);
327e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos            }
32800a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos            return;
32900a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        }
33000a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos
331e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos        switchToUserId(id);
332e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos    }
333e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos
334e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos    private void switchToUserId(int id) {
33500a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        try {
33688b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos            pauseRefreshUsers();
33700a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos            ActivityManagerNative.getDefault().switchUser(id);
33800a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        } catch (RemoteException e) {
33900a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos            Log.e(TAG, "Couldn't switch user.", e);
34000a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        }
34100a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos    }
34200a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos
343860397f6521249f1e2733e65ccebe0c0e781b82aXiaohui Chen    private void stopUserId(int id) {
344860397f6521249f1e2733e65ccebe0c0e781b82aXiaohui Chen        try {
3459cbfc9e212151e84910a22387365644916dde446Fyodor Kupolov            ActivityManagerNative.getDefault().stopUser(id, /* force= */ false, null);
346860397f6521249f1e2733e65ccebe0c0e781b82aXiaohui Chen        } catch (RemoteException e) {
347860397f6521249f1e2733e65ccebe0c0e781b82aXiaohui Chen            Log.e(TAG, "Couldn't stop user.", e);
348860397f6521249f1e2733e65ccebe0c0e781b82aXiaohui Chen        }
349860397f6521249f1e2733e65ccebe0c0e781b82aXiaohui Chen    }
350860397f6521249f1e2733e65ccebe0c0e781b82aXiaohui Chen
3515005244f10442e75c1f48973fdddce5facf3f360Adrian Roos    private void showExitGuestDialog(int id) {
3525005244f10442e75c1f48973fdddce5facf3f360Adrian Roos        if (mExitGuestDialog != null && mExitGuestDialog.isShowing()) {
3535005244f10442e75c1f48973fdddce5facf3f360Adrian Roos            mExitGuestDialog.cancel();
3545005244f10442e75c1f48973fdddce5facf3f360Adrian Roos        }
3555005244f10442e75c1f48973fdddce5facf3f360Adrian Roos        mExitGuestDialog = new ExitGuestDialog(mContext, id);
3565005244f10442e75c1f48973fdddce5facf3f360Adrian Roos        mExitGuestDialog.show();
3575005244f10442e75c1f48973fdddce5facf3f360Adrian Roos    }
3585005244f10442e75c1f48973fdddce5facf3f360Adrian Roos
3590c6763a19f32f73f8a940aaee7abecb2a04d1889Adrian Roos    private void showAddUserDialog() {
3600c6763a19f32f73f8a940aaee7abecb2a04d1889Adrian Roos        if (mAddUserDialog != null && mAddUserDialog.isShowing()) {
3610c6763a19f32f73f8a940aaee7abecb2a04d1889Adrian Roos            mAddUserDialog.cancel();
3620c6763a19f32f73f8a940aaee7abecb2a04d1889Adrian Roos        }
3630c6763a19f32f73f8a940aaee7abecb2a04d1889Adrian Roos        mAddUserDialog = new AddUserDialog(mContext);
3640c6763a19f32f73f8a940aaee7abecb2a04d1889Adrian Roos        mAddUserDialog.show();
3650c6763a19f32f73f8a940aaee7abecb2a04d1889Adrian Roos    }
3660c6763a19f32f73f8a940aaee7abecb2a04d1889Adrian Roos
367e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos    private void exitGuest(int id) {
3687cb69df507f5f7956c52a2868a0d6e89aec6dde2Xiaohui Chen        int newId = UserHandle.USER_SYSTEM;
3697cb69df507f5f7956c52a2868a0d6e89aec6dde2Xiaohui Chen        if (mLastNonGuestUser != UserHandle.USER_SYSTEM) {
37070441467f4dc232cd8e6142f0afc117787dc979bAdrian Roos            UserInfo info = mUserManager.getUserInfo(mLastNonGuestUser);
3717cb69df507f5f7956c52a2868a0d6e89aec6dde2Xiaohui Chen            if (info != null && info.isEnabled() && info.supportsSwitchToByUser()) {
37270441467f4dc232cd8e6142f0afc117787dc979bAdrian Roos                newId = info.id;
37370441467f4dc232cd8e6142f0afc117787dc979bAdrian Roos            }
37470441467f4dc232cd8e6142f0afc117787dc979bAdrian Roos        }
37570441467f4dc232cd8e6142f0afc117787dc979bAdrian Roos        switchToUserId(newId);
376e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos        mUserManager.removeUser(id);
377e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos    }
378e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos
37900a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos    private BroadcastReceiver mReceiver = new BroadcastReceiver() {
38000a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        @Override
38100a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        public void onReceive(Context context, Intent intent) {
3825005244f10442e75c1f48973fdddce5facf3f360Adrian Roos            if (DEBUG) {
3835005244f10442e75c1f48973fdddce5facf3f360Adrian Roos                Log.v(TAG, "Broadcast: a=" + intent.getAction()
3845005244f10442e75c1f48973fdddce5facf3f360Adrian Roos                       + " user=" + intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1));
3855005244f10442e75c1f48973fdddce5facf3f360Adrian Roos            }
38688b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos
38788b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos            boolean unpauseRefreshUsers = false;
38888b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos            int forcePictureLoadForId = UserHandle.USER_NULL;
38988b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos
390f4d6ad26636760163083ae84c40d5b19cb6650f6Fyodor Kupolov            if (ACTION_REMOVE_GUEST.equals(intent.getAction())) {
391f4d6ad26636760163083ae84c40d5b19cb6650f6Fyodor Kupolov                int currentUser = ActivityManager.getCurrentUser();
392f4d6ad26636760163083ae84c40d5b19cb6650f6Fyodor Kupolov                UserInfo userInfo = mUserManager.getUserInfo(currentUser);
393f4d6ad26636760163083ae84c40d5b19cb6650f6Fyodor Kupolov                if (userInfo != null && userInfo.isGuest()) {
394f4d6ad26636760163083ae84c40d5b19cb6650f6Fyodor Kupolov                    showExitGuestDialog(currentUser);
395f4d6ad26636760163083ae84c40d5b19cb6650f6Fyodor Kupolov                }
396f4d6ad26636760163083ae84c40d5b19cb6650f6Fyodor Kupolov                return;
39780996bbf40ff192117c391074ed2f9b2cde4e69aAdrian Roos            } else if (ACTION_LOGOUT_USER.equals(intent.getAction())) {
398860397f6521249f1e2733e65ccebe0c0e781b82aXiaohui Chen                int currentUser = ActivityManager.getCurrentUser();
399860397f6521249f1e2733e65ccebe0c0e781b82aXiaohui Chen                if (currentUser != UserHandle.USER_SYSTEM) {
400860397f6521249f1e2733e65ccebe0c0e781b82aXiaohui Chen                    switchToUserId(UserHandle.USER_SYSTEM);
401860397f6521249f1e2733e65ccebe0c0e781b82aXiaohui Chen                    stopUserId(currentUser);
402860397f6521249f1e2733e65ccebe0c0e781b82aXiaohui Chen                }
40388b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos            } else if (Intent.ACTION_USER_SWITCHED.equals(intent.getAction())) {
4045005244f10442e75c1f48973fdddce5facf3f360Adrian Roos                if (mExitGuestDialog != null && mExitGuestDialog.isShowing()) {
4055005244f10442e75c1f48973fdddce5facf3f360Adrian Roos                    mExitGuestDialog.cancel();
4065005244f10442e75c1f48973fdddce5facf3f360Adrian Roos                    mExitGuestDialog = null;
4075005244f10442e75c1f48973fdddce5facf3f360Adrian Roos                }
4085005244f10442e75c1f48973fdddce5facf3f360Adrian Roos
40900a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos                final int currentId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
4107cb69df507f5f7956c52a2868a0d6e89aec6dde2Xiaohui Chen                final UserInfo userInfo = mUserManager.getUserInfo(currentId);
41100a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos                final int N = mUsers.size();
41200a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos                for (int i = 0; i < N; i++) {
41300a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos                    UserRecord record = mUsers.get(i);
414e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos                    if (record.info == null) continue;
41500a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos                    boolean shouldBeCurrent = record.info.id == currentId;
41600a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos                    if (record.isCurrent != shouldBeCurrent) {
41700a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos                        mUsers.set(i, record.copyWithIsCurrent(shouldBeCurrent));
41800a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos                    }
41970441467f4dc232cd8e6142f0afc117787dc979bAdrian Roos                    if (shouldBeCurrent && !record.isGuest) {
42070441467f4dc232cd8e6142f0afc117787dc979bAdrian Roos                        mLastNonGuestUser = record.info.id;
42170441467f4dc232cd8e6142f0afc117787dc979bAdrian Roos                    }
4227cb69df507f5f7956c52a2868a0d6e89aec6dde2Xiaohui Chen                    if ((userInfo == null || !userInfo.isAdmin()) && record.isRestricted) {
423ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos                        // Immediately remove restricted records in case the AsyncTask is too slow.
424ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos                        mUsers.remove(i);
425ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos                        i--;
426ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos                    }
42700a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos                }
42800a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos                notifyAdapters();
429860397f6521249f1e2733e65ccebe0c0e781b82aXiaohui Chen
430860397f6521249f1e2733e65ccebe0c0e781b82aXiaohui Chen                if (UserManager.isSplitSystemUser() && userInfo != null && !userInfo.isGuest()
431860397f6521249f1e2733e65ccebe0c0e781b82aXiaohui Chen                        && userInfo.id != UserHandle.USER_SYSTEM) {
432860397f6521249f1e2733e65ccebe0c0e781b82aXiaohui Chen                    showLogoutNotification(currentId);
433860397f6521249f1e2733e65ccebe0c0e781b82aXiaohui Chen                }
434ce161861c3507c91c25b2491abac1e7611d14c5cFyodor Kupolov                if (userInfo != null && userInfo.isGuest()) {
435ce161861c3507c91c25b2491abac1e7611d14c5cFyodor Kupolov                    showGuestNotification(currentId);
436ce161861c3507c91c25b2491abac1e7611d14c5cFyodor Kupolov                }
43788b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos                unpauseRefreshUsers = true;
43888b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos            } else if (Intent.ACTION_USER_INFO_CHANGED.equals(intent.getAction())) {
439e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos                forcePictureLoadForId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE,
440e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos                        UserHandle.USER_NULL);
441e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos            }
442e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos            refreshUsers(forcePictureLoadForId);
44388b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos            if (unpauseRefreshUsers) {
44488b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos                mUnpauseRefreshUsers.run();
44588b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos            }
44600a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        }
447f4d6ad26636760163083ae84c40d5b19cb6650f6Fyodor Kupolov
448f4d6ad26636760163083ae84c40d5b19cb6650f6Fyodor Kupolov        private void showGuestNotification(int guestUserId) {
449f4d6ad26636760163083ae84c40d5b19cb6650f6Fyodor Kupolov            PendingIntent removeGuestPI = PendingIntent.getBroadcastAsUser(mContext,
4507cb69df507f5f7956c52a2868a0d6e89aec6dde2Xiaohui Chen                    0, new Intent(ACTION_REMOVE_GUEST), 0, UserHandle.SYSTEM);
451f4d6ad26636760163083ae84c40d5b19cb6650f6Fyodor Kupolov            Notification notification = new Notification.Builder(mContext)
452f4d6ad26636760163083ae84c40d5b19cb6650f6Fyodor Kupolov                    .setVisibility(Notification.VISIBILITY_SECRET)
453f4d6ad26636760163083ae84c40d5b19cb6650f6Fyodor Kupolov                    .setPriority(Notification.PRIORITY_MIN)
454f4d6ad26636760163083ae84c40d5b19cb6650f6Fyodor Kupolov                    .setSmallIcon(R.drawable.ic_person)
455f4d6ad26636760163083ae84c40d5b19cb6650f6Fyodor Kupolov                    .setContentTitle(mContext.getString(R.string.guest_notification_title))
456f4d6ad26636760163083ae84c40d5b19cb6650f6Fyodor Kupolov                    .setContentText(mContext.getString(R.string.guest_notification_text))
45752408f4fb5dab950847aa12e3bea44399ccd0d6eFyodor Kupolov                    .setContentIntent(removeGuestPI)
458f4d6ad26636760163083ae84c40d5b19cb6650f6Fyodor Kupolov                    .setShowWhen(false)
459f4d6ad26636760163083ae84c40d5b19cb6650f6Fyodor Kupolov                    .addAction(R.drawable.ic_delete,
460f4d6ad26636760163083ae84c40d5b19cb6650f6Fyodor Kupolov                            mContext.getString(R.string.guest_notification_remove_action),
461f4d6ad26636760163083ae84c40d5b19cb6650f6Fyodor Kupolov                            removeGuestPI)
462f4d6ad26636760163083ae84c40d5b19cb6650f6Fyodor Kupolov                    .build();
463d81f8270bec71ec9a569c8308c42cacd7aba0d23Amith Yamasani            NotificationManager.from(mContext).notifyAsUser(TAG_REMOVE_GUEST, ID_REMOVE_GUEST,
464d81f8270bec71ec9a569c8308c42cacd7aba0d23Amith Yamasani                    notification, new UserHandle(guestUserId));
465f4d6ad26636760163083ae84c40d5b19cb6650f6Fyodor Kupolov        }
466860397f6521249f1e2733e65ccebe0c0e781b82aXiaohui Chen
467860397f6521249f1e2733e65ccebe0c0e781b82aXiaohui Chen        private void showLogoutNotification(int userId) {
468860397f6521249f1e2733e65ccebe0c0e781b82aXiaohui Chen            PendingIntent logoutPI = PendingIntent.getBroadcastAsUser(mContext,
469860397f6521249f1e2733e65ccebe0c0e781b82aXiaohui Chen                    0, new Intent(ACTION_LOGOUT_USER), 0, UserHandle.SYSTEM);
470860397f6521249f1e2733e65ccebe0c0e781b82aXiaohui Chen            Notification notification = new Notification.Builder(mContext)
471860397f6521249f1e2733e65ccebe0c0e781b82aXiaohui Chen                    .setVisibility(Notification.VISIBILITY_SECRET)
472860397f6521249f1e2733e65ccebe0c0e781b82aXiaohui Chen                    .setPriority(Notification.PRIORITY_MIN)
473860397f6521249f1e2733e65ccebe0c0e781b82aXiaohui Chen                    .setSmallIcon(R.drawable.ic_person)
474860397f6521249f1e2733e65ccebe0c0e781b82aXiaohui Chen                    .setContentTitle(mContext.getString(R.string.user_logout_notification_title))
475860397f6521249f1e2733e65ccebe0c0e781b82aXiaohui Chen                    .setContentText(mContext.getString(R.string.user_logout_notification_text))
47652408f4fb5dab950847aa12e3bea44399ccd0d6eFyodor Kupolov                    .setContentIntent(logoutPI)
477ce161861c3507c91c25b2491abac1e7611d14c5cFyodor Kupolov                    .setOngoing(true)
478860397f6521249f1e2733e65ccebe0c0e781b82aXiaohui Chen                    .setShowWhen(false)
479860397f6521249f1e2733e65ccebe0c0e781b82aXiaohui Chen                    .addAction(R.drawable.ic_delete,
480860397f6521249f1e2733e65ccebe0c0e781b82aXiaohui Chen                            mContext.getString(R.string.user_logout_notification_action),
481860397f6521249f1e2733e65ccebe0c0e781b82aXiaohui Chen                            logoutPI)
482860397f6521249f1e2733e65ccebe0c0e781b82aXiaohui Chen                    .build();
483860397f6521249f1e2733e65ccebe0c0e781b82aXiaohui Chen            NotificationManager.from(mContext).notifyAsUser(TAG_LOGOUT_USER, ID_LOGOUT_USER,
484860397f6521249f1e2733e65ccebe0c0e781b82aXiaohui Chen                    notification, new UserHandle(userId));
485860397f6521249f1e2733e65ccebe0c0e781b82aXiaohui Chen        }
48600a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos    };
48700a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos
48888b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos    private final Runnable mUnpauseRefreshUsers = new Runnable() {
48988b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos        @Override
49088b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos        public void run() {
49188b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos            mHandler.removeCallbacks(this);
49288b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos            mPauseRefreshUsers = false;
49388b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos            refreshUsers(UserHandle.USER_NULL);
49488b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos        }
49588b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos    };
49688b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos
497ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos    private final ContentObserver mSettingsObserver = new ContentObserver(new Handler()) {
4982daf62ce400fe58c7f0495dda432ba568a75f579Jason Monk        public void onChange(boolean selfChange) {
4992daf62ce400fe58c7f0495dda432ba568a75f579Jason Monk            mSimpleUserSwitcher = Settings.Global.getInt(mContext.getContentResolver(),
5002daf62ce400fe58c7f0495dda432ba568a75f579Jason Monk                    SIMPLE_USER_SWITCHER_GLOBAL_SETTING, 0) != 0;
501ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos            mAddUsersWhenLocked = Settings.Global.getInt(mContext.getContentResolver(),
502ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos                    Settings.Global.ADD_USERS_WHEN_LOCKED, 0) != 0;
5032daf62ce400fe58c7f0495dda432ba568a75f579Jason Monk            refreshUsers(UserHandle.USER_NULL);
5042daf62ce400fe58c7f0495dda432ba568a75f579Jason Monk        };
5052daf62ce400fe58c7f0495dda432ba568a75f579Jason Monk    };
5062daf62ce400fe58c7f0495dda432ba568a75f579Jason Monk
50700a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
50800a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        pw.println("UserSwitcherController state:");
50970441467f4dc232cd8e6142f0afc117787dc979bAdrian Roos        pw.println("  mLastNonGuestUser=" + mLastNonGuestUser);
51000a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        pw.print("  mUsers.size="); pw.println(mUsers.size());
51100a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        for (int i = 0; i < mUsers.size(); i++) {
51200a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos            final UserRecord u = mUsers.get(i);
51300a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos            pw.print("    "); pw.println(u.toString());
51400a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        }
51500a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos    }
51600a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos
51757cf5702e0634b8cb25daa8f2f73292428ec4e08Adrian Roos    public String getCurrentUserName(Context context) {
51857cf5702e0634b8cb25daa8f2f73292428ec4e08Adrian Roos        if (mUsers.isEmpty()) return null;
51957cf5702e0634b8cb25daa8f2f73292428ec4e08Adrian Roos        UserRecord item = mUsers.get(0);
52057cf5702e0634b8cb25daa8f2f73292428ec4e08Adrian Roos        if (item == null || item.info == null) return null;
52157cf5702e0634b8cb25daa8f2f73292428ec4e08Adrian Roos        if (item.isGuest) return context.getString(R.string.guest_nickname);
52257cf5702e0634b8cb25daa8f2f73292428ec4e08Adrian Roos        return item.info.name;
52357cf5702e0634b8cb25daa8f2f73292428ec4e08Adrian Roos    }
52457cf5702e0634b8cb25daa8f2f73292428ec4e08Adrian Roos
52500a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos    public static abstract class BaseUserAdapter extends BaseAdapter {
52600a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos
52700a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        final UserSwitcherController mController;
52800a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos
52900a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        protected BaseUserAdapter(UserSwitcherController controller) {
53000a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos            mController = controller;
53100a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos            controller.mAdapters.add(new WeakReference<>(this));
53200a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        }
53300a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos
53400a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        @Override
53500a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        public int getCount() {
536ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos            boolean secureKeyguardShowing = mController.mKeyguardMonitor.isShowing()
5378a3a964d0ad13374a4c4ee8a8a1b12aa00e577f0Jason Monk                    && mController.mKeyguardMonitor.isSecure()
538e8bae6288bf0f241f0cea70f2c5e8294f930d4d8Selim Cinek                    && !mController.mKeyguardMonitor.canSkipBouncer();
539ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos            if (!secureKeyguardShowing) {
540ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos                return mController.mUsers.size();
541ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos            }
542ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos            // The lock screen is secure and showing. Filter out restricted records.
543ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos            final int N = mController.mUsers.size();
544ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos            int count = 0;
545ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos            for (int i = 0; i < N; i++) {
546ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos                if (mController.mUsers.get(i).isRestricted) {
547ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos                    break;
548ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos                } else {
549ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos                    count++;
550ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos                }
551ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos            }
552ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos            return count;
55300a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        }
55400a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos
55500a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        @Override
55600a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        public UserRecord getItem(int position) {
55700a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos            return mController.mUsers.get(position);
55800a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        }
55900a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos
56000a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        @Override
56100a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        public long getItemId(int position) {
562e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos            return position;
56300a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        }
56400a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos
56500a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        public void switchTo(UserRecord record) {
56600a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos            mController.switchTo(record);
56700a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        }
568e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos
569e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos        public String getName(Context context, UserRecord item) {
570e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos            if (item.isGuest) {
571e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos                if (item.isCurrent) {
572e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos                    return context.getString(R.string.guest_exit_guest);
573e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos                } else {
574e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos                    return context.getString(
575e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos                            item.info == null ? R.string.guest_new_guest : R.string.guest_nickname);
576e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos                }
577ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos            } else if (item.isAddUser) {
578ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos                return context.getString(R.string.user_add_user);
579e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos            } else {
580e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos                return item.info.name;
581e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos            }
582e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos        }
583723632ea1ae30b33e9c2055194a4464f00c48c61Adrian Roos
584ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos        public Drawable getDrawable(Context context, UserRecord item) {
585ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos            if (item.isAddUser) {
586ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos                return context.getDrawable(R.drawable.ic_add_circle_qs);
587ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos            }
58864d4dca63f65e4c7d4a829c85ff6670bdd34e2ebAlexandra Gherghina            return UserIcons.getDefaultUserIcon(item.isGuest ? UserHandle.USER_NULL : item.info.id,
58964d4dca63f65e4c7d4a829c85ff6670bdd34e2ebAlexandra Gherghina                    /* light= */ true);
590ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos        }
591844c92b444dca7f5ef4d0943fb14e2cbeee49701Adrian Roos
592844c92b444dca7f5ef4d0943fb14e2cbeee49701Adrian Roos        public void refresh() {
593844c92b444dca7f5ef4d0943fb14e2cbeee49701Adrian Roos            mController.refreshUsers(UserHandle.USER_NULL);
594844c92b444dca7f5ef4d0943fb14e2cbeee49701Adrian Roos        }
59500a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos    }
59600a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos
59700a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos    public static final class UserRecord {
59800a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        public final UserInfo info;
59900a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        public final Bitmap picture;
60000a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        public final boolean isGuest;
60100a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        public final boolean isCurrent;
602ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos        public final boolean isAddUser;
603ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos        /** If true, the record is only visible to the owner and only when unlocked. */
604ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos        public final boolean isRestricted;
60500a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos
606ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos        public UserRecord(UserInfo info, Bitmap picture, boolean isGuest, boolean isCurrent,
607ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos                boolean isAddUser, boolean isRestricted) {
60800a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos            this.info = info;
60900a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos            this.picture = picture;
61000a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos            this.isGuest = isGuest;
61100a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos            this.isCurrent = isCurrent;
612ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos            this.isAddUser = isAddUser;
613ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos            this.isRestricted = isRestricted;
61400a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        }
61500a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos
61600a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        public UserRecord copyWithIsCurrent(boolean _isCurrent) {
617ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos            return new UserRecord(info, picture, isGuest, _isCurrent, isAddUser, isRestricted);
61800a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        }
61900a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos
62000a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        public String toString() {
62100a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos            StringBuilder sb = new StringBuilder();
62200a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos            sb.append("UserRecord(");
62300a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos            if (info != null) {
62400a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos                sb.append("name=\"" + info.name + "\" id=" + info.id);
62500a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos            } else {
626ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos                if (isGuest) {
627ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos                    sb.append("<add guest placeholder>");
628ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos                } else if (isAddUser) {
629ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos                    sb.append("<add user placeholder>");
630ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos                }
63100a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos            }
632ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos            if (isGuest) sb.append(" <isGuest>");
633ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos            if (isAddUser) sb.append(" <isAddUser>");
634ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos            if (isCurrent) sb.append(" <isCurrent>");
635ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos            if (picture != null) sb.append(" <hasPicture>");
636ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos            if (isRestricted) sb.append(" <isRestricted>");
63700a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos            sb.append(')');
63800a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos            return sb.toString();
63900a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        }
64000a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos    }
64100a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos
64200a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos    public final QSTile.DetailAdapter userDetailAdapter = new QSTile.DetailAdapter() {
64300a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        private final Intent USER_SETTINGS_INTENT = new Intent("android.settings.USER_SETTINGS");
64400a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos
64500a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        @Override
646c06fbb12984a3d3e4c80ab9f819841acae5b0133Jason Monk        public CharSequence getTitle() {
647c06fbb12984a3d3e4c80ab9f819841acae5b0133Jason Monk            return mContext.getString(R.string.quick_settings_user_title);
64800a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        }
64900a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos
65000a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        @Override
65100a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        public View createDetailView(Context context, View convertView, ViewGroup parent) {
6521940892d891c1d2538f51608b6618af646ab7481Adrian Roos            UserDetailView v;
65300a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos            if (!(convertView instanceof UserDetailView)) {
6541940892d891c1d2538f51608b6618af646ab7481Adrian Roos                v = UserDetailView.inflate(context, parent, false);
65500a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos                v.createAndSetAdapter(UserSwitcherController.this);
6561940892d891c1d2538f51608b6618af646ab7481Adrian Roos            } else {
6571940892d891c1d2538f51608b6618af646ab7481Adrian Roos                v = (UserDetailView) convertView;
65800a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos            }
659844c92b444dca7f5ef4d0943fb14e2cbeee49701Adrian Roos            v.refreshAdapter();
66000a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos            return v;
66100a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        }
66200a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos
66300a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        @Override
66400a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        public Intent getSettingsIntent() {
66500a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos            return USER_SETTINGS_INTENT;
66600a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        }
66700a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos
66800a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        @Override
66900a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        public Boolean getToggleState() {
67000a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos            return null;
67100a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        }
67200a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos
67300a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        @Override
67400a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        public void setToggleState(boolean state) {
67500a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        }
676457a21cdeac04565a0c40ad8c43a928c1182ddd1Chris Wren
677457a21cdeac04565a0c40ad8c43a928c1182ddd1Chris Wren        @Override
678457a21cdeac04565a0c40ad8c43a928c1182ddd1Chris Wren        public int getMetricsCategory() {
679457a21cdeac04565a0c40ad8c43a928c1182ddd1Chris Wren            return MetricsLogger.QS_USERDETAIL;
680457a21cdeac04565a0c40ad8c43a928c1182ddd1Chris Wren        }
68100a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos    };
6825005244f10442e75c1f48973fdddce5facf3f360Adrian Roos
683ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos    private final KeyguardMonitor.Callback mCallback = new KeyguardMonitor.Callback() {
684ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos        @Override
685ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos        public void onKeyguardChanged() {
686ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos            notifyAdapters();
687ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos        }
688ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos    };
689ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos
6905005244f10442e75c1f48973fdddce5facf3f360Adrian Roos    private final class ExitGuestDialog extends SystemUIDialog implements
6915005244f10442e75c1f48973fdddce5facf3f360Adrian Roos            DialogInterface.OnClickListener {
6925005244f10442e75c1f48973fdddce5facf3f360Adrian Roos
6935005244f10442e75c1f48973fdddce5facf3f360Adrian Roos        private final int mGuestId;
6945005244f10442e75c1f48973fdddce5facf3f360Adrian Roos
6955005244f10442e75c1f48973fdddce5facf3f360Adrian Roos        public ExitGuestDialog(Context context, int guestId) {
6965005244f10442e75c1f48973fdddce5facf3f360Adrian Roos            super(context);
6975005244f10442e75c1f48973fdddce5facf3f360Adrian Roos            setTitle(R.string.guest_exit_guest_dialog_title);
6985005244f10442e75c1f48973fdddce5facf3f360Adrian Roos            setMessage(context.getString(R.string.guest_exit_guest_dialog_message));
6995005244f10442e75c1f48973fdddce5facf3f360Adrian Roos            setButton(DialogInterface.BUTTON_NEGATIVE,
700e5b274ac612400a7bc9f258d4ef3c366cfa1bc11Amith Yamasani                    context.getString(android.R.string.cancel), this);
7015005244f10442e75c1f48973fdddce5facf3f360Adrian Roos            setButton(DialogInterface.BUTTON_POSITIVE,
702e5b274ac612400a7bc9f258d4ef3c366cfa1bc11Amith Yamasani                    context.getString(R.string.guest_exit_guest_dialog_remove), this);
7035005244f10442e75c1f48973fdddce5facf3f360Adrian Roos            setCanceledOnTouchOutside(false);
7045005244f10442e75c1f48973fdddce5facf3f360Adrian Roos            mGuestId = guestId;
7055005244f10442e75c1f48973fdddce5facf3f360Adrian Roos        }
7065005244f10442e75c1f48973fdddce5facf3f360Adrian Roos
7075005244f10442e75c1f48973fdddce5facf3f360Adrian Roos        @Override
7085005244f10442e75c1f48973fdddce5facf3f360Adrian Roos        public void onClick(DialogInterface dialog, int which) {
7095005244f10442e75c1f48973fdddce5facf3f360Adrian Roos            if (which == BUTTON_NEGATIVE) {
7105005244f10442e75c1f48973fdddce5facf3f360Adrian Roos                cancel();
7115005244f10442e75c1f48973fdddce5facf3f360Adrian Roos            } else {
7125005244f10442e75c1f48973fdddce5facf3f360Adrian Roos                dismiss();
7135005244f10442e75c1f48973fdddce5facf3f360Adrian Roos                exitGuest(mGuestId);
7145005244f10442e75c1f48973fdddce5facf3f360Adrian Roos            }
7155005244f10442e75c1f48973fdddce5facf3f360Adrian Roos        }
7165005244f10442e75c1f48973fdddce5facf3f360Adrian Roos    }
7170c6763a19f32f73f8a940aaee7abecb2a04d1889Adrian Roos
7180c6763a19f32f73f8a940aaee7abecb2a04d1889Adrian Roos    private final class AddUserDialog extends SystemUIDialog implements
7190c6763a19f32f73f8a940aaee7abecb2a04d1889Adrian Roos            DialogInterface.OnClickListener {
7200c6763a19f32f73f8a940aaee7abecb2a04d1889Adrian Roos
7210c6763a19f32f73f8a940aaee7abecb2a04d1889Adrian Roos        public AddUserDialog(Context context) {
7220c6763a19f32f73f8a940aaee7abecb2a04d1889Adrian Roos            super(context);
7230c6763a19f32f73f8a940aaee7abecb2a04d1889Adrian Roos            setTitle(R.string.user_add_user_title);
7240c6763a19f32f73f8a940aaee7abecb2a04d1889Adrian Roos            setMessage(context.getString(R.string.user_add_user_message_short));
7250c6763a19f32f73f8a940aaee7abecb2a04d1889Adrian Roos            setButton(DialogInterface.BUTTON_NEGATIVE,
7260c6763a19f32f73f8a940aaee7abecb2a04d1889Adrian Roos                    context.getString(android.R.string.cancel), this);
7270c6763a19f32f73f8a940aaee7abecb2a04d1889Adrian Roos            setButton(DialogInterface.BUTTON_POSITIVE,
7280c6763a19f32f73f8a940aaee7abecb2a04d1889Adrian Roos                    context.getString(android.R.string.ok), this);
7290c6763a19f32f73f8a940aaee7abecb2a04d1889Adrian Roos        }
7300c6763a19f32f73f8a940aaee7abecb2a04d1889Adrian Roos
7310c6763a19f32f73f8a940aaee7abecb2a04d1889Adrian Roos        @Override
7320c6763a19f32f73f8a940aaee7abecb2a04d1889Adrian Roos        public void onClick(DialogInterface dialog, int which) {
7330c6763a19f32f73f8a940aaee7abecb2a04d1889Adrian Roos            if (which == BUTTON_NEGATIVE) {
7340c6763a19f32f73f8a940aaee7abecb2a04d1889Adrian Roos                cancel();
7350c6763a19f32f73f8a940aaee7abecb2a04d1889Adrian Roos            } else {
7360c6763a19f32f73f8a940aaee7abecb2a04d1889Adrian Roos                dismiss();
737ccbeb61ac21527839deb115199cbe98fa2b73c05Guang Zhu                if (ActivityManager.isUserAMonkey()) {
738ccbeb61ac21527839deb115199cbe98fa2b73c05Guang Zhu                    return;
739ccbeb61ac21527839deb115199cbe98fa2b73c05Guang Zhu                }
740cfe64c8afa9f30d8874c72440c3992e79fdb60c9Xiaohui Chen                UserInfo user = mUserManager.createUser(
741f99727cb878f9709f6c0263c0283257decbaebadAdrian Roos                        mContext.getString(R.string.user_new_user_name), 0 /* flags */);
742f99727cb878f9709f6c0263c0283257decbaebadAdrian Roos                if (user == null) {
743f99727cb878f9709f6c0263c0283257decbaebadAdrian Roos                    // Couldn't create user, most likely because there are too many, but we haven't
744f99727cb878f9709f6c0263c0283257decbaebadAdrian Roos                    // been able to reload the list yet.
745f99727cb878f9709f6c0263c0283257decbaebadAdrian Roos                    return;
746f99727cb878f9709f6c0263c0283257decbaebadAdrian Roos                }
747f99727cb878f9709f6c0263c0283257decbaebadAdrian Roos                int id = user.id;
74864d4dca63f65e4c7d4a829c85ff6670bdd34e2ebAlexandra Gherghina                Bitmap icon = UserIcons.convertToBitmap(UserIcons.getDefaultUserIcon(
74964d4dca63f65e4c7d4a829c85ff6670bdd34e2ebAlexandra Gherghina                        id, /* light= */ false));
75064d4dca63f65e4c7d4a829c85ff6670bdd34e2ebAlexandra Gherghina                mUserManager.setUserIcon(id, icon);
7510c6763a19f32f73f8a940aaee7abecb2a04d1889Adrian Roos                switchToUserId(id);
7520c6763a19f32f73f8a940aaee7abecb2a04d1889Adrian Roos            }
7530c6763a19f32f73f8a940aaee7abecb2a04d1889Adrian Roos        }
7540c6763a19f32f73f8a940aaee7abecb2a04d1889Adrian Roos    }
75500a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos}
756