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