From 3d878be53d033365318733b84b764cd5b4e6357a Mon Sep 17 00:00:00 2001 From: Jorim Jaggi Date: Sat, 10 May 2014 03:22:32 +0200 Subject: [PATCH] Implement new multi-user affordance. Change-Id: I6d7e6cc9893bc7d4fd87431e8e364500af42f107 --- .../res/layout/status_bar_expanded_header.xml | 16 +- .../res/layout/user_switcher_host.xml | 3 +- .../statusbar/phone/MultiUserSwitch.java | 90 ++++++++ .../phone/NotificationPanelView.java | 1 + .../statusbar/phone/PhoneStatusBar.java | 7 + .../statusbar/phone/StatusBarHeaderView.java | 16 ++ .../statusbar/policy/UserInfoController.java | 215 ++++++++++++++++++ 7 files changed, 344 insertions(+), 4 deletions(-) create mode 100644 packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitch.java create mode 100644 packages/SystemUI/src/com/android/systemui/statusbar/policy/UserInfoController.java diff --git a/packages/SystemUI/res/layout/status_bar_expanded_header.xml b/packages/SystemUI/res/layout/status_bar_expanded_header.xml index ac81e4e1bda8a..c9da22140e517 100644 --- a/packages/SystemUI/res/layout/status_bar_expanded_header.xml +++ b/packages/SystemUI/res/layout/status_bar_expanded_header.xml @@ -25,7 +25,7 @@ android:orientation="horizontal" android:gravity="center_vertical" android:baselineAligned="false" - android:elevation="14dp" + android:elevation="10dp" > + + + + android:background="#dd000000" + android:elevation="12dp"> mCallbacks = + new ArrayList(); + private AsyncTask> mUserInfoTask; + + private boolean mUseDefaultAvatar; + private String mUserName; + private Drawable mUserDrawable; + + public UserInfoController(Context context) { + mContext = context; + IntentFilter filter = new IntentFilter(); + filter.addAction(Intent.ACTION_USER_SWITCHED); + filter.addAction(Intent.ACTION_CONFIGURATION_CHANGED); + mContext.registerReceiver(mReceiver, filter); + + IntentFilter profileFilter = new IntentFilter(); + profileFilter.addAction(ContactsContract.Intents.ACTION_PROFILE_CHANGED); + profileFilter.addAction(Intent.ACTION_USER_INFO_CHANGED); + mContext.registerReceiverAsUser(mProfileReceiver, UserHandle.ALL, profileFilter, + null, null); + } + + public void addListener(OnUserInfoChangedListener callback) { + mCallbacks.add(callback); + } + + private final BroadcastReceiver mReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + final String action = intent.getAction(); + if (Intent.ACTION_USER_SWITCHED.equals(action)) { + reloadUserInfo(); + } else if (Intent.ACTION_CONFIGURATION_CHANGED.equals(action)) { + if (mUseDefaultAvatar) { + reloadUserInfo(); + } + } + } + }; + + private final BroadcastReceiver mProfileReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + final String action = intent.getAction(); + if (ContactsContract.Intents.ACTION_PROFILE_CHANGED.equals(action) || + Intent.ACTION_USER_INFO_CHANGED.equals(action)) { + try { + final int currentUser = ActivityManagerNative.getDefault().getCurrentUser().id; + final int changedUser = + intent.getIntExtra(Intent.EXTRA_USER_HANDLE, getSendingUserId()); + if (changedUser == currentUser) { + reloadUserInfo(); + } + } catch (RemoteException e) { + Log.e(TAG, "Couldn't get current user id for profile change", e); + } + } + } + }; + + public void reloadUserInfo() { + if (mUserInfoTask != null) { + mUserInfoTask.cancel(false); + mUserInfoTask = null; + } + queryForUserInformation(); + } + + private Bitmap circularClip(Bitmap input) { + Bitmap output = Bitmap.createBitmap(input.getWidth(), + input.getHeight(), Bitmap.Config.ARGB_8888); + Canvas canvas = new Canvas(output); + final Paint paint = new Paint(); + paint.setShader(new BitmapShader(input, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP)); + paint.setAntiAlias(true); + canvas.drawCircle(input.getWidth() / 2, input.getHeight() / 2, input.getWidth() / 2, paint); + return output; + } + + private void queryForUserInformation() { + Context currentUserContext; + UserInfo userInfo; + try { + userInfo = ActivityManagerNative.getDefault().getCurrentUser(); + currentUserContext = mContext.createPackageContextAsUser("android", 0, + new UserHandle(userInfo.id)); + } catch (PackageManager.NameNotFoundException e) { + Log.e(TAG, "Couldn't create user context", e); + throw new RuntimeException(e); + } catch (RemoteException e) { + Log.e(TAG, "Couldn't get user info", e); + throw new RuntimeException(e); + } + final int userId = userInfo.id; + final String userName = userInfo.name; + + final Context context = currentUserContext; + mUserInfoTask = new AsyncTask>() { + @Override + protected Pair doInBackground(Void... params) { + final UserManager um = UserManager.get(mContext); + + // Fall back to the UserManager nickname if we can't read the name from the local + // profile below. + String name = userName; + Drawable avatar = null; + Bitmap rawAvatar = um.getUserIcon(userId); + if (rawAvatar != null) { + avatar = new BitmapDrawable(mContext.getResources(), circularClip(rawAvatar)); + } else { + avatar = mContext.getResources().getDrawable(R.drawable.ic_qs_default_user); + mUseDefaultAvatar = true; + } + + // If it's a single-user device, get the profile name, since the nickname is not + // usually valid + if (um.getUsers().size() <= 1) { + // Try and read the display name from the local profile + final Cursor cursor = context.getContentResolver().query( + ContactsContract.Profile.CONTENT_URI, new String[] { + ContactsContract.CommonDataKinds.Phone._ID, ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME}, + null, null, null); + if (cursor != null) { + try { + if (cursor.moveToFirst()) { + name = cursor.getString(cursor.getColumnIndex( + ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME)); + } + } finally { + cursor.close(); + } + } + } + return new Pair(name, avatar); + } + + @Override + protected void onPostExecute(Pair result) { + mUserName = result.first; + mUserDrawable = result.second; + mUserInfoTask = null; + notifyChanged(); + } + }; + mUserInfoTask.execute(); + } + + private void notifyChanged() { + for (OnUserInfoChangedListener listener : mCallbacks) { + listener.onUserInfoChanged(mUserName, mUserDrawable); + } + } + + public interface OnUserInfoChangedListener { + public void onUserInfoChanged(String name, Drawable picture); + } +}