OSDN Git Service

b92aac26ae9ace3d56a458da54254241787b0f9a
[android-x86/packages-apps-Settings.git] / src / com / android / settings / accessibility / VibrationPreferenceFragment.java
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 package com.android.settings.accessibility;
17
18 import static android.os.Vibrator.VibrationIntensity;
19
20 import android.support.annotation.VisibleForTesting;
21 import android.content.Context;
22 import android.database.ContentObserver;
23 import android.graphics.drawable.Drawable;
24 import android.media.AudioAttributes;
25 import android.net.Uri;
26 import android.os.Handler;
27 import android.os.VibrationEffect;
28 import android.os.Vibrator;
29 import android.provider.Settings;
30 import android.util.ArrayMap;
31 import android.util.Log;
32
33 import com.android.internal.accessibility.AccessibilityShortcutController;
34 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
35 import com.android.settings.R;
36 import com.android.settings.widget.RadioButtonPickerFragment;
37 import com.android.settingslib.widget.CandidateInfo;
38
39 import java.util.ArrayList;
40 import java.util.Comparator;
41 import java.util.List;
42 import java.util.Map;
43
44 /**
45  * Fragment for changing vibration settings.
46  */
47 public abstract class VibrationPreferenceFragment extends RadioButtonPickerFragment {
48     private static final String TAG = "VibrationPreferenceFragment";
49
50     @VisibleForTesting
51     final static String KEY_INTENSITY_OFF = "intensity_off";
52     @VisibleForTesting
53     final static String KEY_INTENSITY_LOW = "intensity_low";
54     @VisibleForTesting
55     final static String KEY_INTENSITY_MEDIUM = "intensity_medium";
56     @VisibleForTesting
57     final static String KEY_INTENSITY_HIGH = "intensity_high";
58     // KEY_INTENSITY_ON is only used when the device doesn't support multiple intensity levels.
59     @VisibleForTesting
60     final static String KEY_INTENSITY_ON = "intensity_on";
61
62     private final Map<String, VibrationIntensityCandidateInfo> mCandidates;
63     private final SettingsObserver mSettingsObserver;
64
65     public VibrationPreferenceFragment() {
66         mCandidates = new ArrayMap<>();
67         mSettingsObserver = new SettingsObserver();
68     }
69
70     @Override
71     public void onAttach(Context context) {
72         super.onAttach(context);
73         mSettingsObserver.register();
74         if (mCandidates.isEmpty()) {
75             loadCandidates(context);
76         }
77     }
78
79     private void loadCandidates(Context context) {
80         final boolean supportsMultipleIntensities = context.getResources().getBoolean(
81                 R.bool.config_vibration_supports_multiple_intensities);
82         if (supportsMultipleIntensities) {
83             mCandidates.put(KEY_INTENSITY_OFF,
84                     new VibrationIntensityCandidateInfo(KEY_INTENSITY_OFF,
85                         R.string.accessibility_vibration_intensity_off,
86                         Vibrator.VIBRATION_INTENSITY_OFF));
87             mCandidates.put(KEY_INTENSITY_LOW,
88                     new VibrationIntensityCandidateInfo(KEY_INTENSITY_LOW,
89                         R.string.accessibility_vibration_intensity_low,
90                         Vibrator.VIBRATION_INTENSITY_LOW));
91             mCandidates.put(KEY_INTENSITY_MEDIUM,
92                     new VibrationIntensityCandidateInfo(KEY_INTENSITY_MEDIUM,
93                         R.string.accessibility_vibration_intensity_medium,
94                         Vibrator.VIBRATION_INTENSITY_MEDIUM));
95             mCandidates.put(KEY_INTENSITY_HIGH,
96                     new VibrationIntensityCandidateInfo(KEY_INTENSITY_HIGH,
97                         R.string.accessibility_vibration_intensity_high,
98                         Vibrator.VIBRATION_INTENSITY_HIGH));
99         } else {
100             mCandidates.put(KEY_INTENSITY_OFF,
101                     new VibrationIntensityCandidateInfo(KEY_INTENSITY_OFF,
102                         R.string.switch_off_text, Vibrator.VIBRATION_INTENSITY_OFF));
103             mCandidates.put(KEY_INTENSITY_ON,
104                     new VibrationIntensityCandidateInfo(KEY_INTENSITY_ON,
105                         R.string.switch_on_text, getDefaultVibrationIntensity()));
106         }
107     }
108
109     @Override
110     public void onDetach() {
111         super.onDetach();
112         mSettingsObserver.unregister();
113     }
114
115     /**
116      * Get the setting string of the vibration intensity setting this preference is dealing with.
117      */
118     protected abstract String getVibrationIntensitySetting();
119
120     /**
121      * Get the default intensity for the desired setting.
122      */
123     protected abstract int getDefaultVibrationIntensity();
124
125     /**
126      * When a new vibration intensity is selected by the user.
127      */
128     protected void onVibrationIntensitySelected(int intensity) { }
129
130     /**
131      * Play a vibration effect with intensity just selected by user
132      */
133     protected void playVibrationPreview() {
134         Vibrator vibrator = getContext().getSystemService(Vibrator.class);
135         VibrationEffect effect = VibrationEffect.get(VibrationEffect.EFFECT_CLICK);
136         AudioAttributes.Builder builder = new AudioAttributes.Builder();
137         builder.setUsage(getPreviewVibrationAudioAttributesUsage());
138         vibrator.vibrate(effect, builder.build());
139     }
140
141     /**
142      * Get the AudioAttributes usage for vibration preview.
143      */
144     protected int getPreviewVibrationAudioAttributesUsage() {
145         return AudioAttributes.USAGE_UNKNOWN;
146     }
147
148     @Override
149     protected List<? extends CandidateInfo> getCandidates() {
150         List<VibrationIntensityCandidateInfo> candidates = new ArrayList<>(mCandidates.values());
151         candidates.sort(
152                 Comparator.comparing(VibrationIntensityCandidateInfo::getIntensity).reversed());
153         return candidates;
154     }
155
156     @Override
157     protected String getDefaultKey() {
158         final int vibrationIntensity = Settings.System.getInt(getContext().getContentResolver(),
159                 getVibrationIntensitySetting(), getDefaultVibrationIntensity());
160         for (VibrationIntensityCandidateInfo candidate : mCandidates.values()) {
161             final boolean matchesIntensity = candidate.getIntensity() == vibrationIntensity;
162             final boolean matchesOn = candidate.getKey().equals(KEY_INTENSITY_ON)
163                     && vibrationIntensity != Vibrator.VIBRATION_INTENSITY_OFF;
164             if (matchesIntensity || matchesOn) {
165                 return candidate.getKey();
166             }
167         }
168         return null;
169     }
170
171     @Override
172     protected boolean setDefaultKey(String key) {
173         VibrationIntensityCandidateInfo candidate = mCandidates.get(key);
174         if (candidate == null) {
175             Log.e(TAG, "Tried to set unknown intensity (key=" + key + ")!");
176             return false;
177         }
178         Settings.System.putInt(getContext().getContentResolver(),
179                 getVibrationIntensitySetting(), candidate.getIntensity());
180         onVibrationIntensitySelected(candidate.getIntensity());
181         return true;
182     }
183
184     @VisibleForTesting
185     class VibrationIntensityCandidateInfo extends CandidateInfo {
186         private String mKey;
187         private int mLabelId;
188         @VibrationIntensity
189         private int mIntensity;
190
191         public VibrationIntensityCandidateInfo(String key, int labelId, int intensity) {
192             super(true /* enabled */);
193             mKey = key;
194             mLabelId = labelId;
195             mIntensity = intensity;
196         }
197
198         @Override
199         public CharSequence loadLabel() {
200             return getContext().getString(mLabelId);
201         }
202
203         @Override
204         public Drawable loadIcon() {
205             return null;
206         }
207
208         @Override
209         public String getKey() {
210             return mKey;
211         }
212
213         public int getIntensity() {
214             return mIntensity;
215         }
216     }
217
218     private class SettingsObserver extends ContentObserver {
219         public SettingsObserver() {
220             super(new Handler());
221         }
222
223         public void register() {
224             getContext().getContentResolver().registerContentObserver(
225                     Settings.System.getUriFor(getVibrationIntensitySetting()), false, this);
226         }
227
228         public void unregister() {
229             getContext().getContentResolver().unregisterContentObserver(this);
230         }
231
232         @Override
233         public void onChange(boolean selfChange, Uri uri) {
234             updateCandidates();
235             playVibrationPreview();
236         }
237     }
238 }