Loading packages/SystemUI/AndroidManifest.xml +1 −0 Original line number Diff line number Diff line Loading @@ -70,6 +70,7 @@ <uses-permission android:name="android.permission.STOP_APP_SWITCHES" /> <uses-permission android:name="android.permission.SET_SCREEN_COMPATIBILITY" /> <uses-permission android:name="android.permission.START_ANY_ACTIVITY" /> <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS" /> <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" /> <uses-permission android:name="android.permission.GET_TOP_ACTIVITY_INFO" /> <uses-permission android:name="android.permission.MANAGE_ACTIVITY_STACKS" /> Loading packages/SystemUI/res/values/strings.xml +1 −0 Original line number Diff line number Diff line Loading @@ -703,4 +703,5 @@ <!-- Text shown in place of notification contents when the notification is hidden on a secure lockscreen --> <string name="notification_hidden_text">Contents hidden</string> <string name="guest_exit_guest">Exit guest</string> </resources> packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailView.java +1 −7 Original line number Diff line number Diff line Loading @@ -81,13 +81,7 @@ public class UserDetailView extends GridView { UserSwitcherController.UserRecord item = getItem(position); UserDetailItemView v = UserDetailItemView.convertOrInflate( mContext, convertView, parent); String name; if (item.isGuest) { name = mContext.getString( item.info == null ? R.string.guest_new_guest : R.string.guest_nickname); } else { name = item.info.name; } String name = getName(mContext, item); if (item.picture == null) { v.bind(name, mContext.getDrawable(R.drawable.ic_account_circle_qs)); } else { Loading packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java +69 −11 Original line number Diff line number Diff line Loading @@ -30,8 +30,10 @@ import android.content.pm.UserInfo; import android.graphics.Bitmap; import android.os.AsyncTask; import android.os.RemoteException; import android.os.UserHandle; import android.os.UserManager; import android.util.Log; import android.util.SparseArray; import android.view.View; import android.view.ViewGroup; import android.view.WindowManagerGlobal; Loading Loading @@ -64,15 +66,37 @@ public class UserSwitcherController { filter.addAction(Intent.ACTION_USER_REMOVED); filter.addAction(Intent.ACTION_USER_INFO_CHANGED); filter.addAction(Intent.ACTION_USER_SWITCHED); mContext.registerReceiver(mReceiver, filter); refreshUsers(); filter.addAction(Intent.ACTION_USER_STOPPING); mContext.registerReceiverAsUser(mReceiver, UserHandle.OWNER, filter, null /* permission */, null /* scheduler */); refreshUsers(UserHandle.USER_NULL); } private void refreshUsers() { new AsyncTask<Void, Void, ArrayList<UserRecord>>() { /** * Refreshes users from UserManager. * * The pictures are only loaded if they have not been loaded yet. * * @param forcePictureLoadForId forces the picture of the given user to be reloaded. */ private void refreshUsers(int forcePictureLoadForId) { SparseArray<Bitmap> bitmaps = new SparseArray<>(mUsers.size()); final int N = mUsers.size(); for (int i = 0; i < N; i++) { UserRecord r = mUsers.get(i); if (r == null || r.info == null || r.info.id == forcePictureLoadForId || r.picture == null) { continue; } bitmaps.put(r.info.id, r.picture); } new AsyncTask<SparseArray<Bitmap>, Void, ArrayList<UserRecord>>() { @SuppressWarnings("unchecked") @Override protected ArrayList<UserRecord> doInBackground(Void... params) { protected ArrayList<UserRecord> doInBackground(SparseArray<Bitmap>... params) { final SparseArray<Bitmap> bitmaps = params[0]; List<UserInfo> infos = mUserManager.getUsers(true); if (infos == null) { return null; Loading @@ -87,8 +111,11 @@ public class UserSwitcherController { guestRecord = new UserRecord(info, null /* picture */, true /* isGuest */, isCurrent); } else if (!info.isManagedProfile()) { records.add(new UserRecord(info, mUserManager.getUserIcon(info.id), false /* isGuest */, isCurrent)); Bitmap picture = bitmaps.get(info.id); if (picture == null) { picture = mUserManager.getUserIcon(info.id); } records.add(new UserRecord(info, picture, false /* isGuest */, isCurrent)); } } Loading @@ -109,7 +136,7 @@ public class UserSwitcherController { notifyAdapters(); } } }.execute((Void[])null); }.execute((SparseArray)bitmaps); } private void notifyAdapters() { Loading @@ -134,9 +161,16 @@ public class UserSwitcherController { } if (ActivityManager.getCurrentUser() == id) { if (record.isGuest) { exitGuest(id); } return; } switchToUserId(id); } private void switchToUserId(int id) { try { WindowManagerGlobal.getWindowManagerService().lockNow(null); ActivityManagerNative.getDefault().switchUser(id); Loading @@ -145,6 +179,12 @@ public class UserSwitcherController { } } private void exitGuest(int id) { // TODO: show confirmation dialog switchToUserId(UserHandle.USER_OWNER); mUserManager.removeUser(id); } private BroadcastReceiver mReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { Loading @@ -153,15 +193,20 @@ public class UserSwitcherController { final int N = mUsers.size(); for (int i = 0; i < N; i++) { UserRecord record = mUsers.get(i); if (record.info == null) continue; boolean shouldBeCurrent = record.info.id == currentId; if (record.isCurrent != shouldBeCurrent) { mUsers.set(i, record.copyWithIsCurrent(shouldBeCurrent)); } } notifyAdapters(); } else { refreshUsers(); } int forcePictureLoadForId = UserHandle.USER_NULL; if (Intent.ACTION_USER_INFO_CHANGED.equals(intent.getAction())) { forcePictureLoadForId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL); } refreshUsers(forcePictureLoadForId); } }; Loading Loading @@ -195,12 +240,25 @@ public class UserSwitcherController { @Override public long getItemId(int position) { return mController.mUsers.get(position).info.id; return position; } public void switchTo(UserRecord record) { mController.switchTo(record); } public String getName(Context context, UserRecord item) { if (item.isGuest) { if (item.isCurrent) { return context.getString(R.string.guest_exit_guest); } else { return context.getString( item.info == null ? R.string.guest_new_guest : R.string.guest_nickname); } } else { return item.info.name; } } } public static final class UserRecord { Loading Loading
packages/SystemUI/AndroidManifest.xml +1 −0 Original line number Diff line number Diff line Loading @@ -70,6 +70,7 @@ <uses-permission android:name="android.permission.STOP_APP_SWITCHES" /> <uses-permission android:name="android.permission.SET_SCREEN_COMPATIBILITY" /> <uses-permission android:name="android.permission.START_ANY_ACTIVITY" /> <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS" /> <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" /> <uses-permission android:name="android.permission.GET_TOP_ACTIVITY_INFO" /> <uses-permission android:name="android.permission.MANAGE_ACTIVITY_STACKS" /> Loading
packages/SystemUI/res/values/strings.xml +1 −0 Original line number Diff line number Diff line Loading @@ -703,4 +703,5 @@ <!-- Text shown in place of notification contents when the notification is hidden on a secure lockscreen --> <string name="notification_hidden_text">Contents hidden</string> <string name="guest_exit_guest">Exit guest</string> </resources>
packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailView.java +1 −7 Original line number Diff line number Diff line Loading @@ -81,13 +81,7 @@ public class UserDetailView extends GridView { UserSwitcherController.UserRecord item = getItem(position); UserDetailItemView v = UserDetailItemView.convertOrInflate( mContext, convertView, parent); String name; if (item.isGuest) { name = mContext.getString( item.info == null ? R.string.guest_new_guest : R.string.guest_nickname); } else { name = item.info.name; } String name = getName(mContext, item); if (item.picture == null) { v.bind(name, mContext.getDrawable(R.drawable.ic_account_circle_qs)); } else { Loading
packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java +69 −11 Original line number Diff line number Diff line Loading @@ -30,8 +30,10 @@ import android.content.pm.UserInfo; import android.graphics.Bitmap; import android.os.AsyncTask; import android.os.RemoteException; import android.os.UserHandle; import android.os.UserManager; import android.util.Log; import android.util.SparseArray; import android.view.View; import android.view.ViewGroup; import android.view.WindowManagerGlobal; Loading Loading @@ -64,15 +66,37 @@ public class UserSwitcherController { filter.addAction(Intent.ACTION_USER_REMOVED); filter.addAction(Intent.ACTION_USER_INFO_CHANGED); filter.addAction(Intent.ACTION_USER_SWITCHED); mContext.registerReceiver(mReceiver, filter); refreshUsers(); filter.addAction(Intent.ACTION_USER_STOPPING); mContext.registerReceiverAsUser(mReceiver, UserHandle.OWNER, filter, null /* permission */, null /* scheduler */); refreshUsers(UserHandle.USER_NULL); } private void refreshUsers() { new AsyncTask<Void, Void, ArrayList<UserRecord>>() { /** * Refreshes users from UserManager. * * The pictures are only loaded if they have not been loaded yet. * * @param forcePictureLoadForId forces the picture of the given user to be reloaded. */ private void refreshUsers(int forcePictureLoadForId) { SparseArray<Bitmap> bitmaps = new SparseArray<>(mUsers.size()); final int N = mUsers.size(); for (int i = 0; i < N; i++) { UserRecord r = mUsers.get(i); if (r == null || r.info == null || r.info.id == forcePictureLoadForId || r.picture == null) { continue; } bitmaps.put(r.info.id, r.picture); } new AsyncTask<SparseArray<Bitmap>, Void, ArrayList<UserRecord>>() { @SuppressWarnings("unchecked") @Override protected ArrayList<UserRecord> doInBackground(Void... params) { protected ArrayList<UserRecord> doInBackground(SparseArray<Bitmap>... params) { final SparseArray<Bitmap> bitmaps = params[0]; List<UserInfo> infos = mUserManager.getUsers(true); if (infos == null) { return null; Loading @@ -87,8 +111,11 @@ public class UserSwitcherController { guestRecord = new UserRecord(info, null /* picture */, true /* isGuest */, isCurrent); } else if (!info.isManagedProfile()) { records.add(new UserRecord(info, mUserManager.getUserIcon(info.id), false /* isGuest */, isCurrent)); Bitmap picture = bitmaps.get(info.id); if (picture == null) { picture = mUserManager.getUserIcon(info.id); } records.add(new UserRecord(info, picture, false /* isGuest */, isCurrent)); } } Loading @@ -109,7 +136,7 @@ public class UserSwitcherController { notifyAdapters(); } } }.execute((Void[])null); }.execute((SparseArray)bitmaps); } private void notifyAdapters() { Loading @@ -134,9 +161,16 @@ public class UserSwitcherController { } if (ActivityManager.getCurrentUser() == id) { if (record.isGuest) { exitGuest(id); } return; } switchToUserId(id); } private void switchToUserId(int id) { try { WindowManagerGlobal.getWindowManagerService().lockNow(null); ActivityManagerNative.getDefault().switchUser(id); Loading @@ -145,6 +179,12 @@ public class UserSwitcherController { } } private void exitGuest(int id) { // TODO: show confirmation dialog switchToUserId(UserHandle.USER_OWNER); mUserManager.removeUser(id); } private BroadcastReceiver mReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { Loading @@ -153,15 +193,20 @@ public class UserSwitcherController { final int N = mUsers.size(); for (int i = 0; i < N; i++) { UserRecord record = mUsers.get(i); if (record.info == null) continue; boolean shouldBeCurrent = record.info.id == currentId; if (record.isCurrent != shouldBeCurrent) { mUsers.set(i, record.copyWithIsCurrent(shouldBeCurrent)); } } notifyAdapters(); } else { refreshUsers(); } int forcePictureLoadForId = UserHandle.USER_NULL; if (Intent.ACTION_USER_INFO_CHANGED.equals(intent.getAction())) { forcePictureLoadForId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL); } refreshUsers(forcePictureLoadForId); } }; Loading Loading @@ -195,12 +240,25 @@ public class UserSwitcherController { @Override public long getItemId(int position) { return mController.mUsers.get(position).info.id; return position; } public void switchTo(UserRecord record) { mController.switchTo(record); } public String getName(Context context, UserRecord item) { if (item.isGuest) { if (item.isCurrent) { return context.getString(R.string.guest_exit_guest); } else { return context.getString( item.info == null ? R.string.guest_new_guest : R.string.guest_nickname); } } else { return item.info.name; } } } public static final class UserRecord { Loading