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 17 package com.android.systemui.car.statusbar; 18 19 import android.content.BroadcastReceiver; 20 import android.content.Context; 21 import android.content.Intent; 22 import android.content.IntentFilter; 23 import android.content.pm.UserInfo; 24 import android.graphics.drawable.Drawable; 25 import android.os.UserHandle; 26 import android.os.UserManager; 27 import android.view.View; 28 import android.widget.ImageView; 29 import android.widget.TextView; 30 31 import androidx.annotation.MainThread; 32 import androidx.annotation.VisibleForTesting; 33 34 import com.android.systemui.R; 35 import com.android.systemui.broadcast.BroadcastDispatcher; 36 import com.android.systemui.car.userswitcher.UserIconProvider; 37 import com.android.systemui.dagger.SysUISingleton; 38 import com.android.systemui.settings.UserTracker; 39 40 import java.util.ArrayList; 41 42 import javax.inject.Inject; 43 44 /** 45 * Controls TextView and ImageView for the current logged in user. 46 * User icon image consists of the first letter of user name. 47 * Therefore, the user name and icon have to be changed at the same time. 48 */ 49 @SysUISingleton 50 public class UserNameViewController { 51 private static final String TAG = "UserNameViewController"; 52 53 private Context mContext; 54 private UserTracker mUserTracker; 55 private UserManager mUserManager; 56 private BroadcastDispatcher mBroadcastDispatcher; 57 private String mLastUserName; 58 59 @VisibleForTesting 60 UserIconProvider mUserIconProvider; 61 62 @VisibleForTesting 63 ArrayList<TextView> mUserNameViews = new ArrayList<TextView>(); 64 @VisibleForTesting 65 ArrayList<ImageView> mUserIconViews = new ArrayList<ImageView>(); 66 67 private final BroadcastReceiver mUserUpdateReceiver = new BroadcastReceiver() { 68 @Override 69 public void onReceive(Context context, Intent intent) { 70 updateUser(mUserTracker.getUserId()); 71 } 72 }; 73 74 private boolean mUserLifecycleListenerRegistered = false; 75 76 private final UserTracker.Callback mUserChangedCallback = 77 new UserTracker.Callback() { 78 @Override 79 public void onUserChanged(int newUser, Context userContext) { 80 updateUser(newUser); 81 } 82 }; 83 84 @Inject UserNameViewController(Context context, UserTracker userTracker, UserManager userManager, BroadcastDispatcher broadcastDispatcher)85 public UserNameViewController(Context context, UserTracker userTracker, 86 UserManager userManager, BroadcastDispatcher broadcastDispatcher) { 87 mContext = context; 88 mUserTracker = userTracker; 89 mUserManager = userManager; 90 mBroadcastDispatcher = broadcastDispatcher; 91 mUserIconProvider = new UserIconProvider(); 92 } 93 94 /** 95 * Find the {@link ImageView} or {@link TextView} for the user from a view 96 * and if found set them with the current user name and icon. 97 */ 98 @MainThread addUserNameView(View v)99 public void addUserNameView(View v) { 100 TextView userNameView = v.findViewById(R.id.user_name_text); 101 if (userNameView != null) { 102 ImageView userIconView = v.findViewById(R.id.user_icon); 103 104 if (mUserNameViews.size() == 0 105 || (userIconView != null && mUserIconViews.size() == 0)) { 106 registerForUserChangeEvents(); 107 } 108 109 if (!mUserNameViews.contains(userNameView)) { 110 mUserNameViews.add(userNameView); 111 } 112 113 if (userIconView != null && !mUserIconViews.contains(userIconView)) { 114 mUserIconViews.add(userIconView); 115 } 116 117 updateUser(mUserTracker.getUserId()); 118 } 119 } 120 121 /** 122 * Find the {@link ImageView} or {@link TextView} for the user from a view and if found remove 123 * them from the user views list. 124 */ removeUserNameView(View v)125 public void removeUserNameView(View v) { 126 TextView userNameView = v.findViewById(R.id.user_name_text); 127 if (userNameView != null && mUserNameViews.contains(userNameView)) { 128 mUserNameViews.remove(userNameView); 129 } 130 131 ImageView userIconView = v.findViewById(R.id.user_icon); 132 if (userIconView != null && mUserIconViews.contains(userIconView)) { 133 mUserIconViews.remove(userIconView); 134 } 135 } 136 137 /** 138 * Clean up the controller and unregister receiver. 139 */ removeAll()140 public void removeAll() { 141 mUserNameViews.clear(); 142 mUserIconViews.clear(); 143 if (mUserLifecycleListenerRegistered) { 144 mBroadcastDispatcher.unregisterReceiver(mUserUpdateReceiver); 145 mUserTracker.removeCallback(mUserChangedCallback); 146 mUserLifecycleListenerRegistered = false; 147 } 148 } 149 registerForUserChangeEvents()150 private void registerForUserChangeEvents() { 151 // Register for user switching 152 if (!mUserLifecycleListenerRegistered) { 153 mUserTracker.addCallback(mUserChangedCallback, mContext.getMainExecutor()); 154 mUserLifecycleListenerRegistered = true; 155 } 156 // Also register for user info changing 157 IntentFilter filter = new IntentFilter(); 158 filter.addAction(Intent.ACTION_USER_INFO_CHANGED); 159 mBroadcastDispatcher.registerReceiver(mUserUpdateReceiver, filter, /* executor= */ null, 160 UserHandle.ALL); 161 } 162 updateUser(int userId)163 private void updateUser(int userId) { 164 UserInfo currentUserInfo = mUserManager.getUserInfo(userId); 165 166 // Update user name 167 for (int i = 0; i < mUserNameViews.size(); i++) { 168 mUserNameViews.get(i).setText(currentUserInfo.name); 169 } 170 171 // Update user icon with the first letter of the user name 172 if (mLastUserName == null || !mLastUserName.equals(currentUserInfo.name)) { 173 mLastUserName = currentUserInfo.name; 174 mUserIconProvider.setRoundedUserIcon(currentUserInfo, mContext); 175 } 176 177 for (int i = 0; i < mUserIconViews.size(); i++) { 178 updateUserIcon(mUserIconViews.get(i), currentUserInfo); 179 } 180 } 181 updateUserIcon(ImageView userIconView, UserInfo currentUserInfo)182 private void updateUserIcon(ImageView userIconView, UserInfo currentUserInfo) { 183 Drawable circleIcon = mUserIconProvider.getRoundedUserIcon(currentUserInfo, mContext); 184 userIconView.setImageDrawable(circleIcon); 185 } 186 } 187