19abca5e9f88c47579f8334c6c48741a259185b9bJason Monk/*
29abca5e9f88c47579f8334c6c48741a259185b9bJason Monk * Copyright (C) 2014 The Android Open Source Project
39abca5e9f88c47579f8334c6c48741a259185b9bJason Monk *
49abca5e9f88c47579f8334c6c48741a259185b9bJason Monk * Licensed under the Apache License, Version 2.0 (the "License");
59abca5e9f88c47579f8334c6c48741a259185b9bJason Monk * you may not use this file except in compliance with the License.
69abca5e9f88c47579f8334c6c48741a259185b9bJason Monk * You may obtain a copy of the License at
79abca5e9f88c47579f8334c6c48741a259185b9bJason Monk *
89abca5e9f88c47579f8334c6c48741a259185b9bJason Monk *      http://www.apache.org/licenses/LICENSE-2.0
99abca5e9f88c47579f8334c6c48741a259185b9bJason Monk *
109abca5e9f88c47579f8334c6c48741a259185b9bJason Monk * Unless required by applicable law or agreed to in writing, software
119abca5e9f88c47579f8334c6c48741a259185b9bJason Monk * distributed under the License is distributed on an "AS IS" BASIS,
129abca5e9f88c47579f8334c6c48741a259185b9bJason Monk * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139abca5e9f88c47579f8334c6c48741a259185b9bJason Monk * See the License for the specific language governing permissions and
149abca5e9f88c47579f8334c6c48741a259185b9bJason Monk * limitations under the License
159abca5e9f88c47579f8334c6c48741a259185b9bJason Monk */
169abca5e9f88c47579f8334c6c48741a259185b9bJason Monk
179abca5e9f88c47579f8334c6c48741a259185b9bJason Monkpackage com.android.systemui.statusbar.policy;
189abca5e9f88c47579f8334c6c48741a259185b9bJason Monk
199abca5e9f88c47579f8334c6c48741a259185b9bJason Monkimport android.app.ActivityManager;
209abca5e9f88c47579f8334c6c48741a259185b9bJason Monkimport android.content.BroadcastReceiver;
219abca5e9f88c47579f8334c6c48741a259185b9bJason Monkimport android.content.Context;
229abca5e9f88c47579f8334c6c48741a259185b9bJason Monkimport android.content.Intent;
239abca5e9f88c47579f8334c6c48741a259185b9bJason Monkimport android.content.IntentFilter;
249abca5e9f88c47579f8334c6c48741a259185b9bJason Monkimport android.content.pm.PackageManager;
259abca5e9f88c47579f8334c6c48741a259185b9bJason Monkimport android.content.pm.UserInfo;
269abca5e9f88c47579f8334c6c48741a259185b9bJason Monkimport android.content.res.Resources;
279abca5e9f88c47579f8334c6c48741a259185b9bJason Monkimport android.database.Cursor;
289abca5e9f88c47579f8334c6c48741a259185b9bJason Monkimport android.graphics.Bitmap;
299abca5e9f88c47579f8334c6c48741a259185b9bJason Monkimport android.graphics.drawable.Drawable;
309abca5e9f88c47579f8334c6c48741a259185b9bJason Monkimport android.os.AsyncTask;
319abca5e9f88c47579f8334c6c48741a259185b9bJason Monkimport android.os.RemoteException;
329abca5e9f88c47579f8334c6c48741a259185b9bJason Monkimport android.os.UserHandle;
339abca5e9f88c47579f8334c6c48741a259185b9bJason Monkimport android.os.UserManager;
349abca5e9f88c47579f8334c6c48741a259185b9bJason Monkimport android.provider.ContactsContract;
359abca5e9f88c47579f8334c6c48741a259185b9bJason Monkimport android.util.Log;
369abca5e9f88c47579f8334c6c48741a259185b9bJason Monk
379abca5e9f88c47579f8334c6c48741a259185b9bJason Monkimport com.android.internal.util.UserIcons;
389abca5e9f88c47579f8334c6c48741a259185b9bJason Monkimport com.android.settingslib.drawable.UserIconDrawable;
399abca5e9f88c47579f8334c6c48741a259185b9bJason Monkimport com.android.systemui.R;
409abca5e9f88c47579f8334c6c48741a259185b9bJason Monkimport com.android.systemui.statusbar.policy.UserInfoController.OnUserInfoChangedListener;
419abca5e9f88c47579f8334c6c48741a259185b9bJason Monk
429abca5e9f88c47579f8334c6c48741a259185b9bJason Monkimport java.util.ArrayList;
439abca5e9f88c47579f8334c6c48741a259185b9bJason Monk
449abca5e9f88c47579f8334c6c48741a259185b9bJason Monkpublic class UserInfoControllerImpl implements UserInfoController {
459abca5e9f88c47579f8334c6c48741a259185b9bJason Monk
469abca5e9f88c47579f8334c6c48741a259185b9bJason Monk    private static final String TAG = "UserInfoController";
479abca5e9f88c47579f8334c6c48741a259185b9bJason Monk
489abca5e9f88c47579f8334c6c48741a259185b9bJason Monk    private final Context mContext;
499abca5e9f88c47579f8334c6c48741a259185b9bJason Monk    private final ArrayList<OnUserInfoChangedListener> mCallbacks =
509abca5e9f88c47579f8334c6c48741a259185b9bJason Monk            new ArrayList<OnUserInfoChangedListener>();
519abca5e9f88c47579f8334c6c48741a259185b9bJason Monk    private AsyncTask<Void, Void, UserInfoQueryResult> mUserInfoTask;
529abca5e9f88c47579f8334c6c48741a259185b9bJason Monk
539abca5e9f88c47579f8334c6c48741a259185b9bJason Monk    private String mUserName;
549abca5e9f88c47579f8334c6c48741a259185b9bJason Monk    private Drawable mUserDrawable;
559abca5e9f88c47579f8334c6c48741a259185b9bJason Monk    private String mUserAccount;
569abca5e9f88c47579f8334c6c48741a259185b9bJason Monk
579abca5e9f88c47579f8334c6c48741a259185b9bJason Monk    public UserInfoControllerImpl(Context context) {
589abca5e9f88c47579f8334c6c48741a259185b9bJason Monk        mContext = context;
599abca5e9f88c47579f8334c6c48741a259185b9bJason Monk        IntentFilter filter = new IntentFilter();
609abca5e9f88c47579f8334c6c48741a259185b9bJason Monk        filter.addAction(Intent.ACTION_USER_SWITCHED);
619abca5e9f88c47579f8334c6c48741a259185b9bJason Monk        mContext.registerReceiver(mReceiver, filter);
629abca5e9f88c47579f8334c6c48741a259185b9bJason Monk
639abca5e9f88c47579f8334c6c48741a259185b9bJason Monk        IntentFilter profileFilter = new IntentFilter();
649abca5e9f88c47579f8334c6c48741a259185b9bJason Monk        profileFilter.addAction(ContactsContract.Intents.ACTION_PROFILE_CHANGED);
659abca5e9f88c47579f8334c6c48741a259185b9bJason Monk        profileFilter.addAction(Intent.ACTION_USER_INFO_CHANGED);
669abca5e9f88c47579f8334c6c48741a259185b9bJason Monk        mContext.registerReceiverAsUser(mProfileReceiver, UserHandle.ALL, profileFilter,
679abca5e9f88c47579f8334c6c48741a259185b9bJason Monk                null, null);
689abca5e9f88c47579f8334c6c48741a259185b9bJason Monk    }
699abca5e9f88c47579f8334c6c48741a259185b9bJason Monk
709abca5e9f88c47579f8334c6c48741a259185b9bJason Monk    public void addCallback(OnUserInfoChangedListener callback) {
719abca5e9f88c47579f8334c6c48741a259185b9bJason Monk        mCallbacks.add(callback);
729abca5e9f88c47579f8334c6c48741a259185b9bJason Monk        callback.onUserInfoChanged(mUserName, mUserDrawable, mUserAccount);
739abca5e9f88c47579f8334c6c48741a259185b9bJason Monk    }
749abca5e9f88c47579f8334c6c48741a259185b9bJason Monk
759abca5e9f88c47579f8334c6c48741a259185b9bJason Monk    public void removeCallback(OnUserInfoChangedListener callback) {
769abca5e9f88c47579f8334c6c48741a259185b9bJason Monk        mCallbacks.remove(callback);
779abca5e9f88c47579f8334c6c48741a259185b9bJason Monk    }
789abca5e9f88c47579f8334c6c48741a259185b9bJason Monk
799abca5e9f88c47579f8334c6c48741a259185b9bJason Monk    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
809abca5e9f88c47579f8334c6c48741a259185b9bJason Monk        @Override
819abca5e9f88c47579f8334c6c48741a259185b9bJason Monk        public void onReceive(Context context, Intent intent) {
829abca5e9f88c47579f8334c6c48741a259185b9bJason Monk            final String action = intent.getAction();
839abca5e9f88c47579f8334c6c48741a259185b9bJason Monk            if (Intent.ACTION_USER_SWITCHED.equals(action)) {
849abca5e9f88c47579f8334c6c48741a259185b9bJason Monk                reloadUserInfo();
859abca5e9f88c47579f8334c6c48741a259185b9bJason Monk            }
869abca5e9f88c47579f8334c6c48741a259185b9bJason Monk        }
879abca5e9f88c47579f8334c6c48741a259185b9bJason Monk    };
889abca5e9f88c47579f8334c6c48741a259185b9bJason Monk
899abca5e9f88c47579f8334c6c48741a259185b9bJason Monk    private final BroadcastReceiver mProfileReceiver = new BroadcastReceiver() {
909abca5e9f88c47579f8334c6c48741a259185b9bJason Monk        @Override
919abca5e9f88c47579f8334c6c48741a259185b9bJason Monk        public void onReceive(Context context, Intent intent) {
929abca5e9f88c47579f8334c6c48741a259185b9bJason Monk            final String action = intent.getAction();
939abca5e9f88c47579f8334c6c48741a259185b9bJason Monk            if (ContactsContract.Intents.ACTION_PROFILE_CHANGED.equals(action) ||
949abca5e9f88c47579f8334c6c48741a259185b9bJason Monk                    Intent.ACTION_USER_INFO_CHANGED.equals(action)) {
959abca5e9f88c47579f8334c6c48741a259185b9bJason Monk                try {
969abca5e9f88c47579f8334c6c48741a259185b9bJason Monk                    final int currentUser = ActivityManager.getService().getCurrentUser().id;
979abca5e9f88c47579f8334c6c48741a259185b9bJason Monk                    final int changedUser =
989abca5e9f88c47579f8334c6c48741a259185b9bJason Monk                            intent.getIntExtra(Intent.EXTRA_USER_HANDLE, getSendingUserId());
999abca5e9f88c47579f8334c6c48741a259185b9bJason Monk                    if (changedUser == currentUser) {
1009abca5e9f88c47579f8334c6c48741a259185b9bJason Monk                        reloadUserInfo();
1019abca5e9f88c47579f8334c6c48741a259185b9bJason Monk                    }
1029abca5e9f88c47579f8334c6c48741a259185b9bJason Monk                } catch (RemoteException e) {
1039abca5e9f88c47579f8334c6c48741a259185b9bJason Monk                    Log.e(TAG, "Couldn't get current user id for profile change", e);
1049abca5e9f88c47579f8334c6c48741a259185b9bJason Monk                }
1059abca5e9f88c47579f8334c6c48741a259185b9bJason Monk            }
1069abca5e9f88c47579f8334c6c48741a259185b9bJason Monk        }
1079abca5e9f88c47579f8334c6c48741a259185b9bJason Monk    };
1089abca5e9f88c47579f8334c6c48741a259185b9bJason Monk
1099abca5e9f88c47579f8334c6c48741a259185b9bJason Monk    public void reloadUserInfo() {
1109abca5e9f88c47579f8334c6c48741a259185b9bJason Monk        if (mUserInfoTask != null) {
1119abca5e9f88c47579f8334c6c48741a259185b9bJason Monk            mUserInfoTask.cancel(false);
1129abca5e9f88c47579f8334c6c48741a259185b9bJason Monk            mUserInfoTask = null;
1139abca5e9f88c47579f8334c6c48741a259185b9bJason Monk        }
1149abca5e9f88c47579f8334c6c48741a259185b9bJason Monk        queryForUserInformation();
1159abca5e9f88c47579f8334c6c48741a259185b9bJason Monk    }
1169abca5e9f88c47579f8334c6c48741a259185b9bJason Monk
1179abca5e9f88c47579f8334c6c48741a259185b9bJason Monk    private void queryForUserInformation() {
1189abca5e9f88c47579f8334c6c48741a259185b9bJason Monk        Context currentUserContext;
1199abca5e9f88c47579f8334c6c48741a259185b9bJason Monk        UserInfo userInfo;
1209abca5e9f88c47579f8334c6c48741a259185b9bJason Monk        try {
1219abca5e9f88c47579f8334c6c48741a259185b9bJason Monk            userInfo = ActivityManager.getService().getCurrentUser();
1229abca5e9f88c47579f8334c6c48741a259185b9bJason Monk            currentUserContext = mContext.createPackageContextAsUser("android", 0,
1239abca5e9f88c47579f8334c6c48741a259185b9bJason Monk                    new UserHandle(userInfo.id));
1249abca5e9f88c47579f8334c6c48741a259185b9bJason Monk        } catch (PackageManager.NameNotFoundException e) {
1259abca5e9f88c47579f8334c6c48741a259185b9bJason Monk            Log.e(TAG, "Couldn't create user context", e);
1269abca5e9f88c47579f8334c6c48741a259185b9bJason Monk            throw new RuntimeException(e);
1279abca5e9f88c47579f8334c6c48741a259185b9bJason Monk        } catch (RemoteException e) {
1289abca5e9f88c47579f8334c6c48741a259185b9bJason Monk            Log.e(TAG, "Couldn't get user info", e);
1299abca5e9f88c47579f8334c6c48741a259185b9bJason Monk            throw new RuntimeException(e);
1309abca5e9f88c47579f8334c6c48741a259185b9bJason Monk        }
1319abca5e9f88c47579f8334c6c48741a259185b9bJason Monk        final int userId = userInfo.id;
1329abca5e9f88c47579f8334c6c48741a259185b9bJason Monk        final boolean isGuest = userInfo.isGuest();
1339abca5e9f88c47579f8334c6c48741a259185b9bJason Monk        final String userName = userInfo.name;
1349abca5e9f88c47579f8334c6c48741a259185b9bJason Monk
1359abca5e9f88c47579f8334c6c48741a259185b9bJason Monk        final Resources res = mContext.getResources();
1369abca5e9f88c47579f8334c6c48741a259185b9bJason Monk        final int avatarSize = Math.max(
1379abca5e9f88c47579f8334c6c48741a259185b9bJason Monk                res.getDimensionPixelSize(R.dimen.multi_user_avatar_expanded_size),
1389abca5e9f88c47579f8334c6c48741a259185b9bJason Monk                res.getDimensionPixelSize(R.dimen.multi_user_avatar_keyguard_size));
1399abca5e9f88c47579f8334c6c48741a259185b9bJason Monk
1409abca5e9f88c47579f8334c6c48741a259185b9bJason Monk        final Context context = currentUserContext;
1419abca5e9f88c47579f8334c6c48741a259185b9bJason Monk        mUserInfoTask = new AsyncTask<Void, Void, UserInfoQueryResult>() {
1429abca5e9f88c47579f8334c6c48741a259185b9bJason Monk
1439abca5e9f88c47579f8334c6c48741a259185b9bJason Monk            @Override
1449abca5e9f88c47579f8334c6c48741a259185b9bJason Monk            protected UserInfoQueryResult doInBackground(Void... params) {
1459abca5e9f88c47579f8334c6c48741a259185b9bJason Monk                final UserManager um = UserManager.get(mContext);
1469abca5e9f88c47579f8334c6c48741a259185b9bJason Monk
1479abca5e9f88c47579f8334c6c48741a259185b9bJason Monk                // Fall back to the UserManager nickname if we can't read the name from the local
1489abca5e9f88c47579f8334c6c48741a259185b9bJason Monk                // profile below.
1499abca5e9f88c47579f8334c6c48741a259185b9bJason Monk                String name = userName;
1509abca5e9f88c47579f8334c6c48741a259185b9bJason Monk                Drawable avatar = null;
1519abca5e9f88c47579f8334c6c48741a259185b9bJason Monk                Bitmap rawAvatar = um.getUserIcon(userId);
1529abca5e9f88c47579f8334c6c48741a259185b9bJason Monk                if (rawAvatar != null) {
1539abca5e9f88c47579f8334c6c48741a259185b9bJason Monk                    avatar = new UserIconDrawable(avatarSize)
1549abca5e9f88c47579f8334c6c48741a259185b9bJason Monk                            .setIcon(rawAvatar).setBadgeIfManagedUser(mContext, userId).bake();
1559abca5e9f88c47579f8334c6c48741a259185b9bJason Monk                } else {
1569abca5e9f88c47579f8334c6c48741a259185b9bJason Monk                    avatar = UserIcons.getDefaultUserIcon(isGuest? UserHandle.USER_NULL : userId,
1579abca5e9f88c47579f8334c6c48741a259185b9bJason Monk                            /* light= */ true);
1589abca5e9f88c47579f8334c6c48741a259185b9bJason Monk                }
1599abca5e9f88c47579f8334c6c48741a259185b9bJason Monk
1609abca5e9f88c47579f8334c6c48741a259185b9bJason Monk                // If it's a single-user device, get the profile name, since the nickname is not
1619abca5e9f88c47579f8334c6c48741a259185b9bJason Monk                // usually valid
1629abca5e9f88c47579f8334c6c48741a259185b9bJason Monk                if (um.getUsers().size() <= 1) {
1639abca5e9f88c47579f8334c6c48741a259185b9bJason Monk                    // Try and read the display name from the local profile
1649abca5e9f88c47579f8334c6c48741a259185b9bJason Monk                    final Cursor cursor = context.getContentResolver().query(
1659abca5e9f88c47579f8334c6c48741a259185b9bJason Monk                            ContactsContract.Profile.CONTENT_URI, new String[] {
1669abca5e9f88c47579f8334c6c48741a259185b9bJason Monk                                    ContactsContract.CommonDataKinds.Phone._ID,
1679abca5e9f88c47579f8334c6c48741a259185b9bJason Monk                                    ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME
1689abca5e9f88c47579f8334c6c48741a259185b9bJason Monk                            }, null, null, null);
1699abca5e9f88c47579f8334c6c48741a259185b9bJason Monk                    if (cursor != null) {
1709abca5e9f88c47579f8334c6c48741a259185b9bJason Monk                        try {
1719abca5e9f88c47579f8334c6c48741a259185b9bJason Monk                            if (cursor.moveToFirst()) {
1729abca5e9f88c47579f8334c6c48741a259185b9bJason Monk                                name = cursor.getString(cursor.getColumnIndex(
1739abca5e9f88c47579f8334c6c48741a259185b9bJason Monk                                        ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
1749abca5e9f88c47579f8334c6c48741a259185b9bJason Monk                            }
1759abca5e9f88c47579f8334c6c48741a259185b9bJason Monk                        } finally {
1769abca5e9f88c47579f8334c6c48741a259185b9bJason Monk                            cursor.close();
1779abca5e9f88c47579f8334c6c48741a259185b9bJason Monk                        }
1789abca5e9f88c47579f8334c6c48741a259185b9bJason Monk                    }
1799abca5e9f88c47579f8334c6c48741a259185b9bJason Monk                }
1809abca5e9f88c47579f8334c6c48741a259185b9bJason Monk                String userAccount = um.getUserAccount(userId);
1819abca5e9f88c47579f8334c6c48741a259185b9bJason Monk                return new UserInfoQueryResult(name, avatar, userAccount);
1829abca5e9f88c47579f8334c6c48741a259185b9bJason Monk            }
1839abca5e9f88c47579f8334c6c48741a259185b9bJason Monk
1849abca5e9f88c47579f8334c6c48741a259185b9bJason Monk            @Override
1859abca5e9f88c47579f8334c6c48741a259185b9bJason Monk            protected void onPostExecute(UserInfoQueryResult result) {
1869abca5e9f88c47579f8334c6c48741a259185b9bJason Monk                mUserName = result.getName();
1879abca5e9f88c47579f8334c6c48741a259185b9bJason Monk                mUserDrawable = result.getAvatar();
1889abca5e9f88c47579f8334c6c48741a259185b9bJason Monk                mUserAccount = result.getUserAccount();
1899abca5e9f88c47579f8334c6c48741a259185b9bJason Monk                mUserInfoTask = null;
1909abca5e9f88c47579f8334c6c48741a259185b9bJason Monk                notifyChanged();
1919abca5e9f88c47579f8334c6c48741a259185b9bJason Monk            }
1929abca5e9f88c47579f8334c6c48741a259185b9bJason Monk        };
1939abca5e9f88c47579f8334c6c48741a259185b9bJason Monk        mUserInfoTask.execute();
1949abca5e9f88c47579f8334c6c48741a259185b9bJason Monk    }
1959abca5e9f88c47579f8334c6c48741a259185b9bJason Monk
1969abca5e9f88c47579f8334c6c48741a259185b9bJason Monk    private void notifyChanged() {
1979abca5e9f88c47579f8334c6c48741a259185b9bJason Monk        for (OnUserInfoChangedListener listener : mCallbacks) {
1989abca5e9f88c47579f8334c6c48741a259185b9bJason Monk            listener.onUserInfoChanged(mUserName, mUserDrawable, mUserAccount);
1999abca5e9f88c47579f8334c6c48741a259185b9bJason Monk        }
2009abca5e9f88c47579f8334c6c48741a259185b9bJason Monk    }
2019abca5e9f88c47579f8334c6c48741a259185b9bJason Monk
2029abca5e9f88c47579f8334c6c48741a259185b9bJason Monk    public void onDensityOrFontScaleChanged() {
2039abca5e9f88c47579f8334c6c48741a259185b9bJason Monk        reloadUserInfo();
2049abca5e9f88c47579f8334c6c48741a259185b9bJason Monk    }
2059abca5e9f88c47579f8334c6c48741a259185b9bJason Monk
2069abca5e9f88c47579f8334c6c48741a259185b9bJason Monk    private static class UserInfoQueryResult {
2079abca5e9f88c47579f8334c6c48741a259185b9bJason Monk        private String mName;
2089abca5e9f88c47579f8334c6c48741a259185b9bJason Monk        private Drawable mAvatar;
2099abca5e9f88c47579f8334c6c48741a259185b9bJason Monk        private String mUserAccount;
2109abca5e9f88c47579f8334c6c48741a259185b9bJason Monk
2119abca5e9f88c47579f8334c6c48741a259185b9bJason Monk        public UserInfoQueryResult(String name, Drawable avatar, String userAccount) {
2129abca5e9f88c47579f8334c6c48741a259185b9bJason Monk            mName = name;
2139abca5e9f88c47579f8334c6c48741a259185b9bJason Monk            mAvatar = avatar;
2149abca5e9f88c47579f8334c6c48741a259185b9bJason Monk            mUserAccount = userAccount;
2159abca5e9f88c47579f8334c6c48741a259185b9bJason Monk        }
2169abca5e9f88c47579f8334c6c48741a259185b9bJason Monk
2179abca5e9f88c47579f8334c6c48741a259185b9bJason Monk        public String getName() {
2189abca5e9f88c47579f8334c6c48741a259185b9bJason Monk            return mName;
2199abca5e9f88c47579f8334c6c48741a259185b9bJason Monk        }
2209abca5e9f88c47579f8334c6c48741a259185b9bJason Monk
2219abca5e9f88c47579f8334c6c48741a259185b9bJason Monk        public Drawable getAvatar() {
2229abca5e9f88c47579f8334c6c48741a259185b9bJason Monk            return mAvatar;
2239abca5e9f88c47579f8334c6c48741a259185b9bJason Monk        }
2249abca5e9f88c47579f8334c6c48741a259185b9bJason Monk
2259abca5e9f88c47579f8334c6c48741a259185b9bJason Monk        public String getUserAccount() {
2269abca5e9f88c47579f8334c6c48741a259185b9bJason Monk            return mUserAccount;
2279abca5e9f88c47579f8334c6c48741a259185b9bJason Monk        }
2289abca5e9f88c47579f8334c6c48741a259185b9bJason Monk    }
2299abca5e9f88c47579f8334c6c48741a259185b9bJason Monk}
230