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