13d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi/*
23d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi * Copyright (C) 2014 The Android Open Source Project
33d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi *
43d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi * Licensed under the Apache License, Version 2.0 (the "License");
53d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi * you may not use this file except in compliance with the License.
63d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi * You may obtain a copy of the License at
73d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi *
83d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi *      http://www.apache.org/licenses/LICENSE-2.0
93d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi *
103d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi * Unless required by applicable law or agreed to in writing, software
113d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi * distributed under the License is distributed on an "AS IS" BASIS,
123d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
133d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi * See the License for the specific language governing permissions and
143d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi * limitations under the License
153d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi */
163d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi
173d878be53d033365318733b84b764cd5b4e6357aJorim Jaggipackage com.android.systemui.statusbar.policy;
183d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi
193d878be53d033365318733b84b764cd5b4e6357aJorim Jaggiimport android.app.ActivityManagerNative;
203d878be53d033365318733b84b764cd5b4e6357aJorim Jaggiimport android.content.BroadcastReceiver;
213d878be53d033365318733b84b764cd5b4e6357aJorim Jaggiimport android.content.Context;
223d878be53d033365318733b84b764cd5b4e6357aJorim Jaggiimport android.content.Intent;
233d878be53d033365318733b84b764cd5b4e6357aJorim Jaggiimport android.content.IntentFilter;
243d878be53d033365318733b84b764cd5b4e6357aJorim Jaggiimport android.content.pm.PackageManager;
253d878be53d033365318733b84b764cd5b4e6357aJorim Jaggiimport android.content.pm.UserInfo;
262b154a9ec32915fe4a0dbc648344586fb5fa0261Adrian Roosimport android.content.res.Resources;
273d878be53d033365318733b84b764cd5b4e6357aJorim Jaggiimport android.database.Cursor;
283d878be53d033365318733b84b764cd5b4e6357aJorim Jaggiimport android.graphics.Bitmap;
293d878be53d033365318733b84b764cd5b4e6357aJorim Jaggiimport android.graphics.drawable.BitmapDrawable;
303d878be53d033365318733b84b764cd5b4e6357aJorim Jaggiimport android.graphics.drawable.Drawable;
313d878be53d033365318733b84b764cd5b4e6357aJorim Jaggiimport android.os.AsyncTask;
323d878be53d033365318733b84b764cd5b4e6357aJorim Jaggiimport android.os.RemoteException;
333d878be53d033365318733b84b764cd5b4e6357aJorim Jaggiimport android.os.UserHandle;
343d878be53d033365318733b84b764cd5b4e6357aJorim Jaggiimport android.os.UserManager;
353d878be53d033365318733b84b764cd5b4e6357aJorim Jaggiimport android.provider.ContactsContract;
363d878be53d033365318733b84b764cd5b4e6357aJorim Jaggiimport android.util.Log;
373d878be53d033365318733b84b764cd5b4e6357aJorim Jaggiimport android.util.Pair;
383d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi
394d75c079f35d85b687d8349e5e2940447d01198eDan Sandlerimport com.android.systemui.BitmapHelper;
403d878be53d033365318733b84b764cd5b4e6357aJorim Jaggiimport com.android.systemui.R;
4164d4dca63f65e4c7d4a829c85ff6670bdd34e2ebAlexandra Gherghinaimport com.android.internal.util.UserIcons;
423d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi
433d878be53d033365318733b84b764cd5b4e6357aJorim Jaggiimport java.util.ArrayList;
443d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi
453d878be53d033365318733b84b764cd5b4e6357aJorim Jaggipublic final class UserInfoController {
463d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi
473d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi    private static final String TAG = "UserInfoController";
483d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi
493d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi    private final Context mContext;
503d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi    private final ArrayList<OnUserInfoChangedListener> mCallbacks =
513d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi            new ArrayList<OnUserInfoChangedListener>();
523d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi    private AsyncTask<Void, Void, Pair<String, Drawable>> mUserInfoTask;
533d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi
543d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi    private boolean mUseDefaultAvatar;
553d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi    private String mUserName;
563d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi    private Drawable mUserDrawable;
573d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi
583d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi    public UserInfoController(Context context) {
593d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi        mContext = context;
603d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi        IntentFilter filter = new IntentFilter();
613d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi        filter.addAction(Intent.ACTION_USER_SWITCHED);
623d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi        filter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);
633d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi        mContext.registerReceiver(mReceiver, filter);
643d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi
653d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi        IntentFilter profileFilter = new IntentFilter();
663d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi        profileFilter.addAction(ContactsContract.Intents.ACTION_PROFILE_CHANGED);
673d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi        profileFilter.addAction(Intent.ACTION_USER_INFO_CHANGED);
683d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi        mContext.registerReceiverAsUser(mProfileReceiver, UserHandle.ALL, profileFilter,
693d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi                null, null);
703d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi    }
713d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi
723d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi    public void addListener(OnUserInfoChangedListener callback) {
733d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi        mCallbacks.add(callback);
743d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi    }
753d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi
763d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
773d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi        @Override
783d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi        public void onReceive(Context context, Intent intent) {
793d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi            final String action = intent.getAction();
803d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi            if (Intent.ACTION_USER_SWITCHED.equals(action)) {
813d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi                reloadUserInfo();
823d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi            } else if (Intent.ACTION_CONFIGURATION_CHANGED.equals(action)) {
833d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi                if (mUseDefaultAvatar) {
843d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi                    reloadUserInfo();
853d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi                }
863d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi            }
873d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi        }
883d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi    };
893d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi
903d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi    private final BroadcastReceiver mProfileReceiver = new BroadcastReceiver() {
913d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi        @Override
923d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi        public void onReceive(Context context, Intent intent) {
933d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi            final String action = intent.getAction();
943d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi            if (ContactsContract.Intents.ACTION_PROFILE_CHANGED.equals(action) ||
953d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi                    Intent.ACTION_USER_INFO_CHANGED.equals(action)) {
963d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi                try {
973d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi                    final int currentUser = ActivityManagerNative.getDefault().getCurrentUser().id;
983d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi                    final int changedUser =
993d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi                            intent.getIntExtra(Intent.EXTRA_USER_HANDLE, getSendingUserId());
1003d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi                    if (changedUser == currentUser) {
1013d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi                        reloadUserInfo();
1023d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi                    }
1033d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi                } catch (RemoteException e) {
1043d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi                    Log.e(TAG, "Couldn't get current user id for profile change", e);
1053d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi                }
1063d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi            }
1073d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi        }
1083d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi    };
1093d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi
1103d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi    public void reloadUserInfo() {
1113d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi        if (mUserInfoTask != null) {
1123d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi            mUserInfoTask.cancel(false);
1133d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi            mUserInfoTask = null;
1143d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi        }
1153d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi        queryForUserInformation();
1163d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi    }
1173d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi
1183d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi    private void queryForUserInformation() {
1193d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi        Context currentUserContext;
1203d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi        UserInfo userInfo;
1213d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi        try {
1223d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi            userInfo = ActivityManagerNative.getDefault().getCurrentUser();
1233d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi            currentUserContext = mContext.createPackageContextAsUser("android", 0,
1243d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi                    new UserHandle(userInfo.id));
1253d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi        } catch (PackageManager.NameNotFoundException e) {
1263d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi            Log.e(TAG, "Couldn't create user context", e);
1273d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi            throw new RuntimeException(e);
1283d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi        } catch (RemoteException e) {
1293d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi            Log.e(TAG, "Couldn't get user info", e);
1303d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi            throw new RuntimeException(e);
1313d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi        }
1323d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi        final int userId = userInfo.id;
13364d4dca63f65e4c7d4a829c85ff6670bdd34e2ebAlexandra Gherghina        final boolean isGuest = userInfo.isGuest();
1343d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi        final String userName = userInfo.name;
1352b154a9ec32915fe4a0dbc648344586fb5fa0261Adrian Roos
1362b154a9ec32915fe4a0dbc648344586fb5fa0261Adrian Roos        final Resources res = mContext.getResources();
1372b154a9ec32915fe4a0dbc648344586fb5fa0261Adrian Roos        final int avatarSize = Math.max(
1382b154a9ec32915fe4a0dbc648344586fb5fa0261Adrian Roos                res.getDimensionPixelSize(R.dimen.multi_user_avatar_expanded_size),
1392b154a9ec32915fe4a0dbc648344586fb5fa0261Adrian Roos                res.getDimensionPixelSize(R.dimen.multi_user_avatar_keyguard_size));
1403d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi
1413d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi        final Context context = currentUserContext;
1423d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi        mUserInfoTask = new AsyncTask<Void, Void, Pair<String, Drawable>>() {
1433d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi            @Override
1443d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi            protected Pair<String, Drawable> doInBackground(Void... params) {
1453d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi                final UserManager um = UserManager.get(mContext);
1463d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi
1473d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi                // Fall back to the UserManager nickname if we can't read the name from the local
1483d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi                // profile below.
1493d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi                String name = userName;
1503d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi                Drawable avatar = null;
1513d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi                Bitmap rawAvatar = um.getUserIcon(userId);
1523d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi                if (rawAvatar != null) {
1534d75c079f35d85b687d8349e5e2940447d01198eDan Sandler                    avatar = new BitmapDrawable(mContext.getResources(),
1544d75c079f35d85b687d8349e5e2940447d01198eDan Sandler                            BitmapHelper.createCircularClip(rawAvatar, avatarSize, avatarSize));
1553d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi                } else {
15664d4dca63f65e4c7d4a829c85ff6670bdd34e2ebAlexandra Gherghina                    avatar = UserIcons.getDefaultUserIcon(isGuest? UserHandle.USER_NULL : userId,
15764d4dca63f65e4c7d4a829c85ff6670bdd34e2ebAlexandra Gherghina                            /* light= */ true);
1583d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi                    mUseDefaultAvatar = true;
1593d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi                }
1603d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi
1613d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi                // If it's a single-user device, get the profile name, since the nickname is not
1623d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi                // usually valid
1633d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi                if (um.getUsers().size() <= 1) {
1643d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi                    // Try and read the display name from the local profile
1653d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi                    final Cursor cursor = context.getContentResolver().query(
1663d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi                            ContactsContract.Profile.CONTENT_URI, new String[] {
1672b154a9ec32915fe4a0dbc648344586fb5fa0261Adrian Roos                                    ContactsContract.CommonDataKinds.Phone._ID,
1682b154a9ec32915fe4a0dbc648344586fb5fa0261Adrian Roos                                    ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME
1692b154a9ec32915fe4a0dbc648344586fb5fa0261Adrian Roos                            }, null, null, null);
1703d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi                    if (cursor != null) {
1713d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi                        try {
1723d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi                            if (cursor.moveToFirst()) {
1733d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi                                name = cursor.getString(cursor.getColumnIndex(
1743d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi                                        ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
1753d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi                            }
1763d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi                        } finally {
1773d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi                            cursor.close();
1783d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi                        }
1793d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi                    }
1803d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi                }
1813d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi                return new Pair<String, Drawable>(name, avatar);
1823d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi            }
1833d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi
1843d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi            @Override
1853d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi            protected void onPostExecute(Pair<String, Drawable> result) {
1863d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi                mUserName = result.first;
1873d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi                mUserDrawable = result.second;
1883d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi                mUserInfoTask = null;
1893d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi                notifyChanged();
1903d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi            }
1913d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi        };
1923d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi        mUserInfoTask.execute();
1933d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi    }
1943d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi
1953d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi    private void notifyChanged() {
1963d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi        for (OnUserInfoChangedListener listener : mCallbacks) {
1973d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi            listener.onUserInfoChanged(mUserName, mUserDrawable);
1983d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi        }
1993d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi    }
2003d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi
2013d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi    public interface OnUserInfoChangedListener {
2023d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi        public void onUserInfoChanged(String name, Drawable picture);
2033d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi    }
2043d878be53d033365318733b84b764cd5b4e6357aJorim Jaggi}
205