KeyguardUserSwitcher.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 com.android.systemui.BitmapHelper;
20import com.android.systemui.R;
21import com.android.systemui.statusbar.phone.StatusBarHeaderView;
22import com.android.systemui.statusbar.phone.UserAvatarView;
23
24import android.app.ActivityManagerNative;
25import android.content.Context;
26import android.content.pm.UserInfo;
27import android.graphics.Bitmap;
28import android.os.AsyncTask;
29import android.os.RemoteException;
30import android.os.UserManager;
31import android.util.Log;
32import android.view.LayoutInflater;
33import android.view.View;
34import android.view.ViewGroup;
35import android.view.ViewStub;
36import android.view.WindowManagerGlobal;
37import android.widget.TextView;
38
39import java.util.ArrayList;
40import java.util.List;
41
42/**
43 * Manages the user switcher on the Keyguard.
44 */
45public class KeyguardUserSwitcher implements View.OnClickListener {
46
47    private static final String TAG = "KeyguardUserSwitcher";
48
49    private final Context mContext;
50    private final ViewGroup mUserSwitcher;
51    private final UserManager mUserManager;
52    private final StatusBarHeaderView mHeader;
53
54    public KeyguardUserSwitcher(Context context, ViewStub userSwitcher,
55            StatusBarHeaderView header) {
56        mContext = context;
57        if (context.getResources().getBoolean(R.bool.config_keyguardUserSwitcher)) {
58            mUserSwitcher = (ViewGroup) userSwitcher.inflate();
59            mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
60            mHeader = header;
61            refresh();
62        } else {
63            mUserSwitcher = null;
64            mUserManager = null;
65            mHeader = null;
66        }
67    }
68
69    public void setKeyguard(boolean keyguard) {
70        if (mUserSwitcher != null) {
71            // TODO: Cache showUserSwitcherOnKeyguard().
72            if (keyguard && showUserSwitcherOnKeyguard()) {
73                show();
74                refresh();
75            } else {
76                hide();
77            }
78        }
79    }
80
81    /**
82     * @return true if the user switcher should be shown on the lock screen.
83     * @see android.os.UserManager#isUserSwitcherEnabled()
84     */
85    private boolean showUserSwitcherOnKeyguard() {
86        // TODO: Set isEdu. The edu provisioning process can add settings to Settings.Global.
87        boolean isEdu = false;
88        if (isEdu) {
89            return true;
90        }
91        List<UserInfo> users = mUserManager.getUsers(true /* excludeDying */);
92        int N = users.size();
93        int switchableUsers = 0;
94        for (int i = 0; i < N; i++) {
95            if (users.get(i).supportsSwitchTo()) {
96                switchableUsers++;
97            }
98        }
99        return switchableUsers > 1;
100    }
101
102    public void show() {
103        if (mUserSwitcher != null) {
104            // TODO: animate
105            mUserSwitcher.setVisibility(View.VISIBLE);
106            mHeader.setKeyguardUserSwitcherShowing(true);
107        }
108    }
109
110    private void hide() {
111        if (mUserSwitcher != null) {
112            // TODO: animate
113            mUserSwitcher.setVisibility(View.GONE);
114            mHeader.setKeyguardUserSwitcherShowing(false);
115        }
116    }
117
118    private void refresh() {
119        if (mUserSwitcher != null) {
120            new AsyncTask<Void, Void, ArrayList<UserData>>() {
121                @Override
122                protected ArrayList<UserData> doInBackground(Void... params) {
123                    return loadUsers();
124                }
125
126                @Override
127                protected void onPostExecute(ArrayList<UserData> userInfos) {
128                    bind(userInfos);
129                }
130            }.execute((Void[]) null);
131        }
132    }
133
134    private void bind(ArrayList<UserData> userList) {
135        mUserSwitcher.removeAllViews();
136        int N = userList.size();
137        for (int i = 0; i < N; i++) {
138            mUserSwitcher.addView(inflateUser(userList.get(i)));
139        }
140        // TODO: add Guest
141        // TODO: add (+) button
142    }
143
144    private View inflateUser(UserData user) {
145        View v = LayoutInflater.from(mUserSwitcher.getContext()).inflate(
146                R.layout.keyguard_user_switcher_item, mUserSwitcher, false);
147        TextView name = (TextView) v.findViewById(R.id.name);
148        UserAvatarView picture = (UserAvatarView) v.findViewById(R.id.picture);
149        name.setText(user.userInfo.name);
150        picture.setActivated(user.isCurrent);
151        if (user.userInfo.isGuest()) {
152            picture.setDrawable(mContext.getResources().getDrawable(R.drawable.ic_account_circle));
153        } else {
154            picture.setBitmap(user.userIcon);
155        }
156        v.setOnClickListener(this);
157        v.setTag(user.userInfo);
158        // TODO: mark which user is current for accessibility.
159        return v;
160    }
161
162    @Override
163    public void onClick(View v) {
164        switchUser(((UserInfo)v.getTag()).id);
165    }
166
167    // TODO: Factor out logic below and share with QS implementation.
168
169    private ArrayList<UserData> loadUsers() {
170        ArrayList<UserInfo> users = (ArrayList<UserInfo>) mUserManager
171                .getUsers(true /* excludeDying */);
172        int N = users.size();
173        ArrayList<UserData> result = new ArrayList<>(N);
174        int currentUser = -1;
175        try {
176            currentUser = ActivityManagerNative.getDefault().getCurrentUser().id;
177        } catch (RemoteException e) {
178            Log.e(TAG, "Couln't get current user.", e);
179        }
180        final int avatarSize
181                = mContext.getResources().getDimensionPixelSize(R.dimen.max_avatar_size);
182        for (int i = 0; i < N; i++) {
183            UserInfo user = users.get(i);
184            if (user.supportsSwitchTo()) {
185                boolean isCurrent = user.id == currentUser;
186                final Bitmap picture = BitmapHelper.createCircularClip(
187                        mUserManager.getUserIcon(user.id),
188                        avatarSize, avatarSize);
189                result.add(new UserData(user, picture, isCurrent));
190            }
191        }
192        return result;
193    }
194
195    private void switchUser(int userId) {
196        try {
197            WindowManagerGlobal.getWindowManagerService().lockNow(null);
198            ActivityManagerNative.getDefault().switchUser(userId);
199        } catch (RemoteException e) {
200            Log.e(TAG, "Couldn't switch user.", e);
201        }
202    }
203
204    private static class UserData {
205        final UserInfo userInfo;
206        final Bitmap userIcon;
207        final boolean isCurrent;
208
209        UserData(UserInfo userInfo, Bitmap userIcon, boolean isCurrent) {
210            this.userInfo = userInfo;
211            this.userIcon = userIcon;
212            this.isCurrent = isCurrent;
213        }
214    }
215}
216