1 /*
2  * Copyright (C) 2022 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.permissioncontroller.safetycenter.ui;
18 
19 import static android.os.Build.VERSION_CODES.TIRAMISU;
20 
21 import android.content.Context;
22 import android.util.AttributeSet;
23 import android.view.View;
24 import android.view.ViewGroup;
25 
26 import androidx.annotation.RequiresApi;
27 import androidx.fragment.app.Fragment;
28 import androidx.preference.PreferenceViewHolder;
29 import androidx.preference.SwitchPreference;
30 
31 import com.android.permissioncontroller.R;
32 import com.android.permissioncontroller.safetycenter.ui.model.PrivacyControlsViewModel;
33 import com.android.permissioncontroller.safetycenter.ui.model.PrivacyControlsViewModel.Pref;
34 import com.android.permissioncontroller.safetycenter.ui.model.PrivacyControlsViewModel.PrefState;
35 
36 /**
37  * A preference that can be set to appear disabled, but remain clickable. However, the setChecked
38  * method will not register any changes while it appears disabled.
39  */
40 @RequiresApi(TIRAMISU)
41 public class ClickableDisabledSwitchPreference extends SwitchPreference {
42 
43     private boolean mAppearDisabled;
44 
ClickableDisabledSwitchPreference(Context context, AttributeSet attrs)45     public ClickableDisabledSwitchPreference(Context context, AttributeSet attrs) {
46         super(context, attrs);
47     }
48 
ClickableDisabledSwitchPreference(Context context)49     public ClickableDisabledSwitchPreference(Context context) {
50         super(context);
51     }
52 
53     @Override
onBindViewHolder(PreferenceViewHolder holder)54     public void onBindViewHolder(PreferenceViewHolder holder) {
55         super.onBindViewHolder(holder);
56         if (holder.itemView instanceof ViewGroup) {
57             applyEnableStateToChildren((ViewGroup) holder.itemView);
58         }
59     }
60 
61     @Override
setChecked(boolean checked)62     public void setChecked(boolean checked) {
63         if (mAppearDisabled) {
64             return;
65         }
66         super.setChecked(checked);
67     }
68 
69     /**
70      * Set this preference to appear disabled. It will remain clickable, but will be frozen in its
71      * current checked state.
72      */
setAppearDisabled(boolean appearDisabled)73     private void setAppearDisabled(boolean appearDisabled) {
74         if (appearDisabled == mAppearDisabled) {
75             return;
76         }
77         mAppearDisabled = appearDisabled;
78         notifyChanged();
79     }
80 
applyEnableStateToChildren(ViewGroup viewGroup)81     private void applyEnableStateToChildren(ViewGroup viewGroup) {
82         for (int i = 0; i < viewGroup.getChildCount(); i++) {
83             View child = viewGroup.getChildAt(i);
84             child.setEnabled(!mAppearDisabled);
85             if (child instanceof ViewGroup) {
86                 applyEnableStateToChildren((ViewGroup) child);
87             }
88         }
89     }
90 
91     /**
92      * Sets the state of this switch preference based on restrictions enforced by the admin
93      *
94      * @param prefState a map of the preferences and their current toggle state
95      * @param prefType represents the type of privacy control toggle
96      * @param viewModel model used to talk to the backing service
97      * @param fragment represents the fragment containing this preference
98      */
setupState( PrefState prefState, Pref prefType, PrivacyControlsViewModel viewModel, Fragment fragment)99     public void setupState(
100             PrefState prefState,
101             Pref prefType,
102             PrivacyControlsViewModel viewModel,
103             Fragment fragment) {
104         setVisible(prefState.getVisible());
105         setChecked(prefState.getChecked());
106         setAppearDisabled(prefState.getAdmin() != null);
107         setOnPreferenceClickListener(
108                 (v) -> {
109                     viewModel.handlePrefClick(fragment, prefType, prefState.getAdmin());
110                     return true;
111                 });
112 
113         if (prefState.getAdmin() != null && prefState.getChecked()) {
114             setSummary(com.android.settingslib.widget.restricted.R.string.enabled_by_admin);
115         } else if (prefState.getAdmin() != null) {
116             setSummary(com.android.settingslib.widget.restricted.R.string.disabled_by_admin);
117         } else if (prefType.equals(Pref.MIC)) {
118             setSummary(R.string.mic_toggle_description);
119         } else if (prefType.equals(Pref.CAMERA)) {
120             setSummary(R.string.perm_toggle_description);
121         }
122     }
123 }
124