blob: 3ce6905576d282ab86eceb1c410b4c56ca98012b [file] [log] [blame]
/*
* Copyright (C) 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License
*/
package com.android.systemui.statusbar.policy;
import android.app.ActivityManagerNative;
import android.bluetooth.BluetoothAdapter;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.content.pm.UserInfo;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.Shader;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.hardware.display.DisplayManager;
import android.os.AsyncTask;
import android.os.RemoteException;
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.ContactsContract;
import android.security.KeyChain;
import android.util.Log;
import android.util.Pair;
import com.android.internal.view.RotationPolicy;
import com.android.systemui.R;
import java.util.ArrayList;
import java.util.concurrent.CopyOnWriteArrayList;
public final class UserInfoController {
private static final String TAG = "UserInfoController";
private final Context mContext;
private final ArrayList<OnUserInfoChangedListener> mCallbacks =
new ArrayList<OnUserInfoChangedListener>();
private AsyncTask<Void, Void, Pair<String, Drawable>> 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<Void, Void, Pair<String, Drawable>>() {
@Override
protected Pair<String, Drawable> 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_account_circle);
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<String, Drawable>(name, avatar);
}
@Override
protected void onPostExecute(Pair<String, Drawable> 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);
}
}