1 /*
2  * Copyright (C) 2018 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.accessibility;
18 
19 import android.content.ContentResolver;
20 import android.content.Context;
21 import android.content.res.Resources;
22 import android.os.Handler;
23 import android.os.Looper;
24 import android.provider.Settings;
25 
26 import androidx.annotation.VisibleForTesting;
27 import androidx.preference.Preference;
28 import androidx.preference.PreferenceScreen;
29 
30 import com.android.settings.R;
31 import com.android.settings.core.BasePreferenceController;
32 import com.android.settingslib.core.lifecycle.LifecycleObserver;
33 import com.android.settingslib.core.lifecycle.events.OnStart;
34 import com.android.settingslib.core.lifecycle.events.OnStop;
35 import com.android.settingslib.widget.SelectorWithWidgetPreference;
36 
37 import java.util.Arrays;
38 import java.util.HashMap;
39 import java.util.List;
40 import java.util.Map;
41 
42 /** Controller class that control accessibility timeout settings. */
43 public class AccessibilityTimeoutController extends BasePreferenceController implements
44         LifecycleObserver, OnStart, OnStop , SelectorWithWidgetPreference.OnClickListener {
45 
46     private static final List<String> ACCESSIBILITY_TIMEOUT_FEATURE_KEYS = Arrays.asList(
47             Settings.Secure.ACCESSIBILITY_NON_INTERACTIVE_UI_TIMEOUT_MS,
48             Settings.Secure.ACCESSIBILITY_INTERACTIVE_UI_TIMEOUT_MS
49     );
50 
51     // pair the preference key and timeout value.
52     private final Map<String, Integer> mAccessibilityTimeoutKeyToValueMap = new HashMap<>();
53     // RadioButtonPreference key, each preference represent a timeout value.
54     private final ContentResolver mContentResolver;
55     private final Resources mResources;
56     private SelectorWithWidgetPreference mPreference;
57     private int mAccessibilityUiTimeoutValue;
58     private AccessibilitySettingsContentObserver mSettingsContentObserver;
59 
AccessibilityTimeoutController(Context context, String preferenceKey)60     public AccessibilityTimeoutController(Context context, String preferenceKey) {
61         super(context, preferenceKey);
62         mContentResolver = context.getContentResolver();
63         mResources = context.getResources();
64         mSettingsContentObserver = new AccessibilitySettingsContentObserver(
65                 new Handler(Looper.getMainLooper()));
66         mSettingsContentObserver.registerKeysToObserverCallback(ACCESSIBILITY_TIMEOUT_FEATURE_KEYS,
67                 key -> updateState(mPreference));
68     }
69 
70     @VisibleForTesting
AccessibilityTimeoutController(Context context, String preferenceKey, AccessibilitySettingsContentObserver contentObserver)71     AccessibilityTimeoutController(Context context, String preferenceKey,
72             AccessibilitySettingsContentObserver contentObserver) {
73         this(context, preferenceKey);
74         mSettingsContentObserver = contentObserver;
75     }
76 
77     @Override
onStart()78     public void onStart() {
79         mSettingsContentObserver.register(mContentResolver);
80     }
81 
82     @Override
onStop()83     public void onStop() {
84         mSettingsContentObserver.unregister(mContentResolver);
85     }
86 
87     @Override
getAvailabilityStatus()88     public int getAvailabilityStatus() {
89         return AVAILABLE;
90     }
91 
92     @Override
displayPreference(PreferenceScreen screen)93     public void displayPreference(PreferenceScreen screen) {
94         super.displayPreference(screen);
95         mPreference = screen.findPreference(getPreferenceKey());
96         mPreference.setOnClickListener(this);
97     }
98 
99     @Override
onRadioButtonClicked(SelectorWithWidgetPreference preference)100     public void onRadioButtonClicked(SelectorWithWidgetPreference preference) {
101         final String value = String.valueOf(getTimeoutValueToKeyMap().get(mPreferenceKey));
102 
103         // save value to both content and control timeout setting.
104         Settings.Secure.putString(mContentResolver,
105                 Settings.Secure.ACCESSIBILITY_NON_INTERACTIVE_UI_TIMEOUT_MS, value);
106         Settings.Secure.putString(mContentResolver,
107                 Settings.Secure.ACCESSIBILITY_INTERACTIVE_UI_TIMEOUT_MS, value);
108     }
109 
110     @Override
updateState(Preference preference)111     public void updateState(Preference preference) {
112         super.updateState(preference);
113         mAccessibilityUiTimeoutValue = AccessibilityTimeoutUtils.getSecureAccessibilityTimeoutValue(
114                 mContentResolver);
115 
116         // reset RadioButton
117         mPreference.setChecked(false);
118         final int preferenceValue = getTimeoutValueToKeyMap().get(mPreference.getKey());
119         if (mAccessibilityUiTimeoutValue == preferenceValue) {
120             mPreference.setChecked(true);
121         }
122     }
123 
getTimeoutValueToKeyMap()124     private Map<String, Integer> getTimeoutValueToKeyMap() {
125         if (mAccessibilityTimeoutKeyToValueMap.size() == 0) {
126             String[] timeoutKeys = mResources.getStringArray(
127                     R.array.accessibility_timeout_control_selector_keys);
128             final int[] timeoutValues = mResources.getIntArray(
129                     R.array.accessibility_timeout_selector_values);
130             final int timeoutValueCount = timeoutValues.length;
131             for (int i = 0; i < timeoutValueCount; i++) {
132                 mAccessibilityTimeoutKeyToValueMap.put(timeoutKeys[i], timeoutValues[i]);
133             }
134         }
135         return mAccessibilityTimeoutKeyToValueMap;
136     }
137 }
138