• 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.systemui.qs.tiles;
18 
19 import android.content.Context;
20 import android.content.Intent;
21 import android.graphics.drawable.Drawable;
22 import android.graphics.drawable.LayerDrawable;
23 import android.os.Trace;
24 import android.util.AttributeSet;
25 import android.view.LayoutInflater;
26 import android.view.View;
27 import android.view.ViewGroup;
28 
29 import androidx.annotation.NonNull;
30 import androidx.annotation.Nullable;
31 
32 import com.android.internal.logging.MetricsLogger;
33 import com.android.internal.logging.UiEventLogger;
34 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
35 import com.android.settingslib.RestrictedLockUtils;
36 import com.android.settingslib.drawable.CircleFramedDrawable;
37 import com.android.systemui.R;
38 import com.android.systemui.plugins.FalsingManager;
39 import com.android.systemui.qs.PseudoGridView;
40 import com.android.systemui.qs.QSUserSwitcherEvent;
41 import com.android.systemui.qs.user.UserSwitchDialogController;
42 import com.android.systemui.statusbar.phone.SystemUIDialog;
43 import com.android.systemui.statusbar.policy.BaseUserSwitcherAdapter;
44 import com.android.systemui.statusbar.policy.UserSwitcherController;
45 import com.android.systemui.user.data.source.UserRecord;
46 
47 import java.util.List;
48 import java.util.stream.Collectors;
49 
50 import javax.inject.Inject;
51 
52 /**
53  * Quick settings detail view for user switching.
54  */
55 public class UserDetailView extends PseudoGridView {
56 
57     protected Adapter mAdapter;
58 
UserDetailView(Context context, AttributeSet attrs)59     public UserDetailView(Context context, AttributeSet attrs) {
60         super(context, attrs);
61     }
62 
inflate(Context context, ViewGroup parent, boolean attach)63     public static UserDetailView inflate(Context context, ViewGroup parent, boolean attach) {
64         return (UserDetailView) LayoutInflater.from(context).inflate(
65                 R.layout.qs_user_detail, parent, attach);
66     }
67 
68     /** Set a {@link android.widget.BaseAdapter} */
setAdapter(Adapter adapter)69     public void setAdapter(Adapter adapter) {
70         mAdapter = adapter;
71         ViewGroupAdapterBridge.link(this, mAdapter);
72     }
73 
refreshAdapter()74     public void refreshAdapter() {
75         mAdapter.refresh();
76     }
77 
78     /** Provides views for user detail items. */
79     public static class Adapter extends BaseUserSwitcherAdapter
80             implements OnClickListener {
81 
82         private final Context mContext;
83         protected UserSwitcherController mController;
84         @Nullable
85         private View mCurrentUserView;
86         private final UiEventLogger mUiEventLogger;
87         private final FalsingManager mFalsingManager;
88         private @Nullable UserSwitchDialogController.DialogShower mDialogShower;
89 
90         @NonNull
91         @Override
getUsers()92         protected List<UserRecord> getUsers() {
93             return super.getUsers().stream().filter(
94                     userRecord -> !userRecord.isManageUsers).collect(Collectors.toList());
95         }
96 
97         @Inject
Adapter(Context context, UserSwitcherController controller, UiEventLogger uiEventLogger, FalsingManager falsingManager)98         public Adapter(Context context, UserSwitcherController controller,
99                 UiEventLogger uiEventLogger, FalsingManager falsingManager) {
100             super(controller);
101             mContext = context;
102             mController = controller;
103             mUiEventLogger = uiEventLogger;
104             mFalsingManager = falsingManager;
105         }
106 
107         @Override
getView(int position, View convertView, ViewGroup parent)108         public View getView(int position, View convertView, ViewGroup parent) {
109             UserRecord item = getItem(position);
110             return createUserDetailItemView(convertView, parent, item);
111         }
112 
113         /**
114          * If this adapter is inside a dialog, passing a
115          * {@link UserSwitchDialogController.DialogShower} will help animate to and from the parent
116          * dialog. This will also allow for dismissing the whole stack of dialogs in a single
117          * animation.
118          *
119          * @param shower
120          * @see SystemUIDialog#dismissStack()
121          */
injectDialogShower(UserSwitchDialogController.DialogShower shower)122         public void injectDialogShower(UserSwitchDialogController.DialogShower shower) {
123             mDialogShower = shower;
124         }
125 
createUserDetailItemView(View convertView, ViewGroup parent, UserRecord item)126         public UserDetailItemView createUserDetailItemView(View convertView, ViewGroup parent,
127                 UserRecord item) {
128             UserDetailItemView v = UserDetailItemView.convertOrInflate(
129                     parent.getContext(), convertView, parent);
130             if (!item.isCurrent || item.isGuest) {
131                 v.setOnClickListener(this);
132             } else {
133                 v.setOnClickListener(null);
134                 v.setClickable(false);
135             }
136             String name = getName(mContext, item);
137             if (item.picture == null) {
138                 v.bind(name, getDrawable(mContext, item).mutate(), item.resolveId());
139             } else {
140                 int avatarSize =
141                         (int) mContext.getResources().getDimension(R.dimen.qs_framed_avatar_size);
142                 Drawable drawable = new CircleFramedDrawable(item.picture, avatarSize);
143                 drawable.setColorFilter(
144                         item.isSwitchToEnabled ? null : getDisabledUserAvatarColorFilter());
145                 v.bind(name, drawable, item.info.id);
146             }
147             v.setActivated(item.isCurrent);
148             v.setDisabledByAdmin(item.isDisabledByAdmin());
149             v.setEnabled(item.isSwitchToEnabled);
150             UserSwitcherController.setSelectableAlpha(v);
151 
152             if (item.isCurrent) {
153                 mCurrentUserView = v;
154             }
155             v.setTag(item);
156             return v;
157         }
158 
getDrawable(Context context, UserRecord item)159         private static Drawable getDrawable(Context context,
160                 UserRecord item) {
161             Drawable icon = getIconDrawable(context, item);
162             int iconColorRes;
163             if (item.isCurrent) {
164                 iconColorRes = R.color.qs_user_switcher_selected_avatar_icon_color;
165             } else if (!item.isSwitchToEnabled) {
166                 iconColorRes = R.color.GM2_grey_600;
167             } else {
168                 iconColorRes = R.color.qs_user_switcher_avatar_icon_color;
169             }
170             icon.setTint(context.getResources().getColor(iconColorRes, context.getTheme()));
171 
172             int bgRes = item.isCurrent ? R.drawable.bg_avatar_selected : R.drawable.qs_bg_avatar;
173             Drawable bg = context.getDrawable(bgRes);
174             LayerDrawable drawable = new LayerDrawable(new Drawable[]{bg, icon});
175             return drawable;
176         }
177 
178         @Override
onClick(View view)179         public void onClick(View view) {
180             if (mFalsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) {
181                 return;
182             }
183 
184             Trace.beginSection("UserDetailView.Adapter#onClick");
185             UserRecord userRecord =
186                     (UserRecord) view.getTag();
187             if (userRecord.isDisabledByAdmin()) {
188                 final Intent intent = RestrictedLockUtils.getShowAdminSupportDetailsIntent(
189                         mContext, userRecord.enforcedAdmin);
190                 mController.startActivity(intent);
191             } else if (userRecord.isSwitchToEnabled) {
192                 MetricsLogger.action(mContext, MetricsEvent.QS_SWITCH_USER);
193                 mUiEventLogger.log(QSUserSwitcherEvent.QS_USER_SWITCH);
194                 if (!userRecord.isAddUser
195                         && !userRecord.isRestricted
196                         && !userRecord.isDisabledByAdmin()) {
197                     if (mCurrentUserView != null) {
198                         mCurrentUserView.setActivated(false);
199                     }
200                     view.setActivated(true);
201                 }
202                 onUserListItemClicked(userRecord, mDialogShower);
203             }
204             Trace.endSection();
205         }
206 
linkToViewGroup(ViewGroup viewGroup)207         public void linkToViewGroup(ViewGroup viewGroup) {
208             PseudoGridView.ViewGroupAdapterBridge.link(viewGroup, this);
209         }
210     }
211 }
212