1 /*
2  * Copyright (C) 2015 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 com.android.settings.accessibility.ToggleAutoclickCustomSeekbarController.MAX_AUTOCLICK_DELAY_MS;
20 import static com.android.settings.accessibility.ToggleAutoclickCustomSeekbarController.MIN_AUTOCLICK_DELAY_MS;
21 
22 import static java.lang.annotation.RetentionPolicy.SOURCE;
23 
24 import android.annotation.IntDef;
25 import android.app.settings.SettingsEnums;
26 import android.content.Context;
27 import android.content.res.Resources;
28 
29 import androidx.preference.Preference;
30 
31 import com.android.settings.R;
32 import com.android.settings.dashboard.DashboardFragment;
33 import com.android.settings.search.BaseSearchIndexProvider;
34 import com.android.settingslib.core.AbstractPreferenceController;
35 import com.android.settingslib.core.lifecycle.Lifecycle;
36 import com.android.settingslib.search.SearchIndexable;
37 
38 import java.lang.annotation.Retention;
39 import java.util.ArrayList;
40 import java.util.List;
41 
42 /**
43  * Fragment for preference screen for settings related to Automatically click after mouse stops
44  * feature.
45  */
46 @SearchIndexable(forTarget = SearchIndexable.ALL & ~SearchIndexable.ARC)
47 public class ToggleAutoclickPreferenceFragment extends DashboardFragment
48         implements ToggleAutoclickPreferenceController.OnChangeListener {
49 
50     private static final String TAG = "AutoclickPrefFragment";
51     private static final List<AbstractPreferenceController> sControllers = new ArrayList<>();
52 
53     @Retention(SOURCE)
54     @IntDef({
55             Quantity.OTHER,
56             Quantity.ONE,
57             Quantity.FEW
58     })
59     @interface Quantity {
60         int OTHER = 0;
61         int ONE = 1;
62         int FEW = 3;
63     }
64 
65     /**
66      * Resource ids from which autoclick preference summaries should be derived. The strings have
67      * placeholder for integer delay value.
68      */
69     private static final int[] AUTOCLICK_PREFERENCE_SUMMARIES = {
70             R.plurals.accessibilty_autoclick_preference_subtitle_short_delay,
71             R.plurals.accessibilty_autoclick_preference_subtitle_medium_delay,
72             R.plurals.accessibilty_autoclick_preference_subtitle_long_delay
73     };
74 
75     /**
76      * Gets string that should be used as a autoclick preference summary for provided autoclick
77      * delay.
78      *
79      * @param resources Resources from which string should be retrieved.
80      * @param delayMillis Delay for whose value summary should be retrieved.
81      */
getAutoclickPreferenceSummary(Resources resources, int delayMillis)82     static CharSequence getAutoclickPreferenceSummary(Resources resources, int delayMillis) {
83         final int summaryIndex = getAutoclickPreferenceSummaryIndex(delayMillis);
84         final int quantity = (delayMillis == 1000) ? Quantity.ONE : Quantity.FEW;
85         final float delaySecond =  (float) delayMillis / 1000;
86         // Only show integer when delay time is 1.
87         final String decimalFormat = (delaySecond == 1) ? "%.0f" : "%.1f";
88 
89         return resources.getQuantityString(AUTOCLICK_PREFERENCE_SUMMARIES[summaryIndex],
90                 quantity, String.format(decimalFormat, delaySecond));
91     }
92 
93     /**
94      * Finds index of the summary that should be used for the provided autoclick delay.
95      */
getAutoclickPreferenceSummaryIndex(int delay)96     private static int getAutoclickPreferenceSummaryIndex(int delay) {
97         if (delay <= MIN_AUTOCLICK_DELAY_MS) {
98             return 0;
99         }
100         if (delay >= MAX_AUTOCLICK_DELAY_MS) {
101             return AUTOCLICK_PREFERENCE_SUMMARIES.length - 1;
102         }
103         int delayRange = MAX_AUTOCLICK_DELAY_MS - MIN_AUTOCLICK_DELAY_MS;
104         int rangeSize = (delayRange) / (AUTOCLICK_PREFERENCE_SUMMARIES.length - 1);
105         return (delay - MIN_AUTOCLICK_DELAY_MS) / rangeSize;
106     }
107 
108     @Override
getMetricsCategory()109     public int getMetricsCategory() {
110         return SettingsEnums.ACCESSIBILITY_TOGGLE_AUTOCLICK;
111     }
112 
113     @Override
getHelpResource()114     public int getHelpResource() {
115         return R.string.help_url_autoclick;
116     }
117 
118     @Override
getLogTag()119     protected String getLogTag() {
120         return TAG;
121     }
122 
123     @Override
getPreferenceScreenResId()124     protected int getPreferenceScreenResId() {
125         return R.xml.accessibility_autoclick_settings;
126     }
127 
128     @Override
onResume()129     public void onResume() {
130         super.onResume();
131 
132         for (AbstractPreferenceController controller : sControllers) {
133             ((ToggleAutoclickPreferenceController) controller).setOnChangeListener(this);
134         }
135     }
136 
137     @Override
onPause()138     public void onPause() {
139         super.onPause();
140 
141         for (AbstractPreferenceController controller : sControllers) {
142             ((ToggleAutoclickPreferenceController) controller).setOnChangeListener(null);
143         }
144     }
145 
146     @Override
onCheckedChanged(Preference preference)147     public void onCheckedChanged(Preference preference) {
148         for (AbstractPreferenceController controller : sControllers) {
149             controller.updateState(preference);
150         }
151     }
152 
153     @Override
createPreferenceControllers(Context context)154     protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
155         return buildPreferenceControllers(context, getSettingsLifecycle());
156     }
157 
buildPreferenceControllers(Context context, Lifecycle lifecycle)158     private static List<AbstractPreferenceController> buildPreferenceControllers(Context context,
159             Lifecycle lifecycle) {
160         Resources resources = context.getResources();
161 
162         String[] autoclickKeys = resources.getStringArray(
163                 R.array.accessibility_autoclick_control_selector_keys);
164 
165         final int length = autoclickKeys.length;
166         for (int i = 0; i < length; i++) {
167             sControllers.add(new ToggleAutoclickPreferenceController(
168                     context, lifecycle, autoclickKeys[i]));
169         }
170         return sControllers;
171     }
172 
173     public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
174             new BaseSearchIndexProvider(R.xml.accessibility_autoclick_settings) {
175 
176                 @Override
177                 public List<AbstractPreferenceController> createPreferenceControllers(
178                         Context context) {
179                     return buildPreferenceControllers(context, null);
180                 }
181             };
182 }
183