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.accessibility;
18 
19 import static android.content.Context.MODE_PRIVATE;
20 
21 import static com.android.settings.accessibility.AccessibilityUtil.State.OFF;
22 import static com.android.settings.accessibility.AccessibilityUtil.State.ON;
23 import static com.android.settings.accessibility.AutoclickUtils.KEY_DELAY_MODE;
24 
25 import android.content.ContentResolver;
26 import android.content.Context;
27 import android.content.SharedPreferences;
28 import android.content.res.Resources;
29 import android.provider.Settings;
30 import android.util.ArrayMap;
31 
32 import androidx.annotation.Nullable;
33 import androidx.preference.Preference;
34 import androidx.preference.PreferenceScreen;
35 
36 import com.android.settings.R;
37 import com.android.settings.core.BasePreferenceController;
38 import com.android.settingslib.core.lifecycle.LifecycleObserver;
39 import com.android.settingslib.core.lifecycle.events.OnStart;
40 import com.android.settingslib.core.lifecycle.events.OnStop;
41 import com.android.settingslib.widget.LayoutPreference;
42 import com.android.settingslib.widget.SelectorWithWidgetPreference;
43 
44 import java.util.Map;
45 
46 /** Controller class that controls accessibility autoclick settings. */
47 public class ToggleAutoclickPreferenceController extends BasePreferenceController implements
48         LifecycleObserver, OnStart, OnStop, SelectorWithWidgetPreference.OnClickListener,
49         SharedPreferences.OnSharedPreferenceChangeListener {
50 
51     private static final String KEY_AUTOCLICK_CUSTOM_SEEKBAR = "autoclick_custom_seekbar";
52     private static final int AUTOCLICK_OFF_MODE = 0;
53     private static final int AUTOCLICK_CUSTOM_MODE = 2000;
54 
55     /**
56      * Seek bar preference for autoclick delay value. The seek bar has values between 0 and
57      * number of possible discrete autoclick delay values. These will have to be converted to actual
58      * delay values before saving them in settings.
59      */
60     private LayoutPreference mSeekBerPreference;
61     private SelectorWithWidgetPreference mDelayModePref;
62     private Map<String, Integer> mAccessibilityAutoclickKeyToValueMap = new ArrayMap<>();
63     private final SharedPreferences mSharedPreferences;
64     private final ContentResolver mContentResolver;
65     private final Resources mResources;
66 
ToggleAutoclickPreferenceController(Context context, String preferenceKey)67     public ToggleAutoclickPreferenceController(Context context, String preferenceKey) {
68         super(context, preferenceKey);
69         mSharedPreferences = context.getSharedPreferences(context.getPackageName(), MODE_PRIVATE);
70         mContentResolver = context.getContentResolver();
71         mResources = context.getResources();
72     }
73 
74     @Override
onStart()75     public void onStart() {
76         mSharedPreferences.registerOnSharedPreferenceChangeListener(this);
77     }
78 
79     @Override
onStop()80     public void onStop() {
81         mSharedPreferences.unregisterOnSharedPreferenceChangeListener(this);
82     }
83 
84     @Override
onSharedPreferenceChanged(SharedPreferences sharedPreferences, @Nullable String key)85     public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
86             @Nullable String key) {
87         updateState(mDelayModePref);
88     }
89 
90     @Override
getAvailabilityStatus()91     public int getAvailabilityStatus() {
92         return AVAILABLE;
93     }
94 
95     @Override
displayPreference(PreferenceScreen screen)96     public void displayPreference(PreferenceScreen screen) {
97         super.displayPreference(screen);
98 
99         mDelayModePref = screen.findPreference(getPreferenceKey());
100         mDelayModePref.setOnClickListener(this);
101         mSeekBerPreference = screen.findPreference(KEY_AUTOCLICK_CUSTOM_SEEKBAR);
102         updateState(mDelayModePref);
103     }
104 
105     @Override
onRadioButtonClicked(SelectorWithWidgetPreference preference)106     public void onRadioButtonClicked(SelectorWithWidgetPreference preference) {
107         final int mode = getAutoclickModeToKeyMap().get(mPreferenceKey);
108         Settings.Secure.putInt(mContentResolver, Settings.Secure.ACCESSIBILITY_AUTOCLICK_ENABLED,
109                 (mode != AUTOCLICK_OFF_MODE) ? ON : OFF);
110         mSharedPreferences.edit().putInt(KEY_DELAY_MODE, mode).apply();
111         if (mode != AUTOCLICK_CUSTOM_MODE) {
112             Settings.Secure.putInt(mContentResolver, Settings.Secure.ACCESSIBILITY_AUTOCLICK_DELAY,
113                     mode);
114         }
115     }
116 
117     @Override
updateState(Preference preference)118     public void updateState(Preference preference) {
119         super.updateState(preference);
120         final boolean enabled = Settings.Secure.getInt(mContext.getContentResolver(),
121                 Settings.Secure.ACCESSIBILITY_AUTOCLICK_ENABLED, OFF) == ON;
122         final int currentUiAutoClickMode = enabled
123                 ? mSharedPreferences.getInt(KEY_DELAY_MODE, AUTOCLICK_CUSTOM_MODE)
124                 : AUTOCLICK_OFF_MODE;
125         final int mode = getAutoclickModeToKeyMap().get(mDelayModePref.getKey());
126         mDelayModePref.setChecked(currentUiAutoClickMode == mode);
127         if (mode == AUTOCLICK_CUSTOM_MODE) {
128             mSeekBerPreference.setVisible(mDelayModePref.isChecked());
129         }
130     }
131 
132     /** Returns the paring preference key and autoclick mode value listing. */
getAutoclickModeToKeyMap()133     private Map<String, Integer> getAutoclickModeToKeyMap() {
134         if (mAccessibilityAutoclickKeyToValueMap.size() == 0) {
135             final String[] autoclickKeys = mResources.getStringArray(
136                     R.array.accessibility_autoclick_control_selector_keys);
137             final int[] autoclickValues = mResources.getIntArray(
138                     R.array.accessibility_autoclick_selector_values);
139             final int autoclickValueCount = autoclickValues.length;
140             for (int i = 0; i < autoclickValueCount; i++) {
141                 mAccessibilityAutoclickKeyToValueMap.put(autoclickKeys[i], autoclickValues[i]);
142             }
143         }
144         return mAccessibilityAutoclickKeyToValueMap;
145     }
146 }
147