1 /*
2  * Copyright (C) 2022 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.AccessibilityUtil.State.OFF;
20 import static com.android.settings.accessibility.AccessibilityUtil.State.ON;
21 
22 import android.content.Context;
23 import android.database.ContentObserver;
24 import android.net.Uri;
25 import android.os.Handler;
26 import android.os.VibrationAttributes;
27 import android.os.Vibrator;
28 import android.provider.Settings;
29 
30 import com.android.settings.R;
31 import com.android.settings.widget.SettingsMainSwitchPreferenceController;
32 import com.android.settingslib.core.lifecycle.LifecycleObserver;
33 import com.android.settingslib.core.lifecycle.events.OnStart;
34 import com.android.settingslib.core.lifecycle.events.OnStop;
35 
36 /**
37  * Preference controller for the main switch setting for vibration and haptics screen.
38  *
39  * <p>This preference is controlled by the setting key{@link Settings.System#VIBRATE_ON}, and it
40  * will disable the entire settings screen once the settings is turned OFF. All device haptics will
41  * be disabled by this setting, except the flagged alerts and accessibility touch feedback.
42  */
43 public class VibrationMainSwitchPreferenceController extends SettingsMainSwitchPreferenceController
44         implements LifecycleObserver, OnStart, OnStop {
45 
46     private final ContentObserver mSettingObserver;
47     private final Vibrator mVibrator;
48 
VibrationMainSwitchPreferenceController(Context context, String preferenceKey)49     public VibrationMainSwitchPreferenceController(Context context, String preferenceKey) {
50         super(context, preferenceKey);
51         mVibrator = context.getSystemService(Vibrator.class);
52         mSettingObserver = new ContentObserver(new Handler(/* async= */ true)) {
53             @Override
54             public void onChange(boolean selfChange, Uri uri) {
55                 updateState(mSwitchPreference);
56             }
57         };
58     }
59 
60     @Override
getAvailabilityStatus()61     public int getAvailabilityStatus() {
62         return AVAILABLE;
63     }
64 
65     @Override
onStart()66     public void onStart() {
67         mContext.getContentResolver().registerContentObserver(
68                 Settings.System.getUriFor(VibrationPreferenceConfig.MAIN_SWITCH_SETTING_KEY),
69                 /* notifyForDescendants= */ false,
70                 mSettingObserver);
71     }
72 
73     @Override
onStop()74     public void onStop() {
75         mContext.getContentResolver().unregisterContentObserver(mSettingObserver);
76     }
77 
78     @Override
isChecked()79     public boolean isChecked() {
80         return VibrationPreferenceConfig.isMainVibrationSwitchEnabled(
81                 mContext.getContentResolver());
82     }
83 
84     @Override
setChecked(boolean isChecked)85     public boolean setChecked(boolean isChecked) {
86         // The main switch change can be triggered by both the user click and the
87         // SettingsMainSwitchPreferenceController state change. Make sure we only do it once.
88         boolean wasChecked = isChecked();
89         boolean success = Settings.System.putInt(mContext.getContentResolver(),
90                 VibrationPreferenceConfig.MAIN_SWITCH_SETTING_KEY,
91                 isChecked ? ON : OFF);
92 
93         if (success && !wasChecked && isChecked) {
94             // Play a haptic as preview for the main toggle only when touch feedback is enabled.
95             VibrationPreferenceConfig.playVibrationPreview(
96                     mVibrator, VibrationAttributes.USAGE_TOUCH);
97         }
98 
99         return success;
100     }
101 
102     @Override
getSliceHighlightMenuRes()103     public int getSliceHighlightMenuRes() {
104         return R.string.menu_key_accessibility;
105     }
106 }
107