• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
17 package com.android.systemui.statusbar.policy;
18 
19 import android.app.ActivityManagerNative;
20 import android.content.BroadcastReceiver;
21 import android.content.Context;
22 import android.content.Intent;
23 import android.content.IntentFilter;
24 import android.content.pm.PackageManager;
25 import android.content.pm.UserInfo;
26 import android.content.res.Resources;
27 import android.database.Cursor;
28 import android.graphics.Bitmap;
29 import android.graphics.drawable.Drawable;
30 import android.os.AsyncTask;
31 import android.os.RemoteException;
32 import android.os.UserHandle;
33 import android.os.UserManager;
34 import android.provider.ContactsContract;
35 import android.util.Log;
36 import android.util.Pair;
37 
38 import com.android.internal.util.UserIcons;
39 import com.android.settingslib.drawable.UserIconDrawable;
40 import com.android.systemui.R;
41 
42 import java.util.ArrayList;
43 
44 public final class UserInfoController {
45 
46     private static final String TAG = "UserInfoController";
47 
48     private final Context mContext;
49     private final ArrayList<OnUserInfoChangedListener> mCallbacks =
50             new ArrayList<OnUserInfoChangedListener>();
51     private AsyncTask<Void, Void, Pair<String, Drawable>> mUserInfoTask;
52 
53     private String mUserName;
54     private Drawable mUserDrawable;
55 
UserInfoController(Context context)56     public UserInfoController(Context context) {
57         mContext = context;
58         IntentFilter filter = new IntentFilter();
59         filter.addAction(Intent.ACTION_USER_SWITCHED);
60         mContext.registerReceiver(mReceiver, filter);
61 
62         IntentFilter profileFilter = new IntentFilter();
63         profileFilter.addAction(ContactsContract.Intents.ACTION_PROFILE_CHANGED);
64         profileFilter.addAction(Intent.ACTION_USER_INFO_CHANGED);
65         mContext.registerReceiverAsUser(mProfileReceiver, UserHandle.ALL, profileFilter,
66                 null, null);
67     }
68 
addListener(OnUserInfoChangedListener callback)69     public void addListener(OnUserInfoChangedListener callback) {
70         mCallbacks.add(callback);
71         callback.onUserInfoChanged(mUserName, mUserDrawable);
72     }
73 
remListener(OnUserInfoChangedListener callback)74     public void remListener(OnUserInfoChangedListener callback) {
75         mCallbacks.remove(callback);
76     }
77 
78     private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
79         @Override
80         public void onReceive(Context context, Intent intent) {
81             final String action = intent.getAction();
82             if (Intent.ACTION_USER_SWITCHED.equals(action)) {
83                 reloadUserInfo();
84             }
85         }
86     };
87 
88     private final BroadcastReceiver mProfileReceiver = new BroadcastReceiver() {
89         @Override
90         public void onReceive(Context context, Intent intent) {
91             final String action = intent.getAction();
92             if (ContactsContract.Intents.ACTION_PROFILE_CHANGED.equals(action) ||
93                     Intent.ACTION_USER_INFO_CHANGED.equals(action)) {
94                 try {
95                     final int currentUser = ActivityManagerNative.getDefault().getCurrentUser().id;
96                     final int changedUser =
97                             intent.getIntExtra(Intent.EXTRA_USER_HANDLE, getSendingUserId());
98                     if (changedUser == currentUser) {
99                         reloadUserInfo();
100                     }
101                 } catch (RemoteException e) {
102                     Log.e(TAG, "Couldn't get current user id for profile change", e);
103                 }
104             }
105         }
106     };
107 
reloadUserInfo()108     public void reloadUserInfo() {
109         if (mUserInfoTask != null) {
110             mUserInfoTask.cancel(false);
111             mUserInfoTask = null;
112         }
113         queryForUserInformation();
114     }
115 
queryForUserInformation()116     private void queryForUserInformation() {
117         Context currentUserContext;
118         UserInfo userInfo;
119         try {
120             userInfo = ActivityManagerNative.getDefault().getCurrentUser();
121             currentUserContext = mContext.createPackageContextAsUser("android", 0,
122                     new UserHandle(userInfo.id));
123         } catch (PackageManager.NameNotFoundException e) {
124             Log.e(TAG, "Couldn't create user context", e);
125             throw new RuntimeException(e);
126         } catch (RemoteException e) {
127             Log.e(TAG, "Couldn't get user info", e);
128             throw new RuntimeException(e);
129         }
130         final int userId = userInfo.id;
131         final boolean isGuest = userInfo.isGuest();
132         final String userName = userInfo.name;
133 
134         final Resources res = mContext.getResources();
135         final int avatarSize = Math.max(
136                 res.getDimensionPixelSize(R.dimen.multi_user_avatar_expanded_size),
137                 res.getDimensionPixelSize(R.dimen.multi_user_avatar_keyguard_size));
138 
139         final Context context = currentUserContext;
140         mUserInfoTask = new AsyncTask<Void, Void, Pair<String, Drawable>>() {
141             @Override
142             protected Pair<String, Drawable> doInBackground(Void... params) {
143                 final UserManager um = UserManager.get(mContext);
144 
145                 // Fall back to the UserManager nickname if we can't read the name from the local
146                 // profile below.
147                 String name = userName;
148                 Drawable avatar = null;
149                 Bitmap rawAvatar = um.getUserIcon(userId);
150                 if (rawAvatar != null) {
151                     avatar = new UserIconDrawable(avatarSize)
152                             .setIcon(rawAvatar).setBadgeIfManagedUser(mContext, userId).bake();
153                 } else {
154                     avatar = UserIcons.getDefaultUserIcon(isGuest? UserHandle.USER_NULL : userId,
155                             /* light= */ true);
156                 }
157 
158                 // If it's a single-user device, get the profile name, since the nickname is not
159                 // usually valid
160                 if (um.getUsers().size() <= 1) {
161                     // Try and read the display name from the local profile
162                     final Cursor cursor = context.getContentResolver().query(
163                             ContactsContract.Profile.CONTENT_URI, new String[] {
164                                     ContactsContract.CommonDataKinds.Phone._ID,
165                                     ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME
166                             }, null, null, null);
167                     if (cursor != null) {
168                         try {
169                             if (cursor.moveToFirst()) {
170                                 name = cursor.getString(cursor.getColumnIndex(
171                                         ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
172                             }
173                         } finally {
174                             cursor.close();
175                         }
176                     }
177                 }
178                 return new Pair<String, Drawable>(name, avatar);
179             }
180 
181             @Override
182             protected void onPostExecute(Pair<String, Drawable> result) {
183                 mUserName = result.first;
184                 mUserDrawable = result.second;
185                 mUserInfoTask = null;
186                 notifyChanged();
187             }
188         };
189         mUserInfoTask.execute();
190     }
191 
notifyChanged()192     private void notifyChanged() {
193         for (OnUserInfoChangedListener listener : mCallbacks) {
194             listener.onUserInfoChanged(mUserName, mUserDrawable);
195         }
196     }
197 
onDensityOrFontScaleChanged()198     public void onDensityOrFontScaleChanged() {
199         reloadUserInfo();
200     }
201 
202     public interface OnUserInfoChangedListener {
onUserInfoChanged(String name, Drawable picture)203         public void onUserInfoChanged(String name, Drawable picture);
204     }
205 }
206