• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2024 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.users;
18 
19 import android.annotation.UserIdInt;
20 import android.content.BroadcastReceiver;
21 import android.content.Context;
22 import android.content.Intent;
23 import android.content.IntentFilter;
24 import android.content.pm.UserInfo;
25 import android.os.UserManager;
26 import android.util.ArraySet;
27 
28 import androidx.annotation.GuardedBy;
29 
30 import com.android.systemui.CoreStartable;
31 import com.android.systemui.broadcast.BroadcastDispatcher;
32 import com.android.systemui.car.userswitcher.UserIconProvider;
33 import com.android.systemui.dagger.SysUISingleton;
34 import com.android.systemui.dagger.qualifiers.Main;
35 import com.android.systemui.settings.UserTracker;
36 
37 import java.util.Set;
38 import java.util.concurrent.Executor;
39 
40 import javax.inject.Inject;
41 
42 /**
43  * CoreStartable service to keep the user icon updated and allow other components to listen to
44  * these updates.
45  */
46 @SysUISingleton
47 public class CarProfileIconUpdater implements CoreStartable {
48     private final Context mContext;
49     private final Executor mMainExecutor;
50     private final UserTracker mUserTracker;
51     private final UserManager mUserManager;
52     private final BroadcastDispatcher mBroadcastDispatcher;
53     private final UserIconProvider mUserIconProvider;
54     @GuardedBy("mCallbacks")
55     private final Set<Callback> mCallbacks = new ArraySet<>();
56 
57     private boolean mUserLifecycleListenerRegistered;
58     private String mLastUserName;
59 
60     private final UserTracker.Callback mUserChangedCallback =
61             new UserTracker.Callback() {
62                 @Override
63                 public void onUserChanged(int newUser, Context userContext) {
64                     mBroadcastDispatcher.unregisterReceiver(mUserUpdateReceiver);
65                     registerForUserInfoChange();
66                 }
67             };
68 
69     private final BroadcastReceiver mUserUpdateReceiver = new BroadcastReceiver() {
70         @Override
71         public void onReceive(Context context, Intent intent) {
72             updateUserIcon(mUserTracker.getUserId());
73         }
74     };
75 
76     @Inject
CarProfileIconUpdater(Context context, @Main Executor mainExecutor, UserTracker userTracker, UserManager userManager, BroadcastDispatcher broadcastDispatcher, UserIconProvider userIconProvider)77     public CarProfileIconUpdater(Context context, @Main Executor mainExecutor,
78             UserTracker userTracker, UserManager userManager,
79             BroadcastDispatcher broadcastDispatcher, UserIconProvider userIconProvider) {
80         mContext = context;
81         mMainExecutor = mainExecutor;
82         mUserTracker = userTracker;
83         mUserManager = userManager;
84         mBroadcastDispatcher = broadcastDispatcher;
85         mUserIconProvider = userIconProvider;
86     }
87 
88     @Override
start()89     public void start() {
90         registerForUserChangeEvents();
91     }
92 
93     /** Add a callback to listen to user icon updates */
addCallback(Callback callback)94     public void addCallback(Callback callback) {
95         synchronized (mCallbacks) {
96             mCallbacks.add(callback);
97         }
98     }
99 
100     /** Remove callback for user icon updates */
removeCallback(Callback callback)101     public void removeCallback(Callback callback) {
102         synchronized (mCallbacks) {
103             mCallbacks.remove(callback);
104         }
105     }
106 
updateUserIcon(@serIdInt int userId)107     protected void updateUserIcon(@UserIdInt int userId) {
108         UserInfo currentUserInfo = mUserManager.getUserInfo(userId);
109 
110         // Update user icon with the first letter of the user name
111         if (mLastUserName == null || !mLastUserName.equals(currentUserInfo.name)) {
112             mLastUserName = currentUserInfo.name;
113             mUserIconProvider.setRoundedUserIcon(userId);
114             notifyCallbacks(userId);
115         }
116     }
117 
notifyCallbacks(@serIdInt int userId)118     protected void notifyCallbacks(@UserIdInt int userId) {
119         synchronized (mCallbacks) {
120             for (Callback callback : mCallbacks) {
121                 callback.onUserIconUpdated(userId);
122             }
123         }
124     }
125 
registerForUserChangeEvents()126     private void registerForUserChangeEvents() {
127         if (mUserLifecycleListenerRegistered) {
128             return;
129         }
130         mUserLifecycleListenerRegistered = true;
131         mUserTracker.addCallback(mUserChangedCallback, mMainExecutor);
132         registerForUserInfoChange();
133     }
134 
registerForUserInfoChange()135     private void registerForUserInfoChange() {
136         mLastUserName = mUserManager.getUserInfo(mUserTracker.getUserId()).name;
137         IntentFilter filter = new IntentFilter();
138         filter.addAction(Intent.ACTION_USER_INFO_CHANGED);
139         mBroadcastDispatcher.registerReceiver(mUserUpdateReceiver, filter, /* executor= */ null,
140                 mUserTracker.getUserHandle());
141     }
142 
143     public interface Callback {
144         /** Called when the user icon is updated for a specific userId. */
onUserIconUpdated(int userId)145         void onUserIconUpdated(int userId);
146     }
147 }
148