1 /* 2 * Copyright (C) 2023 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.systemui.car.userpicker; 18 19 import android.car.feature.Flags; 20 import android.content.Context; 21 import android.view.Display; 22 import android.view.LayoutInflater; 23 import android.view.View; 24 import android.view.ViewGroup; 25 import android.widget.FrameLayout; 26 import android.widget.ImageView; 27 import android.widget.TextView; 28 29 import androidx.annotation.ColorInt; 30 import androidx.annotation.NonNull; 31 import androidx.recyclerview.widget.RecyclerView; 32 import androidx.recyclerview.widget.RecyclerView.Adapter; 33 34 import com.android.systemui.R; 35 36 import java.io.PrintWriter; 37 import java.util.List; 38 39 final class UserPickerAdapter extends Adapter<UserPickerAdapter.UserPickerAdapterViewHolder> { 40 private final Context mContext; 41 private final int mDisplayId; 42 private final float mDisabledAlpha; 43 @ColorInt 44 private final int mCurrentUserSubtitleColor; 45 @ColorInt 46 private final int mOtherUserSubtitleColor; 47 private final int mVerticalSpacing; 48 private final int mHorizontalSpacing; 49 private final int mNumCols; 50 51 private List<UserRecord> mUsers; 52 private String mLoggedInText; 53 private String mPrefixOtherSeatLoggedInInfo; 54 private String mStoppingUserText; 55 private String mUnavailableSecureUserText; 56 UserPickerAdapter(Context context)57 UserPickerAdapter(Context context) { 58 mContext = context; 59 mDisplayId = mContext.getDisplayId(); 60 mDisabledAlpha = mContext.getResources().getFloat(R.fraction.user_picker_disabled_alpha); 61 mCurrentUserSubtitleColor = mContext.getResources().getColor( 62 R.color.user_picker_current_login_state_color, mContext.getTheme()); 63 mOtherUserSubtitleColor = mContext.getResources().getColor( 64 R.color.user_picker_other_login_state_color, mContext.getTheme()); 65 mVerticalSpacing = mContext.getResources().getDimensionPixelSize( 66 R.dimen.user_picker_vertical_space_between_users); 67 mHorizontalSpacing = mContext.getResources().getDimensionPixelSize( 68 R.dimen.user_picker_horizontal_space_between_users); 69 mNumCols = mContext.getResources().getInteger(R.integer.user_fullscreen_switcher_num_col); 70 71 updateTexts(); 72 } 73 updateUsers(List<UserRecord> users)74 void updateUsers(List<UserRecord> users) { 75 mUsers = users; 76 } 77 setUserLoggedInInfo(UserPickerAdapterViewHolder holder, UserRecord userRecord)78 private void setUserLoggedInInfo(UserPickerAdapterViewHolder holder, UserRecord userRecord) { 79 if (!userRecord.mIsStopping && !userRecord.mIsLoggedIn) { 80 if (userRecord.mIsSecure && mDisplayId != Display.DEFAULT_DISPLAY 81 && !Flags.supportsSecurePassengerUsers()) { 82 holder.mUserBorderImageView.setVisibility(View.INVISIBLE); 83 holder.mLoggedInTextView.setText(mUnavailableSecureUserText); 84 updateAlpha(holder, /* disabled= */ true); 85 return; 86 } 87 holder.mUserBorderImageView.setVisibility(View.INVISIBLE); 88 holder.mLoggedInTextView.setText(""); 89 updateAlpha(holder, /* disabled= */ false); 90 return; 91 } 92 93 if (userRecord.mIsStopping) { 94 holder.mUserBorderImageView.setVisibility(View.INVISIBLE); 95 holder.mLoggedInTextView.setText(mStoppingUserText); 96 holder.mLoggedInTextView.setTextColor(mOtherUserSubtitleColor); 97 updateAlpha(holder, /* disabled= */ true); 98 } else if (userRecord.mIsLoggedIn) { 99 if (userRecord.mLoggedInDisplay == mDisplayId) { 100 holder.mUserBorderImageView.setVisibility(View.VISIBLE); 101 holder.mLoggedInTextView.setText(mLoggedInText); 102 holder.mLoggedInTextView.setTextColor(mCurrentUserSubtitleColor); 103 updateAlpha(holder, /* disabled= */ false); 104 } else { 105 holder.mUserBorderImageView.setVisibility(View.INVISIBLE); 106 holder.mLoggedInTextView.setText(String.format(mPrefixOtherSeatLoggedInInfo, 107 userRecord.mSeatLocationName)); 108 holder.mLoggedInTextView.setTextColor(mOtherUserSubtitleColor); 109 updateAlpha(holder, /* disabled= */ true); 110 } 111 } 112 } 113 updateAlpha(UserPickerAdapterViewHolder holder, boolean disabled)114 private void updateAlpha(UserPickerAdapterViewHolder holder, boolean disabled) { 115 float alpha = disabled ? mDisabledAlpha : 1.0f; 116 holder.mUserAvatarImageView.setAlpha(alpha); 117 holder.mUserNameTextView.setAlpha(alpha); 118 holder.mLoggedInTextView.setAlpha(alpha); 119 } 120 121 @Override onCreateViewHolder(@onNull ViewGroup parent, int viewType)122 public UserPickerAdapterViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { 123 View view = LayoutInflater.from(mContext) 124 .inflate(R.layout.user_picker_user_pod, parent, false); 125 view.setAlpha(1f); 126 view.bringToFront(); 127 return new UserPickerAdapterViewHolder(view); 128 } 129 130 @Override onBindViewHolder(@onNull UserPickerAdapterViewHolder holder, int position)131 public void onBindViewHolder(@NonNull UserPickerAdapterViewHolder holder, int position) { 132 setItemSpacing(holder.mView, position); 133 UserRecord userRecord = mUsers.get(position); 134 holder.mUserAvatarImageView.setImageDrawable(userRecord.mIcon); 135 holder.mFrame.setBackgroundResource(0); 136 holder.mUserNameTextView.setText(userRecord.mName); 137 setUserLoggedInInfo(holder, userRecord); 138 holder.mView.setOnClickListener(userRecord.mOnClickListener); 139 } 140 141 @Override getItemCount()142 public int getItemCount() { 143 return mUsers != null ? mUsers.size() : 0; 144 } 145 onConfigurationChanged()146 void onConfigurationChanged() { 147 updateTexts(); 148 } 149 updateTexts()150 private void updateTexts() { 151 mLoggedInText = mContext.getString(R.string.logged_in_text); 152 mPrefixOtherSeatLoggedInInfo = mContext 153 .getString(R.string.prefix_logged_in_info_for_other_seat); 154 mStoppingUserText = mContext.getString(R.string.stopping_user_text); 155 mUnavailableSecureUserText = mContext.getString(R.string.unavailable_secure_user_text); 156 } 157 158 // TODO(b/281729191) use RecyclerView.ItemDecoration when supported by CarUiRecyclerView setItemSpacing(View rootItemView, int position)159 private void setItemSpacing(View rootItemView, int position) { 160 ViewGroup.LayoutParams params = rootItemView.getLayoutParams(); 161 if (params instanceof ViewGroup.MarginLayoutParams) { 162 ViewGroup.MarginLayoutParams marginLayoutParams = (ViewGroup.MarginLayoutParams) params; 163 marginLayoutParams.bottomMargin = mVerticalSpacing; 164 165 int splitHorizontalSpacing = mHorizontalSpacing / mNumCols; 166 int col = position % mNumCols; 167 marginLayoutParams.leftMargin = col * splitHorizontalSpacing; 168 marginLayoutParams.rightMargin = (mNumCols - (col + 1)) * splitHorizontalSpacing; 169 170 rootItemView.setLayoutParams(marginLayoutParams); 171 } 172 } 173 dump(@onNull PrintWriter pw)174 void dump(@NonNull PrintWriter pw) { 175 pw.println(" UserRecords : "); 176 for (int i = 0; i < mUsers.size(); i++) { 177 UserRecord userRecord = mUsers.get(i); 178 pw.println(" " + userRecord.toString()); 179 } 180 } 181 182 static final class UserPickerAdapterViewHolder extends RecyclerView.ViewHolder { 183 public final ImageView mUserAvatarImageView; 184 public final TextView mUserNameTextView; 185 public final ImageView mUserBorderImageView; 186 public final TextView mLoggedInTextView; 187 public final View mView; 188 public final FrameLayout mFrame; 189 UserPickerAdapterViewHolder(View view)190 UserPickerAdapterViewHolder(View view) { 191 super(view); 192 mView = view; 193 mUserAvatarImageView = view.findViewById(R.id.user_avatar); 194 mUserNameTextView = view.findViewById(R.id.user_name); 195 mUserBorderImageView = view.findViewById(R.id.user_avatar_border); 196 mLoggedInTextView = view.findViewById(R.id.logged_in_info); 197 mFrame = view.findViewById(R.id.current_user_frame); 198 } 199 } 200 } 201