1 /*
2  * Copyright (C) 2020 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 package com.google.android.car.kitchensink.users;
17 
18 import android.annotation.NonNull;
19 import android.annotation.Nullable;
20 import android.annotation.UserIdInt;
21 import android.content.Context;
22 import android.content.pm.UserInfo;
23 import android.os.UserHandle;
24 import android.text.TextUtils;
25 import android.util.AttributeSet;
26 import android.util.Log;
27 import android.view.View;
28 import android.widget.AdapterView;
29 import android.widget.ArrayAdapter;
30 import android.widget.Spinner;
31 
32 import java.util.Arrays;
33 import java.util.List;
34 
35 /**
36  * Custom {@link Spinner} to show a list of Android users.
37  */
38 public final class UsersSpinner extends Spinner {
39 
40     private static final String TAG = UsersSpinner.class.getSimpleName();
41 
42     private UserInfo[] mUsers;
43     private String[] mEntries;
44     private OnUserSelectedListener mListener;
45 
UsersSpinner(Context context, AttributeSet attrs)46     public UsersSpinner(Context context, AttributeSet attrs) {
47         super(context, attrs);
48     }
49 
50     /**
51      * Initializes the spinner with the given users.
52      */
init(List<UserInfo> users)53     public void init(List<UserInfo> users) {
54         Log.v(TAG, "init(): " + users.size() + " users (" + users + ")");
55         int size = users.size();
56         mUsers = new UserInfo[size];
57         users.toArray(mUsers);
58         mEntries = new String[size];
59         for (int i = 0; i < size; i++) {
60             UserInfo user = mUsers[i];
61             StringBuilder entry = new StringBuilder().append(user.id).append('-');
62             if (!TextUtils.isEmpty(user.name)) {
63                 entry.append(user.name);
64             } else {
65                 if (user.id == UserHandle.USER_SYSTEM) {
66                     entry.append("SYSTEM");
67                 } else {
68                     entry.append(UserInfo.flagsToString(user.flags));
69                 }
70             }
71             mEntries[i] = entry.toString();
72         }
73         Log.v(TAG, "initializing spinner with " + size + " entries: " + Arrays.toString(mEntries));
74         setAdapter(new ArrayAdapter<String>(getContext(), android.R.layout.simple_spinner_item,
75                 mEntries));
76         setOnItemSelectedListener(new OnItemSelectedListener() {
77             @Override
78             public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
79                 UserInfo user = getSelectedUser();
80                 Log.v(TAG, "onItemSelected(): index=" + position + ", user=" + user);
81                 if (mListener != null) {
82                     mListener.onUserSelected(user);
83                 }
84             }
85 
86             @Override
87             public void onNothingSelected(AdapterView<?> parent) {
88                 Log.v(TAG, "nothing selected");
89             }
90         });
91     }
92 
93     /**
94      * Gets the selected user id, or {@link UserHandle#USER_NULL}.
95      */
getSelectedUserId()96     public @UserIdInt int getSelectedUserId() {
97         UserInfo user = getSelectedUser();
98         return user == null ? UserHandle.USER_NULL : user.id;
99     }
100 
101     /**
102      * Gets the selected user info.
103      */
getSelectedUser()104     public @Nullable UserInfo getSelectedUser() {
105         int selectedIndex = getSelectedItemPosition();
106         Log.v(TAG, "getSelectedUser(): index=" + selectedIndex);
107         try {
108             return mUsers[selectedIndex];
109         } catch (RuntimeException e) {
110             Log.e(TAG, "getSelectedUserId(): failed to get user at index " + selectedIndex
111                     + ". Users: " + Arrays.toString(mUsers));
112             return null;
113         }
114     }
115 
116     /**
117      * Sets the listener called when the spinner value change.
118      */
setOnUserSelectedListener(@ullable OnUserSelectedListener listener)119     public void setOnUserSelectedListener(@Nullable OnUserSelectedListener listener) {
120         mListener = listener;
121     }
122 
123     /**
124      * Listener called when the spinner value change.
125      */
126     public interface OnUserSelectedListener {
127         /**
128          * Callback for the selected user.
129          */
onUserSelected(@onNull UserInfo user)130         void onUserSelected(@NonNull UserInfo user);
131     }
132 }
133