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