2 * Copyright (C) 2018 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
16 package com.android.settings.accessibility;
18 import static android.os.Vibrator.VibrationIntensity;
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;
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;
39 import java.util.ArrayList;
40 import java.util.Comparator;
41 import java.util.List;
45 * Fragment for changing vibration settings.
47 public abstract class VibrationPreferenceFragment extends RadioButtonPickerFragment {
48 private static final String TAG = "VibrationPreferenceFragment";
51 final static String KEY_INTENSITY_OFF = "intensity_off";
53 final static String KEY_INTENSITY_LOW = "intensity_low";
55 final static String KEY_INTENSITY_MEDIUM = "intensity_medium";
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.
60 final static String KEY_INTENSITY_ON = "intensity_on";
62 private final Map<String, VibrationIntensityCandidateInfo> mCandidates;
63 private final SettingsObserver mSettingsObserver;
65 public VibrationPreferenceFragment() {
66 mCandidates = new ArrayMap<>();
67 mSettingsObserver = new SettingsObserver();
71 public void onAttach(Context context) {
72 super.onAttach(context);
73 mSettingsObserver.register();
74 if (mCandidates.isEmpty()) {
75 loadCandidates(context);
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));
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()));
110 public void onDetach() {
112 mSettingsObserver.unregister();
116 * Get the setting string of the vibration intensity setting this preference is dealing with.
118 protected abstract String getVibrationIntensitySetting();
121 * Get the default intensity for the desired setting.
123 protected abstract int getDefaultVibrationIntensity();
126 * When a new vibration intensity is selected by the user.
128 protected void onVibrationIntensitySelected(int intensity) { }
131 * Play a vibration effect with intensity just selected by user
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());
142 * Get the AudioAttributes usage for vibration preview.
144 protected int getPreviewVibrationAudioAttributesUsage() {
145 return AudioAttributes.USAGE_UNKNOWN;
149 protected List<? extends CandidateInfo> getCandidates() {
150 List<VibrationIntensityCandidateInfo> candidates = new ArrayList<>(mCandidates.values());
152 Comparator.comparing(VibrationIntensityCandidateInfo::getIntensity).reversed());
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();
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 + ")!");
178 Settings.System.putInt(getContext().getContentResolver(),
179 getVibrationIntensitySetting(), candidate.getIntensity());
180 onVibrationIntensitySelected(candidate.getIntensity());
185 class VibrationIntensityCandidateInfo extends CandidateInfo {
187 private int mLabelId;
189 private int mIntensity;
191 public VibrationIntensityCandidateInfo(String key, int labelId, int intensity) {
192 super(true /* enabled */);
195 mIntensity = intensity;
199 public CharSequence loadLabel() {
200 return getContext().getString(mLabelId);
204 public Drawable loadIcon() {
209 public String getKey() {
213 public int getIntensity() {
218 private class SettingsObserver extends ContentObserver {
219 public SettingsObserver() {
220 super(new Handler());
223 public void register() {
224 getContext().getContentResolver().registerContentObserver(
225 Settings.System.getUriFor(getVibrationIntensitySetting()), false, this);
228 public void unregister() {
229 getContext().getContentResolver().unregisterContentObserver(this);
233 public void onChange(boolean selfChange, Uri uri) {
235 playVibrationPreview();