UserInfoController.java revision 4d75c079f35d85b687d8349e5e2940447d01198e
1/* 2 * Copyright (C) 2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License 15 */ 16 17package com.android.systemui.statusbar.policy; 18 19import android.app.ActivityManagerNative; 20import android.bluetooth.BluetoothAdapter; 21import android.content.BroadcastReceiver; 22import android.content.Context; 23import android.content.Intent; 24import android.content.IntentFilter; 25import android.content.pm.PackageManager; 26import android.content.pm.UserInfo; 27import android.database.Cursor; 28import android.graphics.Bitmap; 29import android.graphics.BitmapShader; 30import android.graphics.Canvas; 31import android.graphics.Matrix; 32import android.graphics.Paint; 33import android.graphics.PorterDuff; 34import android.graphics.PorterDuffXfermode; 35import android.graphics.Rect; 36import android.graphics.RectF; 37import android.graphics.Shader; 38import android.graphics.drawable.BitmapDrawable; 39import android.graphics.drawable.Drawable; 40import android.hardware.display.DisplayManager; 41import android.os.AsyncTask; 42import android.os.RemoteException; 43import android.os.UserHandle; 44import android.os.UserManager; 45import android.provider.ContactsContract; 46import android.security.KeyChain; 47import android.util.Log; 48import android.util.Pair; 49 50import com.android.internal.view.RotationPolicy; 51import com.android.systemui.BitmapHelper; 52import com.android.systemui.R; 53 54import java.util.ArrayList; 55import java.util.concurrent.CopyOnWriteArrayList; 56 57public final class UserInfoController { 58 59 private static final String TAG = "UserInfoController"; 60 61 private final Context mContext; 62 private final ArrayList<OnUserInfoChangedListener> mCallbacks = 63 new ArrayList<OnUserInfoChangedListener>(); 64 private AsyncTask<Void, Void, Pair<String, Drawable>> mUserInfoTask; 65 66 private boolean mUseDefaultAvatar; 67 private String mUserName; 68 private Drawable mUserDrawable; 69 70 public UserInfoController(Context context) { 71 mContext = context; 72 IntentFilter filter = new IntentFilter(); 73 filter.addAction(Intent.ACTION_USER_SWITCHED); 74 filter.addAction(Intent.ACTION_CONFIGURATION_CHANGED); 75 mContext.registerReceiver(mReceiver, filter); 76 77 IntentFilter profileFilter = new IntentFilter(); 78 profileFilter.addAction(ContactsContract.Intents.ACTION_PROFILE_CHANGED); 79 profileFilter.addAction(Intent.ACTION_USER_INFO_CHANGED); 80 mContext.registerReceiverAsUser(mProfileReceiver, UserHandle.ALL, profileFilter, 81 null, null); 82 } 83 84 public void addListener(OnUserInfoChangedListener callback) { 85 mCallbacks.add(callback); 86 } 87 88 private final BroadcastReceiver mReceiver = new BroadcastReceiver() { 89 @Override 90 public void onReceive(Context context, Intent intent) { 91 final String action = intent.getAction(); 92 if (Intent.ACTION_USER_SWITCHED.equals(action)) { 93 reloadUserInfo(); 94 } else if (Intent.ACTION_CONFIGURATION_CHANGED.equals(action)) { 95 if (mUseDefaultAvatar) { 96 reloadUserInfo(); 97 } 98 } 99 } 100 }; 101 102 private final BroadcastReceiver mProfileReceiver = new BroadcastReceiver() { 103 @Override 104 public void onReceive(Context context, Intent intent) { 105 final String action = intent.getAction(); 106 if (ContactsContract.Intents.ACTION_PROFILE_CHANGED.equals(action) || 107 Intent.ACTION_USER_INFO_CHANGED.equals(action)) { 108 try { 109 final int currentUser = ActivityManagerNative.getDefault().getCurrentUser().id; 110 final int changedUser = 111 intent.getIntExtra(Intent.EXTRA_USER_HANDLE, getSendingUserId()); 112 if (changedUser == currentUser) { 113 reloadUserInfo(); 114 } 115 } catch (RemoteException e) { 116 Log.e(TAG, "Couldn't get current user id for profile change", e); 117 } 118 } 119 } 120 }; 121 122 public void reloadUserInfo() { 123 if (mUserInfoTask != null) { 124 mUserInfoTask.cancel(false); 125 mUserInfoTask = null; 126 } 127 queryForUserInformation(); 128 } 129 130 private void queryForUserInformation() { 131 Context currentUserContext; 132 UserInfo userInfo; 133 try { 134 userInfo = ActivityManagerNative.getDefault().getCurrentUser(); 135 currentUserContext = mContext.createPackageContextAsUser("android", 0, 136 new UserHandle(userInfo.id)); 137 } catch (PackageManager.NameNotFoundException e) { 138 Log.e(TAG, "Couldn't create user context", e); 139 throw new RuntimeException(e); 140 } catch (RemoteException e) { 141 Log.e(TAG, "Couldn't get user info", e); 142 throw new RuntimeException(e); 143 } 144 final int userId = userInfo.id; 145 final String userName = userInfo.name; 146 final int avatarSize 147 = mContext.getResources().getDimensionPixelSize(R.dimen.max_avatar_size); 148 149 final Context context = currentUserContext; 150 mUserInfoTask = new AsyncTask<Void, Void, Pair<String, Drawable>>() { 151 @Override 152 protected Pair<String, Drawable> doInBackground(Void... params) { 153 final UserManager um = UserManager.get(mContext); 154 155 // Fall back to the UserManager nickname if we can't read the name from the local 156 // profile below. 157 String name = userName; 158 Drawable avatar = null; 159 Bitmap rawAvatar = um.getUserIcon(userId); 160 if (rawAvatar != null) { 161 avatar = new BitmapDrawable(mContext.getResources(), 162 BitmapHelper.createCircularClip(rawAvatar, avatarSize, avatarSize)); 163 } else { 164 avatar = mContext.getResources().getDrawable(R.drawable.ic_account_circle); 165 mUseDefaultAvatar = true; 166 } 167 168 // If it's a single-user device, get the profile name, since the nickname is not 169 // usually valid 170 if (um.getUsers().size() <= 1) { 171 // Try and read the display name from the local profile 172 final Cursor cursor = context.getContentResolver().query( 173 ContactsContract.Profile.CONTENT_URI, new String[] { 174 ContactsContract.CommonDataKinds.Phone._ID, ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME}, 175 null, null, null); 176 if (cursor != null) { 177 try { 178 if (cursor.moveToFirst()) { 179 name = cursor.getString(cursor.getColumnIndex( 180 ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME)); 181 } 182 } finally { 183 cursor.close(); 184 } 185 } 186 } 187 return new Pair<String, Drawable>(name, avatar); 188 } 189 190 @Override 191 protected void onPostExecute(Pair<String, Drawable> result) { 192 mUserName = result.first; 193 mUserDrawable = result.second; 194 mUserInfoTask = null; 195 notifyChanged(); 196 } 197 }; 198 mUserInfoTask.execute(); 199 } 200 201 private void notifyChanged() { 202 for (OnUserInfoChangedListener listener : mCallbacks) { 203 listener.onUserInfoChanged(mUserName, mUserDrawable); 204 } 205 } 206 207 public interface OnUserInfoChangedListener { 208 public void onUserInfoChanged(String name, Drawable picture); 209 } 210} 211