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.settings.widget;
18 
19 import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
20 
21 import android.app.settings.SettingsEnums;
22 import android.content.Context;
23 import android.util.AttributeSet;
24 import android.view.View;
25 import android.widget.ImageView;
26 import android.widget.Switch;
27 
28 import com.android.settings.overlay.FeatureFactory;
29 import com.android.settingslib.RestrictedLockUtils;
30 import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
31 import com.android.settingslib.widget.MainSwitchBar;
32 import com.android.settingslib.widget.R;
33 
34 /**
35  * A {@link MainSwitchBar} with a customized Switch and provides the metrics feature.
36  */
37 public class SettingsMainSwitchBar extends MainSwitchBar {
38 
39     /**
40      * Called before the checked state of the Switch has changed.
41      */
42     public interface OnBeforeCheckedChangeListener {
43 
44         /**
45          * @param switchView The Switch view whose state has changed.
46          * @param isChecked  The new checked state of switchView.
47          */
onBeforeCheckedChanged(Switch switchView, boolean isChecked)48         boolean onBeforeCheckedChanged(Switch switchView, boolean isChecked);
49     }
50 
51     private ImageView mRestrictedIcon;
52     private EnforcedAdmin mEnforcedAdmin;
53     private boolean mDisabledByAdmin;
54 
55     private final MetricsFeatureProvider mMetricsFeatureProvider;
56     private OnBeforeCheckedChangeListener mOnBeforeListener;
57 
58     private String mMetricsTag;
59 
SettingsMainSwitchBar(Context context)60     public SettingsMainSwitchBar(Context context) {
61         this(context, null);
62     }
63 
SettingsMainSwitchBar(Context context, AttributeSet attrs)64     public SettingsMainSwitchBar(Context context, AttributeSet attrs) {
65         this(context, attrs, 0);
66     }
67 
SettingsMainSwitchBar(Context context, AttributeSet attrs, int defStyleAttr)68     public SettingsMainSwitchBar(Context context, AttributeSet attrs, int defStyleAttr) {
69         this(context, attrs, defStyleAttr, 0);
70     }
71 
SettingsMainSwitchBar(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes)72     public SettingsMainSwitchBar(Context context, AttributeSet attrs, int defStyleAttr,
73             int defStyleRes) {
74         super(context, attrs, defStyleAttr, defStyleRes);
75         mMetricsFeatureProvider = FeatureFactory.getFactory(context).getMetricsFeatureProvider();
76 
77         addOnSwitchChangeListener((switchView, isChecked) -> logMetrics(isChecked));
78 
79         mRestrictedIcon = findViewById(R.id.restricted_icon);
80         mRestrictedIcon.setOnClickListener((View v) -> {
81             if (mDisabledByAdmin) {
82                 RestrictedLockUtils.sendShowAdminSupportDetailsIntent(context, mEnforcedAdmin);
83                 onRestrictedIconClick();
84             }
85         });
86     }
87 
88     /**
89      * If admin is not null, disables the text and switch but keeps the view clickable (unless the
90      * switch is disabled for other reasons). Otherwise, calls setEnabled.
91      */
setDisabledByAdmin(EnforcedAdmin admin)92     public void setDisabledByAdmin(EnforcedAdmin admin) {
93         mEnforcedAdmin = admin;
94         if (admin != null) {
95             super.setEnabled(true);
96             mDisabledByAdmin = true;
97             mTextView.setEnabled(false);
98             mSwitch.setEnabled(false);
99             mSwitch.setVisibility(View.GONE);
100             mRestrictedIcon.setVisibility(View.VISIBLE);
101         } else {
102             mDisabledByAdmin = false;
103             mSwitch.setVisibility(View.VISIBLE);
104             mRestrictedIcon.setVisibility(View.GONE);
105             setEnabled(isEnabled());
106         }
107     }
108 
109     @Override
setEnabled(boolean enabled)110     public void setEnabled(boolean enabled) {
111         if (enabled && mDisabledByAdmin) {
112             setDisabledByAdmin(null);
113             return;
114         }
115         super.setEnabled(enabled);
116     }
117 
118     /**
119      * Called by the restricted icon clicked.
120      */
121 
122     @Override
performClick()123     public boolean performClick() {
124         return getDelegatingView().performClick();
125     }
126 
onRestrictedIconClick()127     protected void onRestrictedIconClick() {
128         mMetricsFeatureProvider.action(
129                 SettingsEnums.PAGE_UNKNOWN,
130                 SettingsEnums.ACTION_SETTINGS_PREFERENCE_CHANGE,
131                 SettingsEnums.PAGE_UNKNOWN,
132                 mMetricsTag + "/switch_bar|restricted",
133                 1);
134     }
135 
136     @Override
setChecked(boolean checked)137     public void setChecked(boolean checked) {
138         if (mOnBeforeListener != null
139                 && mOnBeforeListener.onBeforeCheckedChanged(mSwitch, checked)) {
140             return;
141         }
142         super.setChecked(checked);
143     }
144 
145     /**
146      * Update the status of switch but doesn't notify the mOnBeforeListener.
147      */
setCheckedInternal(boolean checked)148     public void setCheckedInternal(boolean checked) {
149         super.setChecked(checked);
150     }
151 
152     /**
153      * Set the OnBeforeCheckedChangeListener.
154      */
setOnBeforeCheckedChangeListener(OnBeforeCheckedChangeListener listener)155     public void setOnBeforeCheckedChangeListener(OnBeforeCheckedChangeListener listener) {
156         mOnBeforeListener = listener;
157     }
158 
159     /**
160      * Set the metrics tag.
161      */
setMetricsTag(String tag)162     public void setMetricsTag(String tag) {
163         mMetricsTag = tag;
164     }
165 
getDelegatingView()166     private View getDelegatingView() {
167         return mDisabledByAdmin ? mRestrictedIcon : mSwitch;
168     }
169 
logMetrics(boolean isChecked)170     private void logMetrics(boolean isChecked) {
171         mMetricsFeatureProvider.action(
172                 SettingsEnums.PAGE_UNKNOWN,
173                 SettingsEnums.ACTION_SETTINGS_PREFERENCE_CHANGE,
174                 SettingsEnums.PAGE_UNKNOWN,
175                 mMetricsTag + "/switch_bar",
176                 isChecked ? 1 : 0);
177     }
178 }
179