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;
352daf62ce400fe58c7f0495dda432ba568a75f579Jason Monkimport android.os.Handler;
3600a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roosimport android.os.RemoteException;
37e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roosimport android.os.UserHandle;
3800a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roosimport android.os.UserManager;
392daf62ce400fe58c7f0495dda432ba568a75f579Jason Monkimport android.provider.Settings;
40523c404612c634f6901205fee4f4cae594f62982Fyodor Kupolovimport android.telephony.PhoneStateListener;
41523c404612c634f6901205fee4f4cae594f62982Fyodor Kupolovimport android.telephony.TelephonyManager;
4200a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roosimport android.util.Log;
43e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roosimport android.util.SparseArray;
4488b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roosimport android.util.SparseBooleanArray;
4500a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roosimport android.view.View;
4600a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roosimport android.view.ViewGroup;
4700a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roosimport android.widget.BaseAdapter;
4800a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos
49f6e9228b8a97603d3ceb8f0d61e8d87cf19bd21fChris Wrenimport com.android.internal.logging.MetricsProto.MetricsEvent;
50117d5b4f28bbaf1b7458233ae5e101b9c41d7b64Chris Wrenimport com.android.internal.messages.SystemMessageProto.SystemMessage;
5164d4dca63f65e4c7d4a829c85ff6670bdd34e2ebAlexandra Gherghinaimport com.android.internal.util.UserIcons;
521c7cda8bbfb848961536a4adbf2c81c5ffddae16Sudheer Shankaimport com.android.settingslib.RestrictedLockUtils;
5364d4dca63f65e4c7d4a829c85ff6670bdd34e2ebAlexandra Gherghinaimport com.android.systemui.GuestResumeSessionReceiver;
5464d4dca63f65e4c7d4a829c85ff6670bdd34e2ebAlexandra Gherghinaimport com.android.systemui.R;
55e25c18da7d2cc3e02620dadfcb976521821bc9d8Adrian Roosimport com.android.systemui.SystemUI;
563c2c34bb039e92d68f466b7d194cbbe8241d8d60Winsonimport com.android.systemui.SystemUISecondaryUserService;
5764d4dca63f65e4c7d4a829c85ff6670bdd34e2ebAlexandra Gherghinaimport com.android.systemui.qs.QSTile;
5864d4dca63f65e4c7d4a829c85ff6670bdd34e2ebAlexandra Gherghinaimport com.android.systemui.qs.tiles.UserDetailView;
591c7cda8bbfb848961536a4adbf2c81c5ffddae16Sudheer Shankaimport com.android.systemui.statusbar.phone.ActivityStarter;
6064d4dca63f65e4c7d4a829c85ff6670bdd34e2ebAlexandra Gherghinaimport com.android.systemui.statusbar.phone.SystemUIDialog;
6164d4dca63f65e4c7d4a829c85ff6670bdd34e2ebAlexandra Gherghina
6200a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roosimport java.io.FileDescriptor;
6300a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roosimport java.io.PrintWriter;
6400a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roosimport java.lang.ref.WeakReference;
6500a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roosimport java.util.ArrayList;
6600a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roosimport java.util.List;
6700a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos
681c7cda8bbfb848961536a4adbf2c81c5ffddae16Sudheer Shankaimport static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
691c7cda8bbfb848961536a4adbf2c81c5ffddae16Sudheer Shanka
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
8800a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos    private final Context mContext;
8900a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos    private 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;
9488b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos    private 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;
101ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos    private boolean mSimpleUserSwitcher;
102ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos    private boolean mAddUsersWhenLocked;
10388b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos    private boolean mPauseRefreshUsers;
1043c2c34bb039e92d68f466b7d194cbbe8241d8d60Winson    private int mSecondaryUser = UserHandle.USER_NULL;
1053c2c34bb039e92d68f466b7d194cbbe8241d8d60Winson    private Intent mSecondaryUserServiceIntent;
10688b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos    private SparseBooleanArray mForcePictureLoadForUserId = new SparseBooleanArray(2);
10700a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos
10888b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos    public UserSwitcherController(Context context, KeyguardMonitor keyguardMonitor,
1091c7cda8bbfb848961536a4adbf2c81c5ffddae16Sudheer Shanka            Handler handler, ActivityStarter activityStarter) {
11000a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        mContext = context;
1115005244f10442e75c1f48973fdddce5facf3f360Adrian Roos        mGuestResumeSessionReceiver.register(context);
112ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos        mKeyguardMonitor = keyguardMonitor;
11388b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos        mHandler = handler;
1141c7cda8bbfb848961536a4adbf2c81c5ffddae16Sudheer Shanka        mActivityStarter = activityStarter;
11500a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        mUserManager = UserManager.get(context);
11600a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        IntentFilter filter = new IntentFilter();
11700a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        filter.addAction(Intent.ACTION_USER_ADDED);
11800a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        filter.addAction(Intent.ACTION_USER_REMOVED);
11900a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        filter.addAction(Intent.ACTION_USER_INFO_CHANGED);
12000a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        filter.addAction(Intent.ACTION_USER_SWITCHED);
121ad2e4bf9f36cf612db6c397feca8effb125ee541Amith Yamasani        filter.addAction(Intent.ACTION_USER_STOPPED);
12207140f7ffd56bf9d4946eba4e48b21a748125659Fyodor Kupolov        filter.addAction(Intent.ACTION_USER_UNLOCKED);
1237cb69df507f5f7956c52a2868a0d6e89aec6dde2Xiaohui Chen        mContext.registerReceiverAsUser(mReceiver, UserHandle.SYSTEM, filter,
124e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos                null /* permission */, null /* scheduler */);
1252daf62ce400fe58c7f0495dda432ba568a75f579Jason Monk
1263c2c34bb039e92d68f466b7d194cbbe8241d8d60Winson        mSecondaryUserServiceIntent = new Intent(context, SystemUISecondaryUserService.class);
1273c2c34bb039e92d68f466b7d194cbbe8241d8d60Winson
128d81f8270bec71ec9a569c8308c42cacd7aba0d23Amith Yamasani        filter = new IntentFilter();
129d81f8270bec71ec9a569c8308c42cacd7aba0d23Amith Yamasani        filter.addAction(ACTION_REMOVE_GUEST);
130860397f6521249f1e2733e65ccebe0c0e781b82aXiaohui Chen        filter.addAction(ACTION_LOGOUT_USER);
1315891a346abbde5bfe95a52633d05533406cc6a2eAmith Yamasani        mContext.registerReceiverAsUser(mReceiver, UserHandle.SYSTEM, filter,
132d81f8270bec71ec9a569c8308c42cacd7aba0d23Amith Yamasani                PERMISSION_SELF, null /* scheduler */);
133ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos
1342daf62ce400fe58c7f0495dda432ba568a75f579Jason Monk        mContext.getContentResolver().registerContentObserver(
1352daf62ce400fe58c7f0495dda432ba568a75f579Jason Monk                Settings.Global.getUriFor(SIMPLE_USER_SWITCHER_GLOBAL_SETTING), true,
136ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos                mSettingsObserver);
137ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos        mContext.getContentResolver().registerContentObserver(
138ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos                Settings.Global.getUriFor(Settings.Global.ADD_USERS_WHEN_LOCKED), true,
139ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos                mSettingsObserver);
14007140f7ffd56bf9d4946eba4e48b21a748125659Fyodor Kupolov        mContext.getContentResolver().registerContentObserver(
14107140f7ffd56bf9d4946eba4e48b21a748125659Fyodor Kupolov                Settings.Global.getUriFor(
14207140f7ffd56bf9d4946eba4e48b21a748125659Fyodor Kupolov                        Settings.Global.ALLOW_USER_SWITCHING_WHEN_SYSTEM_USER_LOCKED),
14307140f7ffd56bf9d4946eba4e48b21a748125659Fyodor Kupolov                true, mSettingsObserver);
144ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos        // Fetch initial values.
145ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos        mSettingsObserver.onChange(false);
146ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos
147ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos        keyguardMonitor.addCallback(mCallback);
148523c404612c634f6901205fee4f4cae594f62982Fyodor Kupolov        listenForCallState();
1492daf62ce400fe58c7f0495dda432ba568a75f579Jason Monk
150e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos        refreshUsers(UserHandle.USER_NULL);
15100a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos    }
15200a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos
153e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos    /**
154e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos     * Refreshes users from UserManager.
155e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos     *
156e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos     * The pictures are only loaded if they have not been loaded yet.
157e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos     *
158e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos     * @param forcePictureLoadForId forces the picture of the given user to be reloaded.
159e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos     */
16095ab7849444125387dc88088bb5197ee463d8c17Amith Yamasani    @SuppressWarnings("unchecked")
161e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos    private void refreshUsers(int forcePictureLoadForId) {
16288b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos        if (DEBUG) Log.d(TAG, "refreshUsers(forcePictureLoadForId=" + forcePictureLoadForId+")");
16388b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos        if (forcePictureLoadForId != UserHandle.USER_NULL) {
16488b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos            mForcePictureLoadForUserId.put(forcePictureLoadForId, true);
16588b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos        }
16688b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos
16788b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos        if (mPauseRefreshUsers) {
16888b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos            return;
16988b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos        }
170c5db390f5b5c6c685267dd22cf3b2926f54fba35Adrian Roos
171d390b893eafae634844d7b8b84efaa7baa199119Adrian Roos        boolean forceAllUsers = mForcePictureLoadForUserId.get(UserHandle.USER_ALL);
172c5db390f5b5c6c685267dd22cf3b2926f54fba35Adrian Roos        SparseArray<Bitmap> bitmaps = new SparseArray<>(mUsers.size());
173c5db390f5b5c6c685267dd22cf3b2926f54fba35Adrian Roos        final int N = mUsers.size();
174c5db390f5b5c6c685267dd22cf3b2926f54fba35Adrian Roos        for (int i = 0; i < N; i++) {
175c5db390f5b5c6c685267dd22cf3b2926f54fba35Adrian Roos            UserRecord r = mUsers.get(i);
176d390b893eafae634844d7b8b84efaa7baa199119Adrian Roos            if (r == null || r.picture == null || r.info == null || forceAllUsers
177d390b893eafae634844d7b8b84efaa7baa199119Adrian Roos                    || mForcePictureLoadForUserId.get(r.info.id)) {
178c5db390f5b5c6c685267dd22cf3b2926f54fba35Adrian Roos                continue;
179e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos            }
180c5db390f5b5c6c685267dd22cf3b2926f54fba35Adrian Roos            bitmaps.put(r.info.id, r.picture);
181e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos        }
18288b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos        mForcePictureLoadForUserId.clear();
183e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos
184ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos        final boolean addUsersWhenLocked = mAddUsersWhenLocked;
185e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos        new AsyncTask<SparseArray<Bitmap>, Void, ArrayList<UserRecord>>() {
186e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos            @SuppressWarnings("unchecked")
18700a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos            @Override
188e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos            protected ArrayList<UserRecord> doInBackground(SparseArray<Bitmap>... params) {
189e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos                final SparseArray<Bitmap> bitmaps = params[0];
19000a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos                List<UserInfo> infos = mUserManager.getUsers(true);
19100a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos                if (infos == null) {
19200a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos                    return null;
19300a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos                }
19400a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos                ArrayList<UserRecord> records = new ArrayList<>(infos.size());
19500a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos                int currentId = ActivityManager.getCurrentUser();
196523c404612c634f6901205fee4f4cae594f62982Fyodor Kupolov                boolean canSwitchUsers = mUserManager.canSwitchUsers();
1977cb69df507f5f7956c52a2868a0d6e89aec6dde2Xiaohui Chen                UserInfo currentUserInfo = null;
19800a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos                UserRecord guestRecord = null;
19900a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos
20000a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos                for (UserInfo info : infos) {
20100a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos                    boolean isCurrent = currentId == info.id;
2027cb69df507f5f7956c52a2868a0d6e89aec6dde2Xiaohui Chen                    if (isCurrent) {
2037cb69df507f5f7956c52a2868a0d6e89aec6dde2Xiaohui Chen                        currentUserInfo = info;
2047cb69df507f5f7956c52a2868a0d6e89aec6dde2Xiaohui Chen                    }
205523c404612c634f6901205fee4f4cae594f62982Fyodor Kupolov                    boolean switchToEnabled = canSwitchUsers || isCurrent;
2061ddda4793c26fd249590fd3549cf060ecb7c157bLenka Trochtova                    if (info.isEnabled()) {
2071ddda4793c26fd249590fd3549cf060ecb7c157bLenka Trochtova                        if (info.isGuest()) {
208523c404612c634f6901205fee4f4cae594f62982Fyodor Kupolov                            // Tapping guest icon triggers remove and a user switch therefore
209523c404612c634f6901205fee4f4cae594f62982Fyodor Kupolov                            // the icon shouldn't be enabled even if the user is current
2101ddda4793c26fd249590fd3549cf060ecb7c157bLenka Trochtova                            guestRecord = new UserRecord(info, null /* picture */,
2111ddda4793c26fd249590fd3549cf060ecb7c157bLenka Trochtova                                    true /* isGuest */, isCurrent, false /* isAddUser */,
212523c404612c634f6901205fee4f4cae594f62982Fyodor Kupolov                                    false /* isRestricted */, canSwitchUsers);
2131ddda4793c26fd249590fd3549cf060ecb7c157bLenka Trochtova                        } else if (info.supportsSwitchToByUser()) {
2141ddda4793c26fd249590fd3549cf060ecb7c157bLenka Trochtova                            Bitmap picture = bitmaps.get(info.id);
2151ddda4793c26fd249590fd3549cf060ecb7c157bLenka Trochtova                            if (picture == null) {
2161ddda4793c26fd249590fd3549cf060ecb7c157bLenka Trochtova                                picture = mUserManager.getUserIcon(info.id);
2171ddda4793c26fd249590fd3549cf060ecb7c157bLenka Trochtova
2181ddda4793c26fd249590fd3549cf060ecb7c157bLenka Trochtova                                if (picture != null) {
219aa7f51fe8c6e54485f0b5037c17777b4695d19e0Evan Rosky                                    int avatarSize = mContext.getResources()
220aa7f51fe8c6e54485f0b5037c17777b4695d19e0Evan Rosky                                            .getDimensionPixelSize(R.dimen.max_avatar_size);
221aa7f51fe8c6e54485f0b5037c17777b4695d19e0Evan Rosky                                    picture = Bitmap.createScaledBitmap(
222aa7f51fe8c6e54485f0b5037c17777b4695d19e0Evan Rosky                                            picture, avatarSize, avatarSize, true);
2231ddda4793c26fd249590fd3549cf060ecb7c157bLenka Trochtova                                }
224cba0faadbe1c8cf7c6b264b761d747f7381a2f93Adrian Roos                            }
2251ddda4793c26fd249590fd3549cf060ecb7c157bLenka Trochtova                            int index = isCurrent ? 0 : records.size();
2261ddda4793c26fd249590fd3549cf060ecb7c157bLenka Trochtova                            records.add(index, new UserRecord(info, picture, false /* isGuest */,
2271ddda4793c26fd249590fd3549cf060ecb7c157bLenka Trochtova                                    isCurrent, false /* isAddUser */, false /* isRestricted */,
2281ddda4793c26fd249590fd3549cf060ecb7c157bLenka Trochtova                                    switchToEnabled));
2294d75c079f35d85b687d8349e5e2940447d01198eDan Sandler                        }
23000a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos                    }
23100a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos                }
23200a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos
233a8fbbb30eae03b9ed7a3e6ea78da13480a53b73dSudheer Shanka                boolean systemCanCreateUsers = !mUserManager.hasBaseUserRestriction(
234a8fbbb30eae03b9ed7a3e6ea78da13480a53b73dSudheer Shanka                                UserManager.DISALLOW_ADD_USER, UserHandle.SYSTEM);
2357cb69df507f5f7956c52a2868a0d6e89aec6dde2Xiaohui Chen                boolean currentUserCanCreateUsers = currentUserInfo != null
2367cb69df507f5f7956c52a2868a0d6e89aec6dde2Xiaohui Chen                        && (currentUserInfo.isAdmin()
237a8fbbb30eae03b9ed7a3e6ea78da13480a53b73dSudheer Shanka                                || currentUserInfo.id == UserHandle.USER_SYSTEM)
238a8fbbb30eae03b9ed7a3e6ea78da13480a53b73dSudheer Shanka                        && systemCanCreateUsers;
239a8fbbb30eae03b9ed7a3e6ea78da13480a53b73dSudheer Shanka                boolean anyoneCanCreateUsers = systemCanCreateUsers && addUsersWhenLocked;
240a8fbbb30eae03b9ed7a3e6ea78da13480a53b73dSudheer Shanka                boolean canCreateGuest = (currentUserCanCreateUsers || anyoneCanCreateUsers)
241ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos                        && guestRecord == null;
242a8fbbb30eae03b9ed7a3e6ea78da13480a53b73dSudheer Shanka                boolean canCreateUser = (currentUserCanCreateUsers || anyoneCanCreateUsers)
24395ab7849444125387dc88088bb5197ee463d8c17Amith Yamasani                        && mUserManager.canAddMoreUsers();
244ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos                boolean createIsRestricted = !addUsersWhenLocked;
245ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos
2462daf62ce400fe58c7f0495dda432ba568a75f579Jason Monk                if (!mSimpleUserSwitcher) {
2472daf62ce400fe58c7f0495dda432ba568a75f579Jason Monk                    if (guestRecord == null) {
248ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos                        if (canCreateGuest) {
2491c7cda8bbfb848961536a4adbf2c81c5ffddae16Sudheer Shanka                            guestRecord = new UserRecord(null /* info */, null /* picture */,
250ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos                                    true /* isGuest */, false /* isCurrent */,
251523c404612c634f6901205fee4f4cae594f62982Fyodor Kupolov                                    false /* isAddUser */, createIsRestricted, canSwitchUsers);
252a8fbbb30eae03b9ed7a3e6ea78da13480a53b73dSudheer Shanka                            checkIfAddUserDisallowedByAdminOnly(guestRecord);
2531c7cda8bbfb848961536a4adbf2c81c5ffddae16Sudheer Shanka                            records.add(guestRecord);
254ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos                        }
2552daf62ce400fe58c7f0495dda432ba568a75f579Jason Monk                    } else {
256bed6e3bedc8845e8f9cd59ad436d140b0875cb6bAdrian Roos                        int index = guestRecord.isCurrent ? 0 : records.size();
257bed6e3bedc8845e8f9cd59ad436d140b0875cb6bAdrian Roos                        records.add(index, guestRecord);
2582daf62ce400fe58c7f0495dda432ba568a75f579Jason Monk                    }
25900a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos                }
26000a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos
261092be7de024b8b1a050ad247a016febc795546afJason Monk                if (!mSimpleUserSwitcher && canCreateUser) {
2621c7cda8bbfb848961536a4adbf2c81c5ffddae16Sudheer Shanka                    UserRecord addUserRecord = new UserRecord(null /* info */, null /* picture */,
263ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos                            false /* isGuest */, false /* isCurrent */, true /* isAddUser */,
264523c404612c634f6901205fee4f4cae594f62982Fyodor Kupolov                            createIsRestricted, canSwitchUsers);
265a8fbbb30eae03b9ed7a3e6ea78da13480a53b73dSudheer Shanka                    checkIfAddUserDisallowedByAdminOnly(addUserRecord);
2661c7cda8bbfb848961536a4adbf2c81c5ffddae16Sudheer Shanka                    records.add(addUserRecord);
267ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos                }
268ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos
26900a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos                return records;
27000a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos            }
27100a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos
27200a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos            @Override
27300a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos            protected void onPostExecute(ArrayList<UserRecord> userRecords) {
27400a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos                if (userRecords != null) {
27500a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos                    mUsers = userRecords;
27600a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos                    notifyAdapters();
27700a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos                }
27800a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos            }
279ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos        }.execute((SparseArray) bitmaps);
28000a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos    }
28100a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos
28288b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos    private void pauseRefreshUsers() {
28388b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos        if (!mPauseRefreshUsers) {
28488b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos            mHandler.postDelayed(mUnpauseRefreshUsers, PAUSE_REFRESH_USERS_TIMEOUT_MS);
28588b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos            mPauseRefreshUsers = true;
28688b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos        }
28788b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos    }
28888b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos
28900a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos    private void notifyAdapters() {
29000a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        for (int i = mAdapters.size() - 1; i >= 0; i--) {
29100a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos            BaseUserAdapter adapter = mAdapters.get(i).get();
29200a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos            if (adapter != null) {
29300a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos                adapter.notifyDataSetChanged();
29400a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos            } else {
29500a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos                mAdapters.remove(i);
29600a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos            }
29700a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        }
29800a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos    }
29900a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos
3002daf62ce400fe58c7f0495dda432ba568a75f579Jason Monk    public boolean isSimpleUserSwitcher() {
3012daf62ce400fe58c7f0495dda432ba568a75f579Jason Monk        return mSimpleUserSwitcher;
3022daf62ce400fe58c7f0495dda432ba568a75f579Jason Monk    }
3032daf62ce400fe58c7f0495dda432ba568a75f579Jason Monk
304cc3a74f6ef13ca9a783845e7a04ca6561035c98bXiyuan Xia    public boolean useFullscreenUserSwitcher() {
305cc3a74f6ef13ca9a783845e7a04ca6561035c98bXiyuan Xia        // Use adb to override:
306cc3a74f6ef13ca9a783845e7a04ca6561035c98bXiyuan Xia        // adb shell settings put system enable_fullscreen_user_switcher 0  # Turn it off.
307cc3a74f6ef13ca9a783845e7a04ca6561035c98bXiyuan Xia        // adb shell settings put system enable_fullscreen_user_switcher 1  # Turn it on.
308cc3a74f6ef13ca9a783845e7a04ca6561035c98bXiyuan Xia        // Restart SystemUI or adb reboot.
309cc3a74f6ef13ca9a783845e7a04ca6561035c98bXiyuan Xia        final int DEFAULT = -1;
310cc3a74f6ef13ca9a783845e7a04ca6561035c98bXiyuan Xia        final int overrideUseFullscreenUserSwitcher =
311cc3a74f6ef13ca9a783845e7a04ca6561035c98bXiyuan Xia                Settings.System.getInt(mContext.getContentResolver(),
312cc3a74f6ef13ca9a783845e7a04ca6561035c98bXiyuan Xia                        "enable_fullscreen_user_switcher", DEFAULT);
313cc3a74f6ef13ca9a783845e7a04ca6561035c98bXiyuan Xia        if (overrideUseFullscreenUserSwitcher != DEFAULT) {
314cc3a74f6ef13ca9a783845e7a04ca6561035c98bXiyuan Xia            return overrideUseFullscreenUserSwitcher != 0;
315cc3a74f6ef13ca9a783845e7a04ca6561035c98bXiyuan Xia        }
316cc3a74f6ef13ca9a783845e7a04ca6561035c98bXiyuan Xia        // Otherwise default to the build setting.
31740f9dabaa880eaff54099a3763224b241a6668e6Xiyuan Xia        return mContext.getResources().getBoolean(R.bool.config_enableFullscreenUserSwitcher);
318cc3a74f6ef13ca9a783845e7a04ca6561035c98bXiyuan Xia    }
319cc3a74f6ef13ca9a783845e7a04ca6561035c98bXiyuan Xia
3201b30f79cffbe9e0c2b974fa3ee48001edcdd6c05Xiyuan Xia    public void logoutCurrentUser() {
3211b30f79cffbe9e0c2b974fa3ee48001edcdd6c05Xiyuan Xia        int currentUser = ActivityManager.getCurrentUser();
3221b30f79cffbe9e0c2b974fa3ee48001edcdd6c05Xiyuan Xia        if (currentUser != UserHandle.USER_SYSTEM) {
323b5690bc3086af1d1f064a080c728090de24d6f96Fyodor Kupolov            pauseRefreshUsers();
324b5690bc3086af1d1f064a080c728090de24d6f96Fyodor Kupolov            ActivityManager.logoutCurrentUser();
3251b30f79cffbe9e0c2b974fa3ee48001edcdd6c05Xiyuan Xia        }
3261b30f79cffbe9e0c2b974fa3ee48001edcdd6c05Xiyuan Xia    }
3271b30f79cffbe9e0c2b974fa3ee48001edcdd6c05Xiyuan Xia
328cc3a74f6ef13ca9a783845e7a04ca6561035c98bXiyuan Xia    public void removeUserId(int userId) {
329cc3a74f6ef13ca9a783845e7a04ca6561035c98bXiyuan Xia        if (userId == UserHandle.USER_SYSTEM) {
330cc3a74f6ef13ca9a783845e7a04ca6561035c98bXiyuan Xia            Log.w(TAG, "User " + userId + " could not removed.");
331cc3a74f6ef13ca9a783845e7a04ca6561035c98bXiyuan Xia            return;
332cc3a74f6ef13ca9a783845e7a04ca6561035c98bXiyuan Xia        }
333cc3a74f6ef13ca9a783845e7a04ca6561035c98bXiyuan Xia        if (ActivityManager.getCurrentUser() == userId) {
334cc3a74f6ef13ca9a783845e7a04ca6561035c98bXiyuan Xia            switchToUserId(UserHandle.USER_SYSTEM);
335cc3a74f6ef13ca9a783845e7a04ca6561035c98bXiyuan Xia        }
336cc3a74f6ef13ca9a783845e7a04ca6561035c98bXiyuan Xia        if (mUserManager.removeUser(userId)) {
337cc3a74f6ef13ca9a783845e7a04ca6561035c98bXiyuan Xia            refreshUsers(UserHandle.USER_NULL);
338cc3a74f6ef13ca9a783845e7a04ca6561035c98bXiyuan Xia        }
339cc3a74f6ef13ca9a783845e7a04ca6561035c98bXiyuan Xia    }
340cc3a74f6ef13ca9a783845e7a04ca6561035c98bXiyuan Xia
34100a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos    public void switchTo(UserRecord record) {
34200a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        int id;
34300a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        if (record.isGuest && record.info == null) {
34400a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos            // No guest user. Create one.
345f99727cb878f9709f6c0263c0283257decbaebadAdrian Roos            UserInfo guest = mUserManager.createGuest(
346f99727cb878f9709f6c0263c0283257decbaebadAdrian Roos                    mContext, mContext.getString(R.string.guest_nickname));
347f99727cb878f9709f6c0263c0283257decbaebadAdrian Roos            if (guest == null) {
348f99727cb878f9709f6c0263c0283257decbaebadAdrian Roos                // Couldn't create guest, most likely because there already exists one, we just
349f99727cb878f9709f6c0263c0283257decbaebadAdrian Roos                // haven't reloaded the user list yet.
350f99727cb878f9709f6c0263c0283257decbaebadAdrian Roos                return;
351f99727cb878f9709f6c0263c0283257decbaebadAdrian Roos            }
352f99727cb878f9709f6c0263c0283257decbaebadAdrian Roos            id = guest.id;
353ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos        } else if (record.isAddUser) {
3540c6763a19f32f73f8a940aaee7abecb2a04d1889Adrian Roos            showAddUserDialog();
3550c6763a19f32f73f8a940aaee7abecb2a04d1889Adrian Roos            return;
35600a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        } else {
35700a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos            id = record.info.id;
35800a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        }
35900a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos
36000a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        if (ActivityManager.getCurrentUser() == id) {
361e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos            if (record.isGuest) {
3625005244f10442e75c1f48973fdddce5facf3f360Adrian Roos                showExitGuestDialog(id);
363e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos            }
36400a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos            return;
36500a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        }
36600a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos
367e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos        switchToUserId(id);
368e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos    }
369e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos
370caab2666bd8dbf1e499c309a62f4dff0056d2948Fyodor Kupolov    public void switchTo(int userId) {
371caab2666bd8dbf1e499c309a62f4dff0056d2948Fyodor Kupolov        final int count = mUsers.size();
372caab2666bd8dbf1e499c309a62f4dff0056d2948Fyodor Kupolov        for (int i = 0; i < count; ++i) {
373caab2666bd8dbf1e499c309a62f4dff0056d2948Fyodor Kupolov            UserRecord record = mUsers.get(i);
374caab2666bd8dbf1e499c309a62f4dff0056d2948Fyodor Kupolov            if (record.info != null && record.info.id == userId) {
375caab2666bd8dbf1e499c309a62f4dff0056d2948Fyodor Kupolov                switchTo(record);
376caab2666bd8dbf1e499c309a62f4dff0056d2948Fyodor Kupolov                return;
377caab2666bd8dbf1e499c309a62f4dff0056d2948Fyodor Kupolov            }
378caab2666bd8dbf1e499c309a62f4dff0056d2948Fyodor Kupolov        }
379caab2666bd8dbf1e499c309a62f4dff0056d2948Fyodor Kupolov
380caab2666bd8dbf1e499c309a62f4dff0056d2948Fyodor Kupolov        Log.e(TAG, "Couldn't switch to user, id=" + userId);
381caab2666bd8dbf1e499c309a62f4dff0056d2948Fyodor Kupolov    }
382caab2666bd8dbf1e499c309a62f4dff0056d2948Fyodor Kupolov
3838ba446c9bad94e91cf83c579261298552d51d249Daniel Nishi    public int getSwitchableUserCount() {
3848ba446c9bad94e91cf83c579261298552d51d249Daniel Nishi        int count = 0;
3858ba446c9bad94e91cf83c579261298552d51d249Daniel Nishi        final int N = mUsers.size();
3868ba446c9bad94e91cf83c579261298552d51d249Daniel Nishi        for (int i = 0; i < N; ++i) {
3878ba446c9bad94e91cf83c579261298552d51d249Daniel Nishi            UserRecord record = mUsers.get(i);
3888ba446c9bad94e91cf83c579261298552d51d249Daniel Nishi            if (record.info != null && record.info.supportsSwitchTo()) {
3898ba446c9bad94e91cf83c579261298552d51d249Daniel Nishi                count++;
3908ba446c9bad94e91cf83c579261298552d51d249Daniel Nishi            }
3918ba446c9bad94e91cf83c579261298552d51d249Daniel Nishi        }
3928ba446c9bad94e91cf83c579261298552d51d249Daniel Nishi        return count;
3938ba446c9bad94e91cf83c579261298552d51d249Daniel Nishi    }
3948ba446c9bad94e91cf83c579261298552d51d249Daniel Nishi
395e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos    private void switchToUserId(int id) {
39600a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        try {
39788b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos            pauseRefreshUsers();
39800a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos            ActivityManagerNative.getDefault().switchUser(id);
39900a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        } catch (RemoteException e) {
40000a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos            Log.e(TAG, "Couldn't switch user.", e);
40100a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        }
40200a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos    }
40300a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos
4045005244f10442e75c1f48973fdddce5facf3f360Adrian Roos    private void showExitGuestDialog(int id) {
4055005244f10442e75c1f48973fdddce5facf3f360Adrian Roos        if (mExitGuestDialog != null && mExitGuestDialog.isShowing()) {
4065005244f10442e75c1f48973fdddce5facf3f360Adrian Roos            mExitGuestDialog.cancel();
4075005244f10442e75c1f48973fdddce5facf3f360Adrian Roos        }
4085005244f10442e75c1f48973fdddce5facf3f360Adrian Roos        mExitGuestDialog = new ExitGuestDialog(mContext, id);
4095005244f10442e75c1f48973fdddce5facf3f360Adrian Roos        mExitGuestDialog.show();
4105005244f10442e75c1f48973fdddce5facf3f360Adrian Roos    }
4115005244f10442e75c1f48973fdddce5facf3f360Adrian Roos
4120c6763a19f32f73f8a940aaee7abecb2a04d1889Adrian Roos    private void showAddUserDialog() {
4130c6763a19f32f73f8a940aaee7abecb2a04d1889Adrian Roos        if (mAddUserDialog != null && mAddUserDialog.isShowing()) {
4140c6763a19f32f73f8a940aaee7abecb2a04d1889Adrian Roos            mAddUserDialog.cancel();
4150c6763a19f32f73f8a940aaee7abecb2a04d1889Adrian Roos        }
4160c6763a19f32f73f8a940aaee7abecb2a04d1889Adrian Roos        mAddUserDialog = new AddUserDialog(mContext);
4170c6763a19f32f73f8a940aaee7abecb2a04d1889Adrian Roos        mAddUserDialog.show();
4180c6763a19f32f73f8a940aaee7abecb2a04d1889Adrian Roos    }
4190c6763a19f32f73f8a940aaee7abecb2a04d1889Adrian Roos
420e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos    private void exitGuest(int id) {
4217cb69df507f5f7956c52a2868a0d6e89aec6dde2Xiaohui Chen        int newId = UserHandle.USER_SYSTEM;
4227cb69df507f5f7956c52a2868a0d6e89aec6dde2Xiaohui Chen        if (mLastNonGuestUser != UserHandle.USER_SYSTEM) {
42370441467f4dc232cd8e6142f0afc117787dc979bAdrian Roos            UserInfo info = mUserManager.getUserInfo(mLastNonGuestUser);
4247cb69df507f5f7956c52a2868a0d6e89aec6dde2Xiaohui Chen            if (info != null && info.isEnabled() && info.supportsSwitchToByUser()) {
42570441467f4dc232cd8e6142f0afc117787dc979bAdrian Roos                newId = info.id;
42670441467f4dc232cd8e6142f0afc117787dc979bAdrian Roos            }
42770441467f4dc232cd8e6142f0afc117787dc979bAdrian Roos        }
42870441467f4dc232cd8e6142f0afc117787dc979bAdrian Roos        switchToUserId(newId);
429e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos        mUserManager.removeUser(id);
430e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos    }
431e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos
432523c404612c634f6901205fee4f4cae594f62982Fyodor Kupolov    private void listenForCallState() {
433705a4bc62341d70a9b75b28f68c64efc88321438Jason Monk        TelephonyManager.from(mContext).listen(mPhoneStateListener,
434705a4bc62341d70a9b75b28f68c64efc88321438Jason Monk                PhoneStateListener.LISTEN_CALL_STATE);
435523c404612c634f6901205fee4f4cae594f62982Fyodor Kupolov    }
436523c404612c634f6901205fee4f4cae594f62982Fyodor Kupolov
437705a4bc62341d70a9b75b28f68c64efc88321438Jason Monk    private final PhoneStateListener mPhoneStateListener = new PhoneStateListener() {
438705a4bc62341d70a9b75b28f68c64efc88321438Jason Monk        private int mCallState;
439705a4bc62341d70a9b75b28f68c64efc88321438Jason Monk
440705a4bc62341d70a9b75b28f68c64efc88321438Jason Monk        @Override
441705a4bc62341d70a9b75b28f68c64efc88321438Jason Monk        public void onCallStateChanged(int state, String incomingNumber) {
442705a4bc62341d70a9b75b28f68c64efc88321438Jason Monk            if (mCallState == state) return;
443705a4bc62341d70a9b75b28f68c64efc88321438Jason Monk            if (DEBUG) Log.v(TAG, "Call state changed: " + state);
444705a4bc62341d70a9b75b28f68c64efc88321438Jason Monk            mCallState = state;
445705a4bc62341d70a9b75b28f68c64efc88321438Jason Monk            int currentUserId = ActivityManager.getCurrentUser();
446705a4bc62341d70a9b75b28f68c64efc88321438Jason Monk            UserInfo userInfo = mUserManager.getUserInfo(currentUserId);
447705a4bc62341d70a9b75b28f68c64efc88321438Jason Monk            if (userInfo != null && userInfo.isGuest()) {
448705a4bc62341d70a9b75b28f68c64efc88321438Jason Monk                showGuestNotification(currentUserId);
449705a4bc62341d70a9b75b28f68c64efc88321438Jason Monk            }
450705a4bc62341d70a9b75b28f68c64efc88321438Jason Monk            refreshUsers(UserHandle.USER_NULL);
451705a4bc62341d70a9b75b28f68c64efc88321438Jason Monk        }
452705a4bc62341d70a9b75b28f68c64efc88321438Jason Monk    };
453705a4bc62341d70a9b75b28f68c64efc88321438Jason Monk
45400a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos    private BroadcastReceiver mReceiver = new BroadcastReceiver() {
45500a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        @Override
45600a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        public void onReceive(Context context, Intent intent) {
4575005244f10442e75c1f48973fdddce5facf3f360Adrian Roos            if (DEBUG) {
4585005244f10442e75c1f48973fdddce5facf3f360Adrian Roos                Log.v(TAG, "Broadcast: a=" + intent.getAction()
4595005244f10442e75c1f48973fdddce5facf3f360Adrian Roos                       + " user=" + intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1));
4605005244f10442e75c1f48973fdddce5facf3f360Adrian Roos            }
46188b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos
46288b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos            boolean unpauseRefreshUsers = false;
46388b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos            int forcePictureLoadForId = UserHandle.USER_NULL;
46488b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos
465f4d6ad26636760163083ae84c40d5b19cb6650f6Fyodor Kupolov            if (ACTION_REMOVE_GUEST.equals(intent.getAction())) {
466f4d6ad26636760163083ae84c40d5b19cb6650f6Fyodor Kupolov                int currentUser = ActivityManager.getCurrentUser();
467f4d6ad26636760163083ae84c40d5b19cb6650f6Fyodor Kupolov                UserInfo userInfo = mUserManager.getUserInfo(currentUser);
468f4d6ad26636760163083ae84c40d5b19cb6650f6Fyodor Kupolov                if (userInfo != null && userInfo.isGuest()) {
469f4d6ad26636760163083ae84c40d5b19cb6650f6Fyodor Kupolov                    showExitGuestDialog(currentUser);
470f4d6ad26636760163083ae84c40d5b19cb6650f6Fyodor Kupolov                }
471f4d6ad26636760163083ae84c40d5b19cb6650f6Fyodor Kupolov                return;
47280996bbf40ff192117c391074ed2f9b2cde4e69aAdrian Roos            } else if (ACTION_LOGOUT_USER.equals(intent.getAction())) {
4731b30f79cffbe9e0c2b974fa3ee48001edcdd6c05Xiyuan Xia                logoutCurrentUser();
47488b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos            } else if (Intent.ACTION_USER_SWITCHED.equals(intent.getAction())) {
4755005244f10442e75c1f48973fdddce5facf3f360Adrian Roos                if (mExitGuestDialog != null && mExitGuestDialog.isShowing()) {
4765005244f10442e75c1f48973fdddce5facf3f360Adrian Roos                    mExitGuestDialog.cancel();
4775005244f10442e75c1f48973fdddce5facf3f360Adrian Roos                    mExitGuestDialog = null;
4785005244f10442e75c1f48973fdddce5facf3f360Adrian Roos                }
4795005244f10442e75c1f48973fdddce5facf3f360Adrian Roos
48000a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos                final int currentId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
4817cb69df507f5f7956c52a2868a0d6e89aec6dde2Xiaohui Chen                final UserInfo userInfo = mUserManager.getUserInfo(currentId);
48200a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos                final int N = mUsers.size();
48300a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos                for (int i = 0; i < N; i++) {
48400a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos                    UserRecord record = mUsers.get(i);
485e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos                    if (record.info == null) continue;
48600a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos                    boolean shouldBeCurrent = record.info.id == currentId;
48700a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos                    if (record.isCurrent != shouldBeCurrent) {
48800a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos                        mUsers.set(i, record.copyWithIsCurrent(shouldBeCurrent));
48900a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos                    }
49070441467f4dc232cd8e6142f0afc117787dc979bAdrian Roos                    if (shouldBeCurrent && !record.isGuest) {
49170441467f4dc232cd8e6142f0afc117787dc979bAdrian Roos                        mLastNonGuestUser = record.info.id;
49270441467f4dc232cd8e6142f0afc117787dc979bAdrian Roos                    }
4937cb69df507f5f7956c52a2868a0d6e89aec6dde2Xiaohui Chen                    if ((userInfo == null || !userInfo.isAdmin()) && record.isRestricted) {
494ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos                        // Immediately remove restricted records in case the AsyncTask is too slow.
495ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos                        mUsers.remove(i);
496ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos                        i--;
497ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos                    }
49800a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos                }
49900a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos                notifyAdapters();
500860397f6521249f1e2733e65ccebe0c0e781b82aXiaohui Chen
5013c2c34bb039e92d68f466b7d194cbbe8241d8d60Winson                // Disconnect from the old secondary user's service
5023c2c34bb039e92d68f466b7d194cbbe8241d8d60Winson                if (mSecondaryUser != UserHandle.USER_NULL) {
5033c2c34bb039e92d68f466b7d194cbbe8241d8d60Winson                    context.stopServiceAsUser(mSecondaryUserServiceIntent,
5043c2c34bb039e92d68f466b7d194cbbe8241d8d60Winson                            UserHandle.of(mSecondaryUser));
5053c2c34bb039e92d68f466b7d194cbbe8241d8d60Winson                    mSecondaryUser = UserHandle.USER_NULL;
5063c2c34bb039e92d68f466b7d194cbbe8241d8d60Winson                }
5073c2c34bb039e92d68f466b7d194cbbe8241d8d60Winson                // Connect to the new secondary user's service (purely to ensure that a persistent
5083c2c34bb039e92d68f466b7d194cbbe8241d8d60Winson                // SystemUI application is created for that user)
5093c2c34bb039e92d68f466b7d194cbbe8241d8d60Winson                if (userInfo != null && !userInfo.isPrimary()) {
5103c2c34bb039e92d68f466b7d194cbbe8241d8d60Winson                    context.startServiceAsUser(mSecondaryUserServiceIntent,
5113c2c34bb039e92d68f466b7d194cbbe8241d8d60Winson                            UserHandle.of(userInfo.id));
5123c2c34bb039e92d68f466b7d194cbbe8241d8d60Winson                    mSecondaryUser = userInfo.id;
5133c2c34bb039e92d68f466b7d194cbbe8241d8d60Winson                }
5143c2c34bb039e92d68f466b7d194cbbe8241d8d60Winson
515860397f6521249f1e2733e65ccebe0c0e781b82aXiaohui Chen                if (UserManager.isSplitSystemUser() && userInfo != null && !userInfo.isGuest()
516860397f6521249f1e2733e65ccebe0c0e781b82aXiaohui Chen                        && userInfo.id != UserHandle.USER_SYSTEM) {
517860397f6521249f1e2733e65ccebe0c0e781b82aXiaohui Chen                    showLogoutNotification(currentId);
518860397f6521249f1e2733e65ccebe0c0e781b82aXiaohui Chen                }
519ce161861c3507c91c25b2491abac1e7611d14c5cFyodor Kupolov                if (userInfo != null && userInfo.isGuest()) {
520ce161861c3507c91c25b2491abac1e7611d14c5cFyodor Kupolov                    showGuestNotification(currentId);
521ce161861c3507c91c25b2491abac1e7611d14c5cFyodor Kupolov                }
52288b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos                unpauseRefreshUsers = true;
52388b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos            } else if (Intent.ACTION_USER_INFO_CHANGED.equals(intent.getAction())) {
524e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos                forcePictureLoadForId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE,
525e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos                        UserHandle.USER_NULL);
52607140f7ffd56bf9d4946eba4e48b21a748125659Fyodor Kupolov            } else if (Intent.ACTION_USER_UNLOCKED.equals(intent.getAction())) {
52707140f7ffd56bf9d4946eba4e48b21a748125659Fyodor Kupolov                // Unlocking the system user may require a refresh
52807140f7ffd56bf9d4946eba4e48b21a748125659Fyodor Kupolov                int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL);
52907140f7ffd56bf9d4946eba4e48b21a748125659Fyodor Kupolov                if (userId != UserHandle.USER_SYSTEM) {
53007140f7ffd56bf9d4946eba4e48b21a748125659Fyodor Kupolov                    return;
53107140f7ffd56bf9d4946eba4e48b21a748125659Fyodor Kupolov                }
532e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos            }
533e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos            refreshUsers(forcePictureLoadForId);
53488b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos            if (unpauseRefreshUsers) {
53588b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos                mUnpauseRefreshUsers.run();
53688b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos            }
53700a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        }
538f4d6ad26636760163083ae84c40d5b19cb6650f6Fyodor Kupolov
539860397f6521249f1e2733e65ccebe0c0e781b82aXiaohui Chen        private void showLogoutNotification(int userId) {
540860397f6521249f1e2733e65ccebe0c0e781b82aXiaohui Chen            PendingIntent logoutPI = PendingIntent.getBroadcastAsUser(mContext,
541860397f6521249f1e2733e65ccebe0c0e781b82aXiaohui Chen                    0, new Intent(ACTION_LOGOUT_USER), 0, UserHandle.SYSTEM);
542e25c18da7d2cc3e02620dadfcb976521821bc9d8Adrian Roos            Notification.Builder builder = new Notification.Builder(mContext)
543860397f6521249f1e2733e65ccebe0c0e781b82aXiaohui Chen                    .setVisibility(Notification.VISIBILITY_SECRET)
544860397f6521249f1e2733e65ccebe0c0e781b82aXiaohui Chen                    .setPriority(Notification.PRIORITY_MIN)
545860397f6521249f1e2733e65ccebe0c0e781b82aXiaohui Chen                    .setSmallIcon(R.drawable.ic_person)
546860397f6521249f1e2733e65ccebe0c0e781b82aXiaohui Chen                    .setContentTitle(mContext.getString(R.string.user_logout_notification_title))
547860397f6521249f1e2733e65ccebe0c0e781b82aXiaohui Chen                    .setContentText(mContext.getString(R.string.user_logout_notification_text))
54852408f4fb5dab950847aa12e3bea44399ccd0d6eFyodor Kupolov                    .setContentIntent(logoutPI)
549ce161861c3507c91c25b2491abac1e7611d14c5cFyodor Kupolov                    .setOngoing(true)
550860397f6521249f1e2733e65ccebe0c0e781b82aXiaohui Chen                    .setShowWhen(false)
551860397f6521249f1e2733e65ccebe0c0e781b82aXiaohui Chen                    .addAction(R.drawable.ic_delete,
552860397f6521249f1e2733e65ccebe0c0e781b82aXiaohui Chen                            mContext.getString(R.string.user_logout_notification_action),
553e25c18da7d2cc3e02620dadfcb976521821bc9d8Adrian Roos                            logoutPI);
554e25c18da7d2cc3e02620dadfcb976521821bc9d8Adrian Roos            SystemUI.overrideNotificationAppName(mContext, builder);
555117d5b4f28bbaf1b7458233ae5e101b9c41d7b64Chris Wren            NotificationManager.from(mContext).notifyAsUser(TAG_LOGOUT_USER,
556117d5b4f28bbaf1b7458233ae5e101b9c41d7b64Chris Wren                    SystemMessage.NOTE_LOGOUT_USER, builder.build(), new UserHandle(userId));
557860397f6521249f1e2733e65ccebe0c0e781b82aXiaohui Chen        }
55800a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos    };
55900a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos
560523c404612c634f6901205fee4f4cae594f62982Fyodor Kupolov    private void showGuestNotification(int guestUserId) {
561523c404612c634f6901205fee4f4cae594f62982Fyodor Kupolov        boolean canSwitchUsers = mUserManager.canSwitchUsers();
562523c404612c634f6901205fee4f4cae594f62982Fyodor Kupolov        // Disable 'Remove guest' action if cannot switch users right now
563523c404612c634f6901205fee4f4cae594f62982Fyodor Kupolov        PendingIntent removeGuestPI = canSwitchUsers ? PendingIntent.getBroadcastAsUser(mContext,
564523c404612c634f6901205fee4f4cae594f62982Fyodor Kupolov                0, new Intent(ACTION_REMOVE_GUEST), 0, UserHandle.SYSTEM) : null;
565523c404612c634f6901205fee4f4cae594f62982Fyodor Kupolov
566e25c18da7d2cc3e02620dadfcb976521821bc9d8Adrian Roos        Notification.Builder builder = new Notification.Builder(mContext)
567523c404612c634f6901205fee4f4cae594f62982Fyodor Kupolov                .setVisibility(Notification.VISIBILITY_SECRET)
568523c404612c634f6901205fee4f4cae594f62982Fyodor Kupolov                .setPriority(Notification.PRIORITY_MIN)
569523c404612c634f6901205fee4f4cae594f62982Fyodor Kupolov                .setSmallIcon(R.drawable.ic_person)
570523c404612c634f6901205fee4f4cae594f62982Fyodor Kupolov                .setContentTitle(mContext.getString(R.string.guest_notification_title))
571523c404612c634f6901205fee4f4cae594f62982Fyodor Kupolov                .setContentText(mContext.getString(R.string.guest_notification_text))
572523c404612c634f6901205fee4f4cae594f62982Fyodor Kupolov                .setContentIntent(removeGuestPI)
573523c404612c634f6901205fee4f4cae594f62982Fyodor Kupolov                .setShowWhen(false)
574523c404612c634f6901205fee4f4cae594f62982Fyodor Kupolov                .addAction(R.drawable.ic_delete,
575523c404612c634f6901205fee4f4cae594f62982Fyodor Kupolov                        mContext.getString(R.string.guest_notification_remove_action),
576e25c18da7d2cc3e02620dadfcb976521821bc9d8Adrian Roos                        removeGuestPI);
577e25c18da7d2cc3e02620dadfcb976521821bc9d8Adrian Roos        SystemUI.overrideNotificationAppName(mContext, builder);
578117d5b4f28bbaf1b7458233ae5e101b9c41d7b64Chris Wren        NotificationManager.from(mContext).notifyAsUser(TAG_REMOVE_GUEST,
579117d5b4f28bbaf1b7458233ae5e101b9c41d7b64Chris Wren                SystemMessage.NOTE_REMOVE_GUEST, builder.build(), new UserHandle(guestUserId));
580523c404612c634f6901205fee4f4cae594f62982Fyodor Kupolov    }
581523c404612c634f6901205fee4f4cae594f62982Fyodor Kupolov
58288b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos    private final Runnable mUnpauseRefreshUsers = new Runnable() {
58388b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos        @Override
58488b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos        public void run() {
58588b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos            mHandler.removeCallbacks(this);
58688b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos            mPauseRefreshUsers = false;
58788b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos            refreshUsers(UserHandle.USER_NULL);
58888b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos        }
58988b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos    };
59088b1193ea2880683a6a3fdf9a5a397370a166680Adrian Roos
591ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos    private final ContentObserver mSettingsObserver = new ContentObserver(new Handler()) {
5922daf62ce400fe58c7f0495dda432ba568a75f579Jason Monk        public void onChange(boolean selfChange) {
5932daf62ce400fe58c7f0495dda432ba568a75f579Jason Monk            mSimpleUserSwitcher = Settings.Global.getInt(mContext.getContentResolver(),
5942daf62ce400fe58c7f0495dda432ba568a75f579Jason Monk                    SIMPLE_USER_SWITCHER_GLOBAL_SETTING, 0) != 0;
595ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos            mAddUsersWhenLocked = Settings.Global.getInt(mContext.getContentResolver(),
596ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos                    Settings.Global.ADD_USERS_WHEN_LOCKED, 0) != 0;
5972daf62ce400fe58c7f0495dda432ba568a75f579Jason Monk            refreshUsers(UserHandle.USER_NULL);
5982daf62ce400fe58c7f0495dda432ba568a75f579Jason Monk        };
5992daf62ce400fe58c7f0495dda432ba568a75f579Jason Monk    };
6002daf62ce400fe58c7f0495dda432ba568a75f579Jason Monk
60100a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
60200a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        pw.println("UserSwitcherController state:");
60370441467f4dc232cd8e6142f0afc117787dc979bAdrian Roos        pw.println("  mLastNonGuestUser=" + mLastNonGuestUser);
60400a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        pw.print("  mUsers.size="); pw.println(mUsers.size());
60500a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        for (int i = 0; i < mUsers.size(); i++) {
60600a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos            final UserRecord u = mUsers.get(i);
60700a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos            pw.print("    "); pw.println(u.toString());
60800a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        }
60900a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos    }
61000a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos
61157cf5702e0634b8cb25daa8f2f73292428ec4e08Adrian Roos    public String getCurrentUserName(Context context) {
61257cf5702e0634b8cb25daa8f2f73292428ec4e08Adrian Roos        if (mUsers.isEmpty()) return null;
61357cf5702e0634b8cb25daa8f2f73292428ec4e08Adrian Roos        UserRecord item = mUsers.get(0);
61457cf5702e0634b8cb25daa8f2f73292428ec4e08Adrian Roos        if (item == null || item.info == null) return null;
61557cf5702e0634b8cb25daa8f2f73292428ec4e08Adrian Roos        if (item.isGuest) return context.getString(R.string.guest_nickname);
61657cf5702e0634b8cb25daa8f2f73292428ec4e08Adrian Roos        return item.info.name;
61757cf5702e0634b8cb25daa8f2f73292428ec4e08Adrian Roos    }
61857cf5702e0634b8cb25daa8f2f73292428ec4e08Adrian Roos
619d390b893eafae634844d7b8b84efaa7baa199119Adrian Roos    public void onDensityOrFontScaleChanged() {
620d390b893eafae634844d7b8b84efaa7baa199119Adrian Roos        refreshUsers(UserHandle.USER_ALL);
621d390b893eafae634844d7b8b84efaa7baa199119Adrian Roos    }
622d390b893eafae634844d7b8b84efaa7baa199119Adrian Roos
62300a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos    public static abstract class BaseUserAdapter extends BaseAdapter {
62400a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos
62500a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        final UserSwitcherController mController;
62600a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos
62700a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        protected BaseUserAdapter(UserSwitcherController controller) {
62800a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos            mController = controller;
62900a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos            controller.mAdapters.add(new WeakReference<>(this));
63000a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        }
63100a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos
63200a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        @Override
63300a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        public int getCount() {
634ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos            boolean secureKeyguardShowing = mController.mKeyguardMonitor.isShowing()
6358a3a964d0ad13374a4c4ee8a8a1b12aa00e577f0Jason Monk                    && mController.mKeyguardMonitor.isSecure()
636e8bae6288bf0f241f0cea70f2c5e8294f930d4d8Selim Cinek                    && !mController.mKeyguardMonitor.canSkipBouncer();
637ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos            if (!secureKeyguardShowing) {
638ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos                return mController.mUsers.size();
639ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos            }
640ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos            // The lock screen is secure and showing. Filter out restricted records.
641ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos            final int N = mController.mUsers.size();
642ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos            int count = 0;
643ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos            for (int i = 0; i < N; i++) {
644ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos                if (mController.mUsers.get(i).isRestricted) {
645ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos                    break;
646ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos                } else {
647ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos                    count++;
648ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos                }
649ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos            }
650ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos            return count;
65100a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        }
65200a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos
65300a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        @Override
65400a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        public UserRecord getItem(int position) {
65500a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos            return mController.mUsers.get(position);
65600a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        }
65700a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos
65800a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        @Override
65900a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        public long getItemId(int position) {
660e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos            return position;
66100a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        }
66200a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos
66300a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        public void switchTo(UserRecord record) {
66400a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos            mController.switchTo(record);
66500a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        }
666e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos
667e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos        public String getName(Context context, UserRecord item) {
668e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos            if (item.isGuest) {
669e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos                if (item.isCurrent) {
670e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos                    return context.getString(R.string.guest_exit_guest);
671e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos                } else {
672e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos                    return context.getString(
673e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos                            item.info == null ? R.string.guest_new_guest : R.string.guest_nickname);
674e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos                }
675ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos            } else if (item.isAddUser) {
676ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos                return context.getString(R.string.user_add_user);
677e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos            } else {
678e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos                return item.info.name;
679e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos            }
680e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos        }
681723632ea1ae30b33e9c2055194a4464f00c48c61Adrian Roos
682ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos        public Drawable getDrawable(Context context, UserRecord item) {
683ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos            if (item.isAddUser) {
684ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos                return context.getDrawable(R.drawable.ic_add_circle_qs);
685ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos            }
686aa7f51fe8c6e54485f0b5037c17777b4695d19e0Evan Rosky            return UserIcons.getDefaultUserIcon(item.resolveId(), /* light= */ true);
687ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos        }
688844c92b444dca7f5ef4d0943fb14e2cbeee49701Adrian Roos
689844c92b444dca7f5ef4d0943fb14e2cbeee49701Adrian Roos        public void refresh() {
690844c92b444dca7f5ef4d0943fb14e2cbeee49701Adrian Roos            mController.refreshUsers(UserHandle.USER_NULL);
691844c92b444dca7f5ef4d0943fb14e2cbeee49701Adrian Roos        }
69200a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos    }
69300a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos
694a8fbbb30eae03b9ed7a3e6ea78da13480a53b73dSudheer Shanka    private void checkIfAddUserDisallowedByAdminOnly(UserRecord record) {
695ad143c09dfbae2f4bb26be8b2a9425edf0562b46Sudheer Shanka        EnforcedAdmin admin = RestrictedLockUtils.checkIfRestrictionEnforced(mContext,
696ad143c09dfbae2f4bb26be8b2a9425edf0562b46Sudheer Shanka                UserManager.DISALLOW_ADD_USER, ActivityManager.getCurrentUser());
697ad143c09dfbae2f4bb26be8b2a9425edf0562b46Sudheer Shanka        if (admin != null && !RestrictedLockUtils.hasBaseUserRestriction(mContext,
698ad143c09dfbae2f4bb26be8b2a9425edf0562b46Sudheer Shanka                UserManager.DISALLOW_ADD_USER, ActivityManager.getCurrentUser())) {
6991c7cda8bbfb848961536a4adbf2c81c5ffddae16Sudheer Shanka            record.isDisabledByAdmin = true;
700ad143c09dfbae2f4bb26be8b2a9425edf0562b46Sudheer Shanka            record.enforcedAdmin = admin;
7011c7cda8bbfb848961536a4adbf2c81c5ffddae16Sudheer Shanka        } else {
7021c7cda8bbfb848961536a4adbf2c81c5ffddae16Sudheer Shanka            record.isDisabledByAdmin = false;
7031c7cda8bbfb848961536a4adbf2c81c5ffddae16Sudheer Shanka            record.enforcedAdmin = null;
7041c7cda8bbfb848961536a4adbf2c81c5ffddae16Sudheer Shanka        }
7051c7cda8bbfb848961536a4adbf2c81c5ffddae16Sudheer Shanka    }
7061c7cda8bbfb848961536a4adbf2c81c5ffddae16Sudheer Shanka
7071c7cda8bbfb848961536a4adbf2c81c5ffddae16Sudheer Shanka    public void startActivity(Intent intent) {
7081c7cda8bbfb848961536a4adbf2c81c5ffddae16Sudheer Shanka        mActivityStarter.startActivity(intent, true);
7091c7cda8bbfb848961536a4adbf2c81c5ffddae16Sudheer Shanka    }
7101c7cda8bbfb848961536a4adbf2c81c5ffddae16Sudheer Shanka
71100a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos    public static final class UserRecord {
71200a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        public final UserInfo info;
71300a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        public final Bitmap picture;
71400a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        public final boolean isGuest;
71500a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        public final boolean isCurrent;
716ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos        public final boolean isAddUser;
717ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos        /** If true, the record is only visible to the owner and only when unlocked. */
718ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos        public final boolean isRestricted;
7191c7cda8bbfb848961536a4adbf2c81c5ffddae16Sudheer Shanka        public boolean isDisabledByAdmin;
7201c7cda8bbfb848961536a4adbf2c81c5ffddae16Sudheer Shanka        public EnforcedAdmin enforcedAdmin;
72107140f7ffd56bf9d4946eba4e48b21a748125659Fyodor Kupolov        public boolean isSwitchToEnabled;
72200a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos
723ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos        public UserRecord(UserInfo info, Bitmap picture, boolean isGuest, boolean isCurrent,
72407140f7ffd56bf9d4946eba4e48b21a748125659Fyodor Kupolov                boolean isAddUser, boolean isRestricted, boolean isSwitchToEnabled) {
72500a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos            this.info = info;
72600a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos            this.picture = picture;
72700a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos            this.isGuest = isGuest;
72800a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos            this.isCurrent = isCurrent;
729ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos            this.isAddUser = isAddUser;
730ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos            this.isRestricted = isRestricted;
73107140f7ffd56bf9d4946eba4e48b21a748125659Fyodor Kupolov            this.isSwitchToEnabled = isSwitchToEnabled;
73200a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        }
73300a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos
73400a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        public UserRecord copyWithIsCurrent(boolean _isCurrent) {
73507140f7ffd56bf9d4946eba4e48b21a748125659Fyodor Kupolov            return new UserRecord(info, picture, isGuest, _isCurrent, isAddUser, isRestricted,
73607140f7ffd56bf9d4946eba4e48b21a748125659Fyodor Kupolov                    isSwitchToEnabled);
73700a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        }
73800a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos
739aa7f51fe8c6e54485f0b5037c17777b4695d19e0Evan Rosky        public int resolveId() {
740aa7f51fe8c6e54485f0b5037c17777b4695d19e0Evan Rosky            if (isGuest || info == null) {
741aa7f51fe8c6e54485f0b5037c17777b4695d19e0Evan Rosky                return UserHandle.USER_NULL;
742aa7f51fe8c6e54485f0b5037c17777b4695d19e0Evan Rosky            }
743aa7f51fe8c6e54485f0b5037c17777b4695d19e0Evan Rosky            return info.id;
744aa7f51fe8c6e54485f0b5037c17777b4695d19e0Evan Rosky        }
745aa7f51fe8c6e54485f0b5037c17777b4695d19e0Evan Rosky
74600a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        public String toString() {
74700a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos            StringBuilder sb = new StringBuilder();
74800a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos            sb.append("UserRecord(");
74900a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos            if (info != null) {
75007140f7ffd56bf9d4946eba4e48b21a748125659Fyodor Kupolov                sb.append("name=\"").append(info.name).append("\" id=").append(info.id);
75100a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos            } else {
752ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos                if (isGuest) {
753ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos                    sb.append("<add guest placeholder>");
754ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos                } else if (isAddUser) {
755ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos                    sb.append("<add user placeholder>");
756ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos                }
75700a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos            }
758ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos            if (isGuest) sb.append(" <isGuest>");
759ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos            if (isAddUser) sb.append(" <isAddUser>");
760ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos            if (isCurrent) sb.append(" <isCurrent>");
761ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos            if (picture != null) sb.append(" <hasPicture>");
762ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos            if (isRestricted) sb.append(" <isRestricted>");
7631c7cda8bbfb848961536a4adbf2c81c5ffddae16Sudheer Shanka            if (isDisabledByAdmin) {
7641c7cda8bbfb848961536a4adbf2c81c5ffddae16Sudheer Shanka                sb.append(" <isDisabledByAdmin>");
76507140f7ffd56bf9d4946eba4e48b21a748125659Fyodor Kupolov                sb.append(" enforcedAdmin=").append(enforcedAdmin);
76607140f7ffd56bf9d4946eba4e48b21a748125659Fyodor Kupolov            }
76707140f7ffd56bf9d4946eba4e48b21a748125659Fyodor Kupolov            if (isSwitchToEnabled) {
76807140f7ffd56bf9d4946eba4e48b21a748125659Fyodor Kupolov                sb.append(" <isSwitchToEnabled>");
7691c7cda8bbfb848961536a4adbf2c81c5ffddae16Sudheer Shanka            }
77000a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos            sb.append(')');
77100a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos            return sb.toString();
77200a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        }
77300a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos    }
77400a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos
77500a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos    public final QSTile.DetailAdapter userDetailAdapter = new QSTile.DetailAdapter() {
77676c67aa361f65dfb2f5e03d06cc1ccebce9cecd9Jason Monk        private final Intent USER_SETTINGS_INTENT = new Intent(Settings.ACTION_USER_SETTINGS);
77700a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos
77800a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        @Override
779c06fbb12984a3d3e4c80ab9f819841acae5b0133Jason Monk        public CharSequence getTitle() {
780c06fbb12984a3d3e4c80ab9f819841acae5b0133Jason Monk            return mContext.getString(R.string.quick_settings_user_title);
78100a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        }
78200a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos
78300a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        @Override
78400a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        public View createDetailView(Context context, View convertView, ViewGroup parent) {
7851940892d891c1d2538f51608b6618af646ab7481Adrian Roos            UserDetailView v;
78600a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos            if (!(convertView instanceof UserDetailView)) {
7871940892d891c1d2538f51608b6618af646ab7481Adrian Roos                v = UserDetailView.inflate(context, parent, false);
78800a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos                v.createAndSetAdapter(UserSwitcherController.this);
7891940892d891c1d2538f51608b6618af646ab7481Adrian Roos            } else {
7901940892d891c1d2538f51608b6618af646ab7481Adrian Roos                v = (UserDetailView) convertView;
79100a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos            }
792844c92b444dca7f5ef4d0943fb14e2cbeee49701Adrian Roos            v.refreshAdapter();
79300a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos            return v;
79400a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        }
79500a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos
79600a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        @Override
79700a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        public Intent getSettingsIntent() {
79800a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos            return USER_SETTINGS_INTENT;
79900a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        }
80000a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos
80100a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        @Override
80200a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        public Boolean getToggleState() {
80300a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos            return null;
80400a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        }
80500a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos
80600a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        @Override
80700a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        public void setToggleState(boolean state) {
80800a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos        }
809457a21cdeac04565a0c40ad8c43a928c1182ddd1Chris Wren
810457a21cdeac04565a0c40ad8c43a928c1182ddd1Chris Wren        @Override
811457a21cdeac04565a0c40ad8c43a928c1182ddd1Chris Wren        public int getMetricsCategory() {
812f6e9228b8a97603d3ceb8f0d61e8d87cf19bd21fChris Wren            return MetricsEvent.QS_USERDETAIL;
813457a21cdeac04565a0c40ad8c43a928c1182ddd1Chris Wren        }
81400a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos    };
8155005244f10442e75c1f48973fdddce5facf3f360Adrian Roos
816ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos    private final KeyguardMonitor.Callback mCallback = new KeyguardMonitor.Callback() {
817ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos        @Override
818ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos        public void onKeyguardChanged() {
819ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos            notifyAdapters();
820ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos        }
821ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos    };
822ccdff62159b41ab130a8f90d30edb9b9542d8c72Adrian Roos
8235005244f10442e75c1f48973fdddce5facf3f360Adrian Roos    private final class ExitGuestDialog extends SystemUIDialog implements
8245005244f10442e75c1f48973fdddce5facf3f360Adrian Roos            DialogInterface.OnClickListener {
8255005244f10442e75c1f48973fdddce5facf3f360Adrian Roos
8265005244f10442e75c1f48973fdddce5facf3f360Adrian Roos        private final int mGuestId;
8275005244f10442e75c1f48973fdddce5facf3f360Adrian Roos
8285005244f10442e75c1f48973fdddce5facf3f360Adrian Roos        public ExitGuestDialog(Context context, int guestId) {
8295005244f10442e75c1f48973fdddce5facf3f360Adrian Roos            super(context);
8305005244f10442e75c1f48973fdddce5facf3f360Adrian Roos            setTitle(R.string.guest_exit_guest_dialog_title);
8315005244f10442e75c1f48973fdddce5facf3f360Adrian Roos            setMessage(context.getString(R.string.guest_exit_guest_dialog_message));
8325005244f10442e75c1f48973fdddce5facf3f360Adrian Roos            setButton(DialogInterface.BUTTON_NEGATIVE,
833e5b274ac612400a7bc9f258d4ef3c366cfa1bc11Amith Yamasani                    context.getString(android.R.string.cancel), this);
8345005244f10442e75c1f48973fdddce5facf3f360Adrian Roos            setButton(DialogInterface.BUTTON_POSITIVE,
835e5b274ac612400a7bc9f258d4ef3c366cfa1bc11Amith Yamasani                    context.getString(R.string.guest_exit_guest_dialog_remove), this);
8365005244f10442e75c1f48973fdddce5facf3f360Adrian Roos            setCanceledOnTouchOutside(false);
8375005244f10442e75c1f48973fdddce5facf3f360Adrian Roos            mGuestId = guestId;
8385005244f10442e75c1f48973fdddce5facf3f360Adrian Roos        }
8395005244f10442e75c1f48973fdddce5facf3f360Adrian Roos
8405005244f10442e75c1f48973fdddce5facf3f360Adrian Roos        @Override
8415005244f10442e75c1f48973fdddce5facf3f360Adrian Roos        public void onClick(DialogInterface dialog, int which) {
8425005244f10442e75c1f48973fdddce5facf3f360Adrian Roos            if (which == BUTTON_NEGATIVE) {
8435005244f10442e75c1f48973fdddce5facf3f360Adrian Roos                cancel();
8445005244f10442e75c1f48973fdddce5facf3f360Adrian Roos            } else {
8455005244f10442e75c1f48973fdddce5facf3f360Adrian Roos                dismiss();
8465005244f10442e75c1f48973fdddce5facf3f360Adrian Roos                exitGuest(mGuestId);
8475005244f10442e75c1f48973fdddce5facf3f360Adrian Roos            }
8485005244f10442e75c1f48973fdddce5facf3f360Adrian Roos        }
8495005244f10442e75c1f48973fdddce5facf3f360Adrian Roos    }
8500c6763a19f32f73f8a940aaee7abecb2a04d1889Adrian Roos
8510c6763a19f32f73f8a940aaee7abecb2a04d1889Adrian Roos    private final class AddUserDialog extends SystemUIDialog implements
8520c6763a19f32f73f8a940aaee7abecb2a04d1889Adrian Roos            DialogInterface.OnClickListener {
8530c6763a19f32f73f8a940aaee7abecb2a04d1889Adrian Roos
8540c6763a19f32f73f8a940aaee7abecb2a04d1889Adrian Roos        public AddUserDialog(Context context) {
8550c6763a19f32f73f8a940aaee7abecb2a04d1889Adrian Roos            super(context);
8560c6763a19f32f73f8a940aaee7abecb2a04d1889Adrian Roos            setTitle(R.string.user_add_user_title);
8570c6763a19f32f73f8a940aaee7abecb2a04d1889Adrian Roos            setMessage(context.getString(R.string.user_add_user_message_short));
8580c6763a19f32f73f8a940aaee7abecb2a04d1889Adrian Roos            setButton(DialogInterface.BUTTON_NEGATIVE,
8590c6763a19f32f73f8a940aaee7abecb2a04d1889Adrian Roos                    context.getString(android.R.string.cancel), this);
8600c6763a19f32f73f8a940aaee7abecb2a04d1889Adrian Roos            setButton(DialogInterface.BUTTON_POSITIVE,
8610c6763a19f32f73f8a940aaee7abecb2a04d1889Adrian Roos                    context.getString(android.R.string.ok), this);
8620c6763a19f32f73f8a940aaee7abecb2a04d1889Adrian Roos        }
8630c6763a19f32f73f8a940aaee7abecb2a04d1889Adrian Roos
8640c6763a19f32f73f8a940aaee7abecb2a04d1889Adrian Roos        @Override
8650c6763a19f32f73f8a940aaee7abecb2a04d1889Adrian Roos        public void onClick(DialogInterface dialog, int which) {
8660c6763a19f32f73f8a940aaee7abecb2a04d1889Adrian Roos            if (which == BUTTON_NEGATIVE) {
8670c6763a19f32f73f8a940aaee7abecb2a04d1889Adrian Roos                cancel();
8680c6763a19f32f73f8a940aaee7abecb2a04d1889Adrian Roos            } else {
8690c6763a19f32f73f8a940aaee7abecb2a04d1889Adrian Roos                dismiss();
870ccbeb61ac21527839deb115199cbe98fa2b73c05Guang Zhu                if (ActivityManager.isUserAMonkey()) {
871ccbeb61ac21527839deb115199cbe98fa2b73c05Guang Zhu                    return;
872ccbeb61ac21527839deb115199cbe98fa2b73c05Guang Zhu                }
873cfe64c8afa9f30d8874c72440c3992e79fdb60c9Xiaohui Chen                UserInfo user = mUserManager.createUser(
874f99727cb878f9709f6c0263c0283257decbaebadAdrian Roos                        mContext.getString(R.string.user_new_user_name), 0 /* flags */);
875f99727cb878f9709f6c0263c0283257decbaebadAdrian Roos                if (user == null) {
876f99727cb878f9709f6c0263c0283257decbaebadAdrian Roos                    // Couldn't create user, most likely because there are too many, but we haven't
877f99727cb878f9709f6c0263c0283257decbaebadAdrian Roos                    // been able to reload the list yet.
878f99727cb878f9709f6c0263c0283257decbaebadAdrian Roos                    return;
879f99727cb878f9709f6c0263c0283257decbaebadAdrian Roos                }
880f99727cb878f9709f6c0263c0283257decbaebadAdrian Roos                int id = user.id;
88164d4dca63f65e4c7d4a829c85ff6670bdd34e2ebAlexandra Gherghina                Bitmap icon = UserIcons.convertToBitmap(UserIcons.getDefaultUserIcon(
88264d4dca63f65e4c7d4a829c85ff6670bdd34e2ebAlexandra Gherghina                        id, /* light= */ false));
88364d4dca63f65e4c7d4a829c85ff6670bdd34e2ebAlexandra Gherghina                mUserManager.setUserIcon(id, icon);
8840c6763a19f32f73f8a940aaee7abecb2a04d1889Adrian Roos                switchToUserId(id);
8850c6763a19f32f73f8a940aaee7abecb2a04d1889Adrian Roos            }
8860c6763a19f32f73f8a940aaee7abecb2a04d1889Adrian Roos        }
8870c6763a19f32f73f8a940aaee7abecb2a04d1889Adrian Roos    }
88800a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos}
889