• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
17 package com.android.settings.dashboard.profileselector;
18 
19 import static android.app.admin.DevicePolicyResources.Strings.Settings.PERSONAL_CATEGORY_HEADER;
20 import static android.app.admin.DevicePolicyResources.Strings.Settings.WORK_CATEGORY_HEADER;
21 
22 import android.app.ActivityManager;
23 import android.app.admin.DevicePolicyManager;
24 import android.app.admin.DevicePolicyResourcesManager;
25 import android.content.Context;
26 import android.content.pm.UserInfo;
27 import android.graphics.drawable.Drawable;
28 import android.os.UserHandle;
29 import android.os.UserManager;
30 import android.view.LayoutInflater;
31 import android.view.View;
32 import android.view.ViewGroup;
33 import android.widget.BaseAdapter;
34 import android.widget.ImageView;
35 import android.widget.TextView;
36 
37 import com.android.internal.util.UserIcons;
38 import com.android.internal.widget.RecyclerView;
39 import com.android.settingslib.R;
40 import com.android.settingslib.Utils;
41 
42 import java.util.ArrayList;
43 import java.util.List;
44 import java.util.Objects;
45 
46 /**
47  * Adapter for a spinner that shows a list of users.
48  */
49 public class UserAdapter extends BaseAdapter {
50 
51     /** Holder for user details */
52     public static class UserDetails {
53         private final UserHandle mUserHandle;
54         private final Drawable mIcon;
55         private final String mTitle;
56 
UserDetails(UserHandle userHandle, UserManager um, Context context)57         public UserDetails(UserHandle userHandle, UserManager um, Context context) {
58             mUserHandle = userHandle;
59             UserInfo userInfo = um.getUserInfo(mUserHandle.getIdentifier());
60             int tintColor = Utils.getColorAttrDefaultColor(context,
61                     com.android.internal.R.attr.colorAccentPrimaryVariant);
62             if (userInfo.isManagedProfile()) {
63                 mIcon = context.getPackageManager().getUserBadgeForDensityNoBackground(
64                         userHandle, /* density= */ 0);
65                 mIcon.setTint(tintColor);
66             } else {
67                 mIcon = UserIcons.getDefaultUserIconInColor(context.getResources(), tintColor);
68             }
69             mTitle = getTitle(context);
70         }
71 
getTitle(Context context)72         private String getTitle(Context context) {
73             DevicePolicyManager devicePolicyManager =
74                     Objects.requireNonNull(context.getSystemService(DevicePolicyManager.class));
75             DevicePolicyResourcesManager resources = devicePolicyManager.getResources();
76             int userHandle = mUserHandle.getIdentifier();
77             if (userHandle == UserHandle.USER_CURRENT
78                     || userHandle == ActivityManager.getCurrentUser()) {
79                 return resources.getString(PERSONAL_CATEGORY_HEADER,
80                         () -> context.getString(R.string.category_personal));
81             } else {
82                 return resources.getString(WORK_CATEGORY_HEADER,
83                         () -> context.getString(R.string.category_work));
84             }
85         }
86     }
87 
88     private final ArrayList<UserDetails> mUserDetails;
89     private final LayoutInflater mInflater;
90 
UserAdapter(Context context, ArrayList<UserDetails> users)91     public UserAdapter(Context context, ArrayList<UserDetails> users) {
92         if (users == null) {
93             throw new IllegalArgumentException("A list of user details must be provided");
94         }
95         mUserDetails = users;
96         mInflater = context.getSystemService(LayoutInflater.class);
97     }
98 
getUserHandle(int position)99     public UserHandle getUserHandle(int position) {
100         if (position < 0 || position >= mUserDetails.size()) {
101             return null;
102         }
103         return mUserDetails.get(position).mUserHandle;
104     }
105 
106     @Override
getView(int position, View convertView, ViewGroup parent)107     public View getView(int position, View convertView, ViewGroup parent) {
108         ViewHolder holder;
109         if (convertView != null) {
110             holder = (ViewHolder) convertView.getTag();
111         } else {
112             convertView = mInflater.inflate(R.layout.user_preference, parent, false);
113             holder = new ViewHolder(convertView);
114             convertView.setTag(holder);
115         }
116         bindViewHolder(holder, position);
117         return convertView;
118     }
119 
bindViewHolder(ViewHolder holder, int position)120     private void bindViewHolder(ViewHolder holder, int position) {
121         UserDetails userDetails = getItem(position);
122         holder.getIconView().setImageDrawable(userDetails.mIcon);
123         holder.setTitle(userDetails.mTitle);
124     }
125 
126     @Override
getCount()127     public int getCount() {
128         return mUserDetails.size();
129     }
130 
131     @Override
getItem(int position)132     public UserAdapter.UserDetails getItem(int position) {
133         return mUserDetails.get(position);
134     }
135 
136     @Override
getItemId(int position)137     public long getItemId(int position) {
138         return mUserDetails.get(position).mUserHandle.getIdentifier();
139     }
140 
createRecyclerViewAdapter( OnClickListener onClickListener)141     private RecyclerView.Adapter<ViewHolder> createRecyclerViewAdapter(
142             OnClickListener onClickListener) {
143         return new RecyclerView.Adapter<ViewHolder>() {
144             @Override
145             public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
146                 View view = LayoutInflater.from(parent.getContext())
147                         .inflate(R.layout.user_select_item, parent, false);
148 
149                 return new ViewHolder(view, onClickListener);
150             }
151 
152             @Override
153             public void onBindViewHolder(ViewHolder holder, int position) {
154                 UserAdapter.this.bindViewHolder(holder, position);
155             }
156 
157             @Override
158             public int getItemCount() {
159                 return getCount();
160             }
161         };
162     }
163 
164     /**
165      * Creates a {@link UserAdapter} if there is more than one profile on the device.
166      *
167      * <p> The adapter can be used to populate a spinner that switches between the different
168      * profiles.
169      *
170      * @return a {@link UserAdapter} or null if there is only one profile.
171      */
172     public static UserAdapter createUserSpinnerAdapter(UserManager userManager, Context context) {
173         List<UserHandle> userProfiles = userManager.getUserProfiles();
174         if (userProfiles.size() < 2) {
175             return null;
176         }
177 
178         UserHandle myUserHandle = new UserHandle(UserHandle.myUserId());
179         // The first option should be the current profile
180         userProfiles.remove(myUserHandle);
181         userProfiles.add(0, myUserHandle);
182 
183         return createUserAdapter(userManager, context, userProfiles);
184     }
185 
186     /**
187      * Creates a {@link RecyclerView} adapter which be used to populate a {@link RecyclerView} that
188      * select one of the different profiles.
189      */
190     public static RecyclerView.Adapter<ViewHolder> createUserRecycleViewAdapter(
191             Context context, List<UserHandle> userProfiles, OnClickListener onClickListener) {
192         UserManager systemService = context.getSystemService(UserManager.class);
193         return createUserAdapter(systemService, context, userProfiles)
194                 .createRecyclerViewAdapter(onClickListener);
195     }
196 
197     private static UserAdapter createUserAdapter(
198             UserManager userManager, Context context, List<UserHandle> userProfiles) {
199         ArrayList<UserDetails> userDetails = new ArrayList<>(userProfiles.size());
200         for (UserHandle userProfile : userProfiles) {
201             userDetails.add(new UserDetails(userProfile, userManager, context));
202         }
203         return new UserAdapter(context, userDetails);
204     }
205 
206     static class ViewHolder extends RecyclerView.ViewHolder {
207         private final ImageView mIconView;
208         private final TextView mTitleView;
209         private final View mButtonView;
210 
211         private ViewHolder(View view) {
212             super(view);
213             mIconView = view.findViewById(android.R.id.icon);
214             mTitleView = view.findViewById(android.R.id.title);
215             mButtonView = view.findViewById(R.id.button);
216         }
217 
218         private ViewHolder(View view, OnClickListener onClickListener) {
219             this(view);
220             if (mButtonView != null) {
221                 mButtonView.setOnClickListener(v -> onClickListener.onClick(getAdapterPosition()));
222             }
223         }
224 
225         private ImageView getIconView() {
226             return mIconView;
227         }
228 
229         private void setTitle(CharSequence title) {
230             mTitleView.setText(title);
231             if (mButtonView != null) {
232                 mButtonView.setContentDescription(title);
233             }
234         }
235     }
236 
237     /**
238      * Interface definition for a callback to be invoked when a user is clicked.
239      */
240     public interface OnClickListener {
241         /**
242          * Called when a user has been clicked.
243          */
244         void onClick(int position);
245     }
246 }
247