UserSwitcherController.java revision 723632ea1ae30b33e9c2055194a4464f00c48c61
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 194d75c079f35d85b687d8349e5e2940447d01198eDan Sandlerimport com.android.systemui.BitmapHelper; 205005244f10442e75c1f48973fdddce5facf3f360Adrian Roosimport com.android.systemui.GuestResumeSessionReceiver; 2100a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roosimport com.android.systemui.R; 2200a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roosimport com.android.systemui.qs.QSTile; 2300a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roosimport com.android.systemui.qs.tiles.UserDetailView; 245005244f10442e75c1f48973fdddce5facf3f360Adrian Roosimport com.android.systemui.statusbar.phone.SystemUIDialog; 2500a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos 2600a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roosimport android.app.ActivityManager; 2700a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roosimport android.app.ActivityManagerNative; 285005244f10442e75c1f48973fdddce5facf3f360Adrian Roosimport android.app.Dialog; 2900a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roosimport android.content.BroadcastReceiver; 3000a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roosimport android.content.Context; 315005244f10442e75c1f48973fdddce5facf3f360Adrian Roosimport android.content.DialogInterface; 3200a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roosimport android.content.Intent; 3300a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roosimport android.content.IntentFilter; 3400a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roosimport android.content.pm.UserInfo; 3500a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roosimport android.graphics.Bitmap; 3600a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roosimport android.os.AsyncTask; 3700a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roosimport android.os.RemoteException; 38e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roosimport android.os.UserHandle; 3900a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roosimport android.os.UserManager; 4000a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roosimport android.util.Log; 41e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roosimport android.util.SparseArray; 4200a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roosimport android.view.View; 4300a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roosimport android.view.ViewGroup; 4400a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roosimport android.view.WindowManagerGlobal; 4500a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roosimport android.widget.BaseAdapter; 4600a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos 4700a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roosimport java.io.FileDescriptor; 4800a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roosimport java.io.PrintWriter; 4900a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roosimport java.lang.ref.WeakReference; 5000a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roosimport java.util.ArrayList; 5100a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roosimport java.util.List; 5200a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos 5300a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos/** 5400a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos * Keeps a list of all users on the device for user switching. 5500a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos */ 5600a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roospublic class UserSwitcherController { 5700a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos 5800a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos private static final String TAG = "UserSwitcherController"; 595005244f10442e75c1f48973fdddce5facf3f360Adrian Roos private static final boolean DEBUG = false; 6000a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos 6100a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos private final Context mContext; 6200a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos private final UserManager mUserManager; 6300a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos private final ArrayList<WeakReference<BaseUserAdapter>> mAdapters = new ArrayList<>(); 645005244f10442e75c1f48973fdddce5facf3f360Adrian Roos private final GuestResumeSessionReceiver mGuestResumeSessionReceiver 655005244f10442e75c1f48973fdddce5facf3f360Adrian Roos = new GuestResumeSessionReceiver(); 6600a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos 6700a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos private ArrayList<UserRecord> mUsers = new ArrayList<>(); 685005244f10442e75c1f48973fdddce5facf3f360Adrian Roos private Dialog mExitGuestDialog; 6970441467f4dc232cd8e6142f0afc117787dc979bAdrian Roos private int mLastNonGuestUser = UserHandle.USER_OWNER; 7000a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos 7100a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos public UserSwitcherController(Context context) { 7200a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos mContext = context; 735005244f10442e75c1f48973fdddce5facf3f360Adrian Roos mGuestResumeSessionReceiver.register(context); 7400a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos mUserManager = UserManager.get(context); 7500a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos IntentFilter filter = new IntentFilter(); 7600a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos filter.addAction(Intent.ACTION_USER_ADDED); 7700a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos filter.addAction(Intent.ACTION_USER_REMOVED); 7800a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos filter.addAction(Intent.ACTION_USER_INFO_CHANGED); 7900a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos filter.addAction(Intent.ACTION_USER_SWITCHED); 80e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos filter.addAction(Intent.ACTION_USER_STOPPING); 81e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos mContext.registerReceiverAsUser(mReceiver, UserHandle.OWNER, filter, 82e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos null /* permission */, null /* scheduler */); 83e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos refreshUsers(UserHandle.USER_NULL); 8400a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos } 8500a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos 86e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos /** 87e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos * Refreshes users from UserManager. 88e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos * 89e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos * The pictures are only loaded if they have not been loaded yet. 90e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos * 91e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos * @param forcePictureLoadForId forces the picture of the given user to be reloaded. 92e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos */ 93e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos private void refreshUsers(int forcePictureLoadForId) { 9400a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos 95e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos SparseArray<Bitmap> bitmaps = new SparseArray<>(mUsers.size()); 96e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos final int N = mUsers.size(); 97e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos for (int i = 0; i < N; i++) { 98e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos UserRecord r = mUsers.get(i); 99e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos if (r == null || r.info == null 100e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos || r.info.id == forcePictureLoadForId || r.picture == null) { 101e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos continue; 102e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos } 103e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos bitmaps.put(r.info.id, r.picture); 104e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos } 105e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos 106e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos new AsyncTask<SparseArray<Bitmap>, Void, ArrayList<UserRecord>>() { 107e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos @SuppressWarnings("unchecked") 10800a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos @Override 109e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos protected ArrayList<UserRecord> doInBackground(SparseArray<Bitmap>... params) { 110e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos final SparseArray<Bitmap> bitmaps = params[0]; 11100a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos List<UserInfo> infos = mUserManager.getUsers(true); 11200a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos if (infos == null) { 11300a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos return null; 11400a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos } 11500a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos ArrayList<UserRecord> records = new ArrayList<>(infos.size()); 11600a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos int currentId = ActivityManager.getCurrentUser(); 11700a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos UserRecord guestRecord = null; 1184d75c079f35d85b687d8349e5e2940447d01198eDan Sandler int avatarSize = mContext.getResources() 1194d75c079f35d85b687d8349e5e2940447d01198eDan Sandler .getDimensionPixelSize(R.dimen.max_avatar_size); 12000a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos 12100a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos for (UserInfo info : infos) { 12200a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos boolean isCurrent = currentId == info.id; 12300a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos if (info.isGuest()) { 12400a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos guestRecord = new UserRecord(info, null /* picture */, 12500a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos true /* isGuest */, isCurrent); 126723632ea1ae30b33e9c2055194a4464f00c48c61Adrian Roos } else if (info.supportsSwitchTo()) { 127e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos Bitmap picture = bitmaps.get(info.id); 128e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos if (picture == null) { 129e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos picture = mUserManager.getUserIcon(info.id); 130e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos } 1314d75c079f35d85b687d8349e5e2940447d01198eDan Sandler if (picture != null) { 1324d75c079f35d85b687d8349e5e2940447d01198eDan Sandler picture = BitmapHelper.createCircularClip( 1334d75c079f35d85b687d8349e5e2940447d01198eDan Sandler picture, avatarSize, avatarSize); 1344d75c079f35d85b687d8349e5e2940447d01198eDan Sandler } 135e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos records.add(new UserRecord(info, picture, false /* isGuest */, isCurrent)); 13600a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos } 13700a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos } 13800a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos 13900a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos if (guestRecord == null) { 14000a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos records.add(new UserRecord(null /* info */, null /* picture */, 14100a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos true /* isGuest */, false /* isCurrent */)); 14200a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos } else { 14300a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos records.add(guestRecord); 14400a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos } 14500a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos 14600a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos return records; 14700a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos } 14800a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos 14900a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos @Override 15000a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos protected void onPostExecute(ArrayList<UserRecord> userRecords) { 15100a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos if (userRecords != null) { 15200a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos mUsers = userRecords; 15300a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos notifyAdapters(); 15400a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos } 15500a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos } 156e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos }.execute((SparseArray)bitmaps); 15700a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos } 15800a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos 15900a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos private void notifyAdapters() { 16000a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos for (int i = mAdapters.size() - 1; i >= 0; i--) { 16100a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos BaseUserAdapter adapter = mAdapters.get(i).get(); 16200a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos if (adapter != null) { 16300a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos adapter.notifyDataSetChanged(); 16400a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos } else { 16500a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos mAdapters.remove(i); 16600a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos } 16700a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos } 16800a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos } 16900a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos 17000a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos public void switchTo(UserRecord record) { 17100a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos int id; 17200a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos if (record.isGuest && record.info == null) { 17300a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos // No guest user. Create one. 17400a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos id = mUserManager.createGuest(mContext, 17500a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos mContext.getResources().getString(R.string.guest_nickname)).id; 17600a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos } else { 17700a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos id = record.info.id; 17800a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos } 17900a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos 18000a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos if (ActivityManager.getCurrentUser() == id) { 181e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos if (record.isGuest) { 1825005244f10442e75c1f48973fdddce5facf3f360Adrian Roos showExitGuestDialog(id); 183e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos } 18400a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos return; 18500a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos } 18600a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos 187e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos switchToUserId(id); 188e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos } 189e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos 190e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos private void switchToUserId(int id) { 19100a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos try { 19200a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos WindowManagerGlobal.getWindowManagerService().lockNow(null); 19300a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos ActivityManagerNative.getDefault().switchUser(id); 19400a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos } catch (RemoteException e) { 19500a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos Log.e(TAG, "Couldn't switch user.", e); 19600a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos } 19700a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos } 19800a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos 1995005244f10442e75c1f48973fdddce5facf3f360Adrian Roos private void showExitGuestDialog(int id) { 2005005244f10442e75c1f48973fdddce5facf3f360Adrian Roos if (mExitGuestDialog != null && mExitGuestDialog.isShowing()) { 2015005244f10442e75c1f48973fdddce5facf3f360Adrian Roos mExitGuestDialog.cancel(); 2025005244f10442e75c1f48973fdddce5facf3f360Adrian Roos } 2035005244f10442e75c1f48973fdddce5facf3f360Adrian Roos mExitGuestDialog = new ExitGuestDialog(mContext, id); 2045005244f10442e75c1f48973fdddce5facf3f360Adrian Roos mExitGuestDialog.show(); 2055005244f10442e75c1f48973fdddce5facf3f360Adrian Roos } 2065005244f10442e75c1f48973fdddce5facf3f360Adrian Roos 207e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos private void exitGuest(int id) { 20870441467f4dc232cd8e6142f0afc117787dc979bAdrian Roos int newId = UserHandle.USER_OWNER; 20970441467f4dc232cd8e6142f0afc117787dc979bAdrian Roos if (mLastNonGuestUser != UserHandle.USER_OWNER) { 21070441467f4dc232cd8e6142f0afc117787dc979bAdrian Roos UserInfo info = mUserManager.getUserInfo(mLastNonGuestUser); 21170441467f4dc232cd8e6142f0afc117787dc979bAdrian Roos if (info != null && info.isEnabled() && info.supportsSwitchTo()) { 21270441467f4dc232cd8e6142f0afc117787dc979bAdrian Roos newId = info.id; 21370441467f4dc232cd8e6142f0afc117787dc979bAdrian Roos } 21470441467f4dc232cd8e6142f0afc117787dc979bAdrian Roos } 21570441467f4dc232cd8e6142f0afc117787dc979bAdrian Roos switchToUserId(newId); 216e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos mUserManager.removeUser(id); 217e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos } 218e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos 21900a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos private BroadcastReceiver mReceiver = new BroadcastReceiver() { 22000a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos @Override 22100a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos public void onReceive(Context context, Intent intent) { 2225005244f10442e75c1f48973fdddce5facf3f360Adrian Roos if (DEBUG) { 2235005244f10442e75c1f48973fdddce5facf3f360Adrian Roos Log.v(TAG, "Broadcast: a=" + intent.getAction() 2245005244f10442e75c1f48973fdddce5facf3f360Adrian Roos + " user=" + intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1)); 2255005244f10442e75c1f48973fdddce5facf3f360Adrian Roos } 22600a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos if (Intent.ACTION_USER_SWITCHED.equals(intent.getAction())) { 2275005244f10442e75c1f48973fdddce5facf3f360Adrian Roos if (mExitGuestDialog != null && mExitGuestDialog.isShowing()) { 2285005244f10442e75c1f48973fdddce5facf3f360Adrian Roos mExitGuestDialog.cancel(); 2295005244f10442e75c1f48973fdddce5facf3f360Adrian Roos mExitGuestDialog = null; 2305005244f10442e75c1f48973fdddce5facf3f360Adrian Roos } 2315005244f10442e75c1f48973fdddce5facf3f360Adrian Roos 23200a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos final int currentId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1); 23300a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos final int N = mUsers.size(); 23400a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos for (int i = 0; i < N; i++) { 23500a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos UserRecord record = mUsers.get(i); 236e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos if (record.info == null) continue; 23700a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos boolean shouldBeCurrent = record.info.id == currentId; 23800a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos if (record.isCurrent != shouldBeCurrent) { 23900a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos mUsers.set(i, record.copyWithIsCurrent(shouldBeCurrent)); 24000a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos } 24170441467f4dc232cd8e6142f0afc117787dc979bAdrian Roos if (shouldBeCurrent && !record.isGuest) { 24270441467f4dc232cd8e6142f0afc117787dc979bAdrian Roos mLastNonGuestUser = record.info.id; 24370441467f4dc232cd8e6142f0afc117787dc979bAdrian Roos } 24400a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos } 24500a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos notifyAdapters(); 24600a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos } 247e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos int forcePictureLoadForId = UserHandle.USER_NULL; 248e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos if (Intent.ACTION_USER_INFO_CHANGED.equals(intent.getAction())) { 249e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos forcePictureLoadForId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 250e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos UserHandle.USER_NULL); 251e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos } 252e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos refreshUsers(forcePictureLoadForId); 25300a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos } 25400a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos }; 25500a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos 25600a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 25700a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos pw.println("UserSwitcherController state:"); 25870441467f4dc232cd8e6142f0afc117787dc979bAdrian Roos pw.println(" mLastNonGuestUser=" + mLastNonGuestUser); 25900a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos pw.print(" mUsers.size="); pw.println(mUsers.size()); 26000a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos for (int i = 0; i < mUsers.size(); i++) { 26100a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos final UserRecord u = mUsers.get(i); 26200a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos pw.print(" "); pw.println(u.toString()); 26300a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos } 26400a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos } 26500a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos 26600a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos public static abstract class BaseUserAdapter extends BaseAdapter { 26700a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos 26800a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos final UserSwitcherController mController; 26900a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos 27000a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos protected BaseUserAdapter(UserSwitcherController controller) { 27100a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos mController = controller; 27200a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos controller.mAdapters.add(new WeakReference<>(this)); 27300a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos } 27400a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos 27500a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos @Override 27600a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos public int getCount() { 27700a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos return mController.mUsers.size(); 27800a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos } 27900a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos 28000a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos @Override 28100a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos public UserRecord getItem(int position) { 28200a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos return mController.mUsers.get(position); 28300a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos } 28400a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos 28500a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos @Override 28600a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos public long getItemId(int position) { 287e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos return position; 28800a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos } 28900a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos 29000a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos public void switchTo(UserRecord record) { 29100a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos mController.switchTo(record); 29200a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos } 293e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos 294e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos public String getName(Context context, UserRecord item) { 295e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos if (item.isGuest) { 296e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos if (item.isCurrent) { 297e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos return context.getString(R.string.guest_exit_guest); 298e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos } else { 299e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos return context.getString( 300e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos item.info == null ? R.string.guest_new_guest : R.string.guest_nickname); 301e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos } 302e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos } else { 303e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos return item.info.name; 304e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos } 305e9c7d431da85b5bc03ecaa964d7a491b01466a99Adrian Roos } 306723632ea1ae30b33e9c2055194a4464f00c48c61Adrian Roos 307723632ea1ae30b33e9c2055194a4464f00c48c61Adrian Roos public int getSwitchableUsers() { 308723632ea1ae30b33e9c2055194a4464f00c48c61Adrian Roos int result = 0; 309723632ea1ae30b33e9c2055194a4464f00c48c61Adrian Roos ArrayList<UserRecord> users = mController.mUsers; 310723632ea1ae30b33e9c2055194a4464f00c48c61Adrian Roos int N = users.size(); 311723632ea1ae30b33e9c2055194a4464f00c48c61Adrian Roos for (int i = 0; i < N; i++) { 312723632ea1ae30b33e9c2055194a4464f00c48c61Adrian Roos if (users.get(i).info != null) { 313723632ea1ae30b33e9c2055194a4464f00c48c61Adrian Roos result++; 314723632ea1ae30b33e9c2055194a4464f00c48c61Adrian Roos } 315723632ea1ae30b33e9c2055194a4464f00c48c61Adrian Roos } 316723632ea1ae30b33e9c2055194a4464f00c48c61Adrian Roos return result; 317723632ea1ae30b33e9c2055194a4464f00c48c61Adrian Roos } 31800a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos } 31900a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos 32000a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos public static final class UserRecord { 32100a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos public final UserInfo info; 32200a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos public final Bitmap picture; 32300a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos public final boolean isGuest; 32400a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos public final boolean isCurrent; 32500a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos 32600a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos public UserRecord(UserInfo info, Bitmap picture, boolean isGuest, boolean isCurrent) { 32700a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos this.info = info; 32800a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos this.picture = picture; 32900a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos this.isGuest = isGuest; 33000a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos this.isCurrent = isCurrent; 33100a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos } 33200a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos 33300a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos public UserRecord copyWithIsCurrent(boolean _isCurrent) { 33400a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos return new UserRecord(info, picture, isGuest, _isCurrent); 33500a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos } 33600a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos 33700a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos public String toString() { 33800a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos StringBuilder sb = new StringBuilder(); 33900a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos sb.append("UserRecord("); 34000a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos if (info != null) { 34100a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos sb.append("name=\"" + info.name + "\" id=" + info.id); 34200a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos } else { 34300a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos sb.append("<add guest placeholder>"); 34400a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos } 34500a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos if (isGuest) { 34600a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos sb.append(" <isGuest>"); 34700a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos } 34800a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos if (isCurrent) { 34900a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos sb.append(" <isCurrent>"); 35000a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos } 35100a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos if (picture != null) { 35200a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos sb.append(" <hasPicture>"); 35300a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos } 35400a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos sb.append(')'); 35500a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos return sb.toString(); 35600a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos } 35700a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos } 35800a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos 35900a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos public final QSTile.DetailAdapter userDetailAdapter = new QSTile.DetailAdapter() { 36000a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos private final Intent USER_SETTINGS_INTENT = new Intent("android.settings.USER_SETTINGS"); 36100a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos 36200a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos @Override 36300a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos public int getTitle() { 36400a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos return R.string.quick_settings_user_title; 36500a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos } 36600a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos 36700a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos @Override 36800a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos public View createDetailView(Context context, View convertView, ViewGroup parent) { 36900a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos if (!(convertView instanceof UserDetailView)) { 37000a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos convertView = UserDetailView.inflate(context, parent, false); 37100a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos } 37200a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos UserDetailView v = (UserDetailView) convertView; 37300a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos if (v.getAdapter() == null) { 37400a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos v.createAndSetAdapter(UserSwitcherController.this); 37500a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos } 37600a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos return v; 37700a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos } 37800a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos 37900a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos @Override 38000a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos public Intent getSettingsIntent() { 38100a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos return USER_SETTINGS_INTENT; 38200a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos } 38300a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos 38400a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos @Override 38500a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos public Boolean getToggleState() { 38600a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos return null; 38700a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos } 38800a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos 38900a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos @Override 39000a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos public void setToggleState(boolean state) { 39100a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos } 39200a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos }; 3935005244f10442e75c1f48973fdddce5facf3f360Adrian Roos 3945005244f10442e75c1f48973fdddce5facf3f360Adrian Roos private final class ExitGuestDialog extends SystemUIDialog implements 3955005244f10442e75c1f48973fdddce5facf3f360Adrian Roos DialogInterface.OnClickListener { 3965005244f10442e75c1f48973fdddce5facf3f360Adrian Roos 3975005244f10442e75c1f48973fdddce5facf3f360Adrian Roos private final int mGuestId; 3985005244f10442e75c1f48973fdddce5facf3f360Adrian Roos 3995005244f10442e75c1f48973fdddce5facf3f360Adrian Roos public ExitGuestDialog(Context context, int guestId) { 4005005244f10442e75c1f48973fdddce5facf3f360Adrian Roos super(context); 4015005244f10442e75c1f48973fdddce5facf3f360Adrian Roos setTitle(R.string.guest_exit_guest_dialog_title); 4025005244f10442e75c1f48973fdddce5facf3f360Adrian Roos setMessage(context.getString(R.string.guest_exit_guest_dialog_message)); 4035005244f10442e75c1f48973fdddce5facf3f360Adrian Roos setButton(DialogInterface.BUTTON_NEGATIVE, 4045005244f10442e75c1f48973fdddce5facf3f360Adrian Roos context.getString(android.R.string.no), this); 4055005244f10442e75c1f48973fdddce5facf3f360Adrian Roos setButton(DialogInterface.BUTTON_POSITIVE, 4065005244f10442e75c1f48973fdddce5facf3f360Adrian Roos context.getString(android.R.string.yes), this); 4075005244f10442e75c1f48973fdddce5facf3f360Adrian Roos setCanceledOnTouchOutside(false); 4085005244f10442e75c1f48973fdddce5facf3f360Adrian Roos mGuestId = guestId; 4095005244f10442e75c1f48973fdddce5facf3f360Adrian Roos } 4105005244f10442e75c1f48973fdddce5facf3f360Adrian Roos 4115005244f10442e75c1f48973fdddce5facf3f360Adrian Roos @Override 4125005244f10442e75c1f48973fdddce5facf3f360Adrian Roos public void onClick(DialogInterface dialog, int which) { 4135005244f10442e75c1f48973fdddce5facf3f360Adrian Roos if (which == BUTTON_NEGATIVE) { 4145005244f10442e75c1f48973fdddce5facf3f360Adrian Roos cancel(); 4155005244f10442e75c1f48973fdddce5facf3f360Adrian Roos } else { 4165005244f10442e75c1f48973fdddce5facf3f360Adrian Roos dismiss(); 4175005244f10442e75c1f48973fdddce5facf3f360Adrian Roos exitGuest(mGuestId); 4185005244f10442e75c1f48973fdddce5facf3f360Adrian Roos } 4195005244f10442e75c1f48973fdddce5facf3f360Adrian Roos } 4205005244f10442e75c1f48973fdddce5facf3f360Adrian Roos } 42100a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos} 422