blob: f1e2302ceda240d32988a9e4b908d09d8471e860 [file] [log] [blame]
Aarthi Balachanderd8bf2492018-03-30 11:15:59 -07001/*
2 * Copyright (C) 2018 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.car;
18
Aarthi Balachanderd8bf2492018-03-30 11:15:59 -070019import android.content.Context;
20import android.content.pm.UserInfo;
Aarthi Balachander608b6e32018-04-11 18:41:52 -070021import android.content.res.ColorStateList;
Aarthi Balachanderd8bf2492018-03-30 11:15:59 -070022import android.content.res.Resources;
jovanake4ce3cc2018-04-19 12:17:12 -070023import android.graphics.Bitmap;
Aarthi Balachanderd8bf2492018-03-30 11:15:59 -070024import android.os.AsyncTask;
jovanake4ce3cc2018-04-19 12:17:12 -070025import android.os.UserHandle;
Aarthi Balachanderd8bf2492018-03-30 11:15:59 -070026import android.support.v7.widget.RecyclerView;
Aarthi Balachanderd8bf2492018-03-30 11:15:59 -070027import android.util.AttributeSet;
28import android.view.LayoutInflater;
29import android.view.View;
30import android.view.ViewGroup;
31import android.widget.ImageView;
32import android.widget.TextView;
33
Aarthi Balachander608b6e32018-04-11 18:41:52 -070034import androidx.car.widget.PagedListView;
35
jovanake4ce3cc2018-04-19 12:17:12 -070036import com.android.internal.util.UserIcons;
Aarthi Balachanderd8bf2492018-03-30 11:15:59 -070037import com.android.settingslib.users.UserManagerHelper;
38import com.android.systemui.R;
Aarthi Balachanderd8bf2492018-03-30 11:15:59 -070039
40import java.util.ArrayList;
41import java.util.List;
42
43/**
44 * Displays a GridLayout with icons for the users in the system to allow switching between users.
45 * One of the uses of this is for the lock screen in auto.
46 */
Aarthi Balachander608b6e32018-04-11 18:41:52 -070047public class UserGridRecyclerView extends PagedListView implements
Aarthi Balachanderd8bf2492018-03-30 11:15:59 -070048 UserManagerHelper.OnUsersUpdateListener {
Aarthi Balachanderd8bf2492018-03-30 11:15:59 -070049 private UserSelectionListener mUserSelectionListener;
50 private UserAdapter mAdapter;
51 private UserManagerHelper mUserManagerHelper;
52 private Context mContext;
53
54 public UserGridRecyclerView(Context context, AttributeSet attrs) {
55 super(context, attrs);
Aarthi Balachanderd8bf2492018-03-30 11:15:59 -070056 mContext = context;
57 mUserManagerHelper = new UserManagerHelper(mContext);
58 }
59
60 /**
61 * Register listener for any update to the users
62 */
63 @Override
64 public void onFinishInflate() {
Aarthi Balachander608b6e32018-04-11 18:41:52 -070065 super.onFinishInflate();
Aarthi Balachanderd8bf2492018-03-30 11:15:59 -070066 mUserManagerHelper.registerOnUsersUpdateListener(this);
67 }
68
69 /**
70 * Unregisters listener checking for any change to the users
71 */
72 @Override
73 public void onDetachedFromWindow() {
Aarthi Balachander608b6e32018-04-11 18:41:52 -070074 super.onDetachedFromWindow();
Aarthi Balachanderd8bf2492018-03-30 11:15:59 -070075 mUserManagerHelper.unregisterOnUsersUpdateListener();
76 }
77
78 /**
79 * Initializes the adapter that populates the grid layout
80 *
81 * @return the adapter
82 */
83 public void buildAdapter() {
84 List<UserRecord> userRecords = createUserRecords(mUserManagerHelper
85 .getAllUsers());
86 mAdapter = new UserAdapter(mContext, userRecords);
87 super.setAdapter(mAdapter);
88 }
89
Aarthi Balachanderd8bf2492018-03-30 11:15:59 -070090 private List<UserRecord> createUserRecords(List<UserInfo> userInfoList) {
91 List<UserRecord> userRecords = new ArrayList<>();
92 for (UserInfo userInfo : userInfoList) {
jovanak80b48592018-04-11 17:09:53 -070093 if (userInfo.isGuest()) {
94 // Don't display guests in the switcher.
95 continue;
96 }
jovanak0535abc2018-04-10 15:14:50 -070097 boolean isForeground = mUserManagerHelper.getForegroundUserId() == userInfo.id;
jovanak80b48592018-04-11 17:09:53 -070098 UserRecord record = new UserRecord(userInfo, false /* isStartGuestSession */,
jovanak0535abc2018-04-10 15:14:50 -070099 false /* isAddUser */, isForeground);
Aarthi Balachanderd8bf2492018-03-30 11:15:59 -0700100 userRecords.add(record);
101 }
102
jovanak0535abc2018-04-10 15:14:50 -0700103 // Add guest user record if the foreground user is not a guest
jovanak82029ae2018-04-02 16:40:15 -0700104 if (!mUserManagerHelper.foregroundUserIsGuestUser()) {
Aarthi Balachanderd8bf2492018-03-30 11:15:59 -0700105 userRecords.add(addGuestUserRecord());
106 }
107
jovanak0535abc2018-04-10 15:14:50 -0700108 // Add add user record if the foreground user can add users
jovanak82029ae2018-04-02 16:40:15 -0700109 if (mUserManagerHelper.foregroundUserCanAddUsers()) {
Aarthi Balachanderd8bf2492018-03-30 11:15:59 -0700110 userRecords.add(addUserRecord());
111 }
112
113 return userRecords;
114 }
115
116 /**
117 * Create guest user record
118 */
119 private UserRecord addGuestUserRecord() {
120 UserInfo userInfo = new UserInfo();
121 userInfo.name = mContext.getString(R.string.car_guest);
jovanak80b48592018-04-11 17:09:53 -0700122 return new UserRecord(userInfo, true /* isStartGuestSession */,
jovanak0535abc2018-04-10 15:14:50 -0700123 false /* isAddUser */, false /* isForeground */);
Aarthi Balachanderd8bf2492018-03-30 11:15:59 -0700124 }
125
126 /**
127 * Create add user record
128 */
129 private UserRecord addUserRecord() {
130 UserInfo userInfo = new UserInfo();
131 userInfo.name = mContext.getString(R.string.car_add_user);
jovanak80b48592018-04-11 17:09:53 -0700132 return new UserRecord(userInfo, false /* isStartGuestSession */,
jovanak0535abc2018-04-10 15:14:50 -0700133 true /* isAddUser */, false /* isForeground */);
Aarthi Balachanderd8bf2492018-03-30 11:15:59 -0700134 }
135
136 public void setUserSelectionListener(UserSelectionListener userSelectionListener) {
137 mUserSelectionListener = userSelectionListener;
138 }
139
Aarthi Balachanderd8bf2492018-03-30 11:15:59 -0700140 @Override
141 public void onUsersUpdate() {
142 mAdapter.clearUsers();
143 mAdapter.updateUsers(createUserRecords(mUserManagerHelper.getAllUsers()));
144 mAdapter.notifyDataSetChanged();
145 }
146
147 /**
148 * Adapter to populate the grid layout with the available user profiles
149 */
150 public final class UserAdapter extends RecyclerView.Adapter<UserAdapter.UserAdapterViewHolder> {
151
152 private final Context mContext;
153 private List<UserRecord> mUsers;
Aarthi Balachanderd8bf2492018-03-30 11:15:59 -0700154 private final Resources mRes;
155 private final String mGuestName;
156 private final String mNewUserName;
157
158 public UserAdapter(Context context, List<UserRecord> users) {
159 mRes = context.getResources();
160 mContext = context;
161 updateUsers(users);
Aarthi Balachanderd8bf2492018-03-30 11:15:59 -0700162 mGuestName = mRes.getString(R.string.car_guest);
163 mNewUserName = mRes.getString(R.string.car_new_user);
164 }
165
166 public void clearUsers() {
167 mUsers.clear();
168 }
169
170 public void updateUsers(List<UserRecord> users) {
171 mUsers = users;
172 }
173
174 @Override
175 public UserAdapterViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
176 View view = LayoutInflater.from(mContext)
177 .inflate(R.layout.car_fullscreen_user_pod, parent, false);
178 view.setAlpha(1f);
179 view.bringToFront();
180 return new UserAdapterViewHolder(view);
181 }
182
183 @Override
184 public void onBindViewHolder(UserAdapterViewHolder holder, int position) {
185 UserRecord userRecord = mUsers.get(position);
jovanake4ce3cc2018-04-19 12:17:12 -0700186 holder.mUserAvatarImageView.setImageBitmap(getUserRecordIcon(userRecord));
Aarthi Balachanderd8bf2492018-03-30 11:15:59 -0700187 holder.mUserNameTextView.setText(userRecord.mInfo.name);
188 holder.mView.setOnClickListener(v -> {
189 if (userRecord == null) {
190 return;
191 }
192
Aarthi Balachander608b6e32018-04-11 18:41:52 -0700193 // Disable button so it cannot be clicked multiple times
194 holder.mView.setEnabled(false);
195
Aarthi Balachanderd8bf2492018-03-30 11:15:59 -0700196 // Notify the listener which user was selected
197 if (mUserSelectionListener != null) {
198 mUserSelectionListener.onUserSelected(userRecord);
199 }
200
jovanak80b48592018-04-11 17:09:53 -0700201 // If the user selects Guest, start the guest session.
202 if (userRecord.mIsStartGuestSession) {
Aarthi Balachanderd8bf2492018-03-30 11:15:59 -0700203 mUserManagerHelper.switchToGuest(mGuestName);
204 return;
205 }
206
207 // If the user wants to add a user, start task to add new user
208 if (userRecord.mIsAddUser) {
209 new AddNewUserTask().execute(mNewUserName);
210 return;
211 }
212
213 // If the user doesn't want to be a guest or add a user, switch to the user selected
214 mUserManagerHelper.switchToUser(userRecord.mInfo);
215 });
216
217 }
218
jovanake4ce3cc2018-04-19 12:17:12 -0700219 private Bitmap getUserRecordIcon(UserRecord userRecord) {
220 if (userRecord.mIsStartGuestSession) {
221 return UserIcons.convertToBitmap(UserIcons.getDefaultUserIcon(
222 mContext.getResources(), UserHandle.USER_NULL, false));
223 }
224
225 if (userRecord.mIsAddUser) {
226 return UserIcons.convertToBitmap(mContext
227 .getDrawable(R.drawable.car_add_circle_round));
228 }
229
230 return mUserManagerHelper.getUserIcon(userRecord.mInfo);
231 }
232
Aarthi Balachanderd8bf2492018-03-30 11:15:59 -0700233 private class AddNewUserTask extends AsyncTask<String, Void, UserInfo> {
234
235 @Override
236 protected UserInfo doInBackground(String... userNames) {
237 return mUserManagerHelper.createNewUser(userNames[0]);
238 }
239
240 @Override
241 protected void onPreExecute() {
242 }
243
244 @Override
245 protected void onPostExecute(UserInfo user) {
246 if (user != null) {
247 mUserManagerHelper.switchToUser(user);
248 }
249 }
250 }
251
252 @Override
253 public int getItemCount() {
254 return mUsers.size();
255 }
256
Aarthi Balachanderd8bf2492018-03-30 11:15:59 -0700257 public class UserAdapterViewHolder extends RecyclerView.ViewHolder {
258
259 public ImageView mUserAvatarImageView;
260 public TextView mUserNameTextView;
261 public View mView;
262
263 public UserAdapterViewHolder(View view) {
264 super(view);
265 mView = view;
266 mUserAvatarImageView = (ImageView) view.findViewById(R.id.user_avatar);
267 mUserNameTextView = (TextView) view.findViewById(R.id.user_name);
268 }
269 }
270 }
271
272 /**
273 * Object wrapper class for the userInfo. Use it to distinguish if a profile is a
jovanak0535abc2018-04-10 15:14:50 -0700274 * guest profile, add user profile, or the foreground user.
Aarthi Balachanderd8bf2492018-03-30 11:15:59 -0700275 */
276 public static final class UserRecord {
277
278 public final UserInfo mInfo;
jovanak80b48592018-04-11 17:09:53 -0700279 public final boolean mIsStartGuestSession;
Aarthi Balachanderd8bf2492018-03-30 11:15:59 -0700280 public final boolean mIsAddUser;
jovanak0535abc2018-04-10 15:14:50 -0700281 public final boolean mIsForeground;
Aarthi Balachanderd8bf2492018-03-30 11:15:59 -0700282
jovanak80b48592018-04-11 17:09:53 -0700283 public UserRecord(UserInfo userInfo, boolean isStartGuestSession, boolean isAddUser,
jovanak0535abc2018-04-10 15:14:50 -0700284 boolean isForeground) {
Aarthi Balachanderd8bf2492018-03-30 11:15:59 -0700285 mInfo = userInfo;
jovanak80b48592018-04-11 17:09:53 -0700286 mIsStartGuestSession = isStartGuestSession;
Aarthi Balachanderd8bf2492018-03-30 11:15:59 -0700287 mIsAddUser = isAddUser;
jovanak0535abc2018-04-10 15:14:50 -0700288 mIsForeground = isForeground;
Aarthi Balachanderd8bf2492018-03-30 11:15:59 -0700289 }
290 }
291
292 /**
293 * Listener used to notify when a user has been selected
294 */
295 interface UserSelectionListener {
296
297 void onUserSelected(UserRecord record);
298 }
299}