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.provider.Settings; 23 24 import androidx.lifecycle.LifecycleObserver; 25 import androidx.preference.Preference; 26 import androidx.preference.PreferenceScreen; 27 28 import com.android.settings.R; 29 import com.android.settings.core.PreferenceControllerMixin; 30 import com.android.settingslib.core.AbstractPreferenceController; 31 import com.android.settingslib.core.lifecycle.Lifecycle; 32 import com.android.settingslib.widget.RadioButtonPreference; 33 34 import com.google.common.primitives.Ints; 35 36 import java.util.HashMap; 37 import java.util.Map; 38 39 /** 40 * Controller class that control accessibility time out settings. 41 */ 42 public class AccessibilityTimeoutController extends AbstractPreferenceController implements 43 LifecycleObserver, RadioButtonPreference.OnClickListener, PreferenceControllerMixin { 44 static final String CONTENT_TIMEOUT_SETTINGS_SECURE = 45 Settings.Secure.ACCESSIBILITY_NON_INTERACTIVE_UI_TIMEOUT_MS; 46 static final String CONTROL_TIMEOUT_SETTINGS_SECURE = 47 Settings.Secure.ACCESSIBILITY_INTERACTIVE_UI_TIMEOUT_MS; 48 49 // pair the preference key and timeout value. 50 private final Map<String, Integer> mAccessibilityTimeoutKeyToValueMap = new HashMap<>(); 51 52 // RadioButtonPreference key, each preference represent a timeout value. 53 private final String mPreferenceKey; 54 private final ContentResolver mContentResolver; 55 private final Resources mResources; 56 private OnChangeListener mOnChangeListener; 57 private RadioButtonPreference mPreference; 58 private int mAccessibilityUiTimeoutValue; 59 AccessibilityTimeoutController(Context context, Lifecycle lifecycle, String preferenceKey)60 public AccessibilityTimeoutController(Context context, Lifecycle lifecycle, 61 String preferenceKey) { 62 super(context); 63 64 mContentResolver = context.getContentResolver(); 65 mResources = context.getResources(); 66 67 if (lifecycle != null) { 68 lifecycle.addObserver(this); 69 } 70 mPreferenceKey = preferenceKey; 71 } 72 getSecureAccessibilityTimeoutValue(ContentResolver resolver, String name)73 protected static int getSecureAccessibilityTimeoutValue(ContentResolver resolver, String name) { 74 String timeOutSec = Settings.Secure.getString(resolver, name); 75 if (timeOutSec == null) { 76 return 0; 77 } 78 Integer timeOutValue = Ints.tryParse(timeOutSec); 79 return timeOutValue == null ? 0 : timeOutValue; 80 } 81 setOnChangeListener(OnChangeListener listener)82 public void setOnChangeListener(OnChangeListener listener) { 83 mOnChangeListener = listener; 84 } 85 getTimeoutValueToKeyMap()86 private Map<String, Integer> getTimeoutValueToKeyMap() { 87 if (mAccessibilityTimeoutKeyToValueMap.size() == 0) { 88 89 String[] timeoutKeys = mResources.getStringArray( 90 R.array.accessibility_timeout_control_selector_keys); 91 92 int[] timeoutValues = mResources.getIntArray( 93 R.array.accessibility_timeout_selector_values); 94 95 final int timeoutValueCount = timeoutValues.length; 96 for (int i = 0; i < timeoutValueCount; i++) { 97 mAccessibilityTimeoutKeyToValueMap.put(timeoutKeys[i], timeoutValues[i]); 98 } 99 } 100 return mAccessibilityTimeoutKeyToValueMap; 101 } 102 putSecureString(String name, String value)103 private void putSecureString(String name, String value) { 104 Settings.Secure.putString(mContentResolver, name, value); 105 } 106 handlePreferenceChange(String value)107 private void handlePreferenceChange(String value) { 108 // save value to both content and control timeout setting. 109 putSecureString(Settings.Secure.ACCESSIBILITY_NON_INTERACTIVE_UI_TIMEOUT_MS, value); 110 putSecureString(Settings.Secure.ACCESSIBILITY_INTERACTIVE_UI_TIMEOUT_MS, value); 111 } 112 113 @Override isAvailable()114 public boolean isAvailable() { 115 return true; 116 } 117 118 @Override getPreferenceKey()119 public String getPreferenceKey() { 120 return mPreferenceKey; 121 } 122 123 @Override displayPreference(PreferenceScreen screen)124 public void displayPreference(PreferenceScreen screen) { 125 super.displayPreference(screen); 126 127 mPreference = (RadioButtonPreference) 128 screen.findPreference(getPreferenceKey()); 129 mPreference.setOnClickListener(this); 130 } 131 132 @Override onRadioButtonClicked(RadioButtonPreference preference)133 public void onRadioButtonClicked(RadioButtonPreference preference) { 134 int value = getTimeoutValueToKeyMap().get(mPreferenceKey); 135 handlePreferenceChange(String.valueOf(value)); 136 if (mOnChangeListener != null) { 137 mOnChangeListener.onCheckedChanged(mPreference); 138 } 139 } 140 getAccessibilityTimeoutValue()141 private int getAccessibilityTimeoutValue() { 142 // get accessibility control timeout value 143 int timeoutValue = getSecureAccessibilityTimeoutValue(mContentResolver, 144 CONTROL_TIMEOUT_SETTINGS_SECURE); 145 return timeoutValue; 146 } 147 updatePreferenceCheckedState(int value)148 protected void updatePreferenceCheckedState(int value) { 149 if (mAccessibilityUiTimeoutValue == value) { 150 mPreference.setChecked(true); 151 } 152 } 153 154 @Override updateState(Preference preference)155 public void updateState(Preference preference) { 156 super.updateState(preference); 157 158 mAccessibilityUiTimeoutValue = getAccessibilityTimeoutValue(); 159 160 // reset RadioButton 161 mPreference.setChecked(false); 162 int preferenceValue = getTimeoutValueToKeyMap().get(mPreference.getKey()); 163 updatePreferenceCheckedState(preferenceValue); 164 } 165 166 /** 167 * Listener interface handles checked event. 168 */ 169 public interface OnChangeListener { 170 /** 171 * A hook that is called when preference checked. 172 */ onCheckedChanged(Preference preference)173 void onCheckedChanged(Preference preference); 174 } 175 } 176