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 17 package com.android.settings.gestures; 18 19 import static android.provider.Settings.Secure.VOLUME_HUSH_GESTURE; 20 import static android.provider.Settings.Secure.VOLUME_HUSH_MUTE; 21 import static android.provider.Settings.Secure.VOLUME_HUSH_VIBRATE; 22 23 import android.content.ContentResolver; 24 import android.content.Context; 25 import android.database.ContentObserver; 26 import android.net.Uri; 27 import android.os.Handler; 28 import android.provider.Settings; 29 30 import androidx.preference.Preference; 31 import androidx.preference.PreferenceScreen; 32 33 import com.android.settings.R; 34 import com.android.settings.core.TogglePreferenceController; 35 import com.android.settingslib.PrimarySwitchPreference; 36 import com.android.settingslib.core.lifecycle.LifecycleObserver; 37 import com.android.settingslib.core.lifecycle.events.OnStart; 38 import com.android.settingslib.core.lifecycle.events.OnStop; 39 40 import com.google.common.annotations.VisibleForTesting; 41 42 /** The controller manages the behaviour of the Prevent Ringing gesture setting. */ 43 public class PreventRingingParentPreferenceController extends TogglePreferenceController 44 implements LifecycleObserver, OnStart, OnStop { 45 46 @VisibleForTesting 47 static final int KEY_CHORD_POWER_VOLUME_UP_MUTE_TOGGLE = 1; 48 49 final String SECURE_KEY = VOLUME_HUSH_GESTURE; 50 51 private PrimarySwitchPreference mPreference; 52 private SettingObserver mSettingObserver; 53 PreventRingingParentPreferenceController(Context context, String preferenceKey)54 public PreventRingingParentPreferenceController(Context context, String preferenceKey) { 55 super(context, preferenceKey); 56 } 57 58 @Override displayPreference(PreferenceScreen screen)59 public void displayPreference(PreferenceScreen screen) { 60 super.displayPreference(screen); 61 mPreference = screen.findPreference(getPreferenceKey()); 62 mSettingObserver = new SettingObserver(mPreference); 63 } 64 65 @Override isChecked()66 public boolean isChecked() { 67 if (!isVolumePowerKeyChordSetToHush()) { 68 return false; 69 } 70 71 final int preventRinging = Settings.Secure.getInt(mContext.getContentResolver(), 72 Settings.Secure.VOLUME_HUSH_GESTURE, 73 Settings.Secure.VOLUME_HUSH_VIBRATE); 74 return preventRinging != Settings.Secure.VOLUME_HUSH_OFF; 75 } 76 77 @Override setChecked(boolean isChecked)78 public boolean setChecked(boolean isChecked) { 79 final int preventRingingSetting = Settings.Secure.getInt(mContext.getContentResolver(), 80 Settings.Secure.VOLUME_HUSH_GESTURE, Settings.Secure.VOLUME_HUSH_VIBRATE); 81 final int newRingingSetting = preventRingingSetting == Settings.Secure.VOLUME_HUSH_OFF 82 ? Settings.Secure.VOLUME_HUSH_VIBRATE 83 : preventRingingSetting; 84 85 return Settings.Secure.putInt(mContext.getContentResolver(), 86 Settings.Secure.VOLUME_HUSH_GESTURE, isChecked 87 ? newRingingSetting 88 : Settings.Secure.VOLUME_HUSH_OFF); 89 } 90 91 @Override updateState(Preference preference)92 public void updateState(Preference preference) { 93 super.updateState(preference); 94 final int value = Settings.Secure.getInt( 95 mContext.getContentResolver(), SECURE_KEY, VOLUME_HUSH_VIBRATE); 96 CharSequence summary; 97 if (isVolumePowerKeyChordSetToHush()) { 98 switch (value) { 99 case VOLUME_HUSH_VIBRATE: 100 summary = mContext.getText(R.string.prevent_ringing_option_vibrate_summary); 101 break; 102 case VOLUME_HUSH_MUTE: 103 summary = mContext.getText(R.string.prevent_ringing_option_mute_summary); 104 break; 105 // VOLUME_HUSH_OFF 106 default: 107 summary = mContext.getText(R.string.switch_off_text); 108 } 109 preference.setEnabled(true); 110 mPreference.setSwitchEnabled(true); 111 } else { 112 summary = mContext.getText(R.string.prevent_ringing_option_unavailable_lpp_summary); 113 preference.setEnabled(false); 114 mPreference.setSwitchEnabled(false); 115 } 116 117 preference.setSummary(summary); 118 } 119 120 @Override getAvailabilityStatus()121 public int getAvailabilityStatus() { 122 if (!mContext.getResources().getBoolean( 123 com.android.internal.R.bool.config_volumeHushGestureEnabled)) { 124 return UNSUPPORTED_ON_DEVICE; 125 } 126 if (isVolumePowerKeyChordSetToHush()) { 127 return AVAILABLE; 128 } 129 if (mContext.getResources().getBoolean( 130 com.android.internal 131 .R.bool.config_longPressOnPowerForAssistantSettingAvailable)) { 132 // The power + volume key chord is not set to hush gesture - it's been disabled 133 // by long press power for Assistant. 134 return DISABLED_DEPENDENT_SETTING; 135 } 136 137 return UNSUPPORTED_ON_DEVICE; 138 } 139 140 @Override getSliceHighlightMenuRes()141 public int getSliceHighlightMenuRes() { 142 return R.string.menu_key_sound; 143 } 144 145 @Override onStart()146 public void onStart() { 147 if (mSettingObserver != null) { 148 mSettingObserver.register(mContext.getContentResolver()); 149 mSettingObserver.onChange(false, null); 150 } 151 } 152 153 @Override onStop()154 public void onStop() { 155 if (mSettingObserver != null) { 156 mSettingObserver.unregister(mContext.getContentResolver()); 157 } 158 } 159 160 /** 161 * Returns true if power + volume up key chord is actually set to "mute toggle". If not, 162 * this setting will have no effect and should be disabled. 163 * 164 * This handles the condition when long press on power for Assistant changes power + volume 165 * chord to power menu and this setting needs to be disabled. 166 */ isVolumePowerKeyChordSetToHush()167 private boolean isVolumePowerKeyChordSetToHush() { 168 return Settings.Global.getInt(mContext.getContentResolver(), 169 Settings.Global.KEY_CHORD_POWER_VOLUME_UP, 170 mContext.getResources().getInteger( 171 com.android.internal.R.integer.config_keyChordPowerVolumeUp)) 172 == KEY_CHORD_POWER_VOLUME_UP_MUTE_TOGGLE; 173 } 174 175 private class SettingObserver extends ContentObserver { 176 private final Uri mVolumeHushGestureUri = Settings.Secure.getUriFor( 177 Settings.Secure.VOLUME_HUSH_GESTURE); 178 private final Uri mKeyChordVolumePowerUpUri = Settings.Global.getUriFor( 179 Settings.Global.KEY_CHORD_POWER_VOLUME_UP); 180 181 private final Preference mPreference; 182 SettingObserver(Preference preference)183 SettingObserver(Preference preference) { 184 super(new Handler()); 185 mPreference = preference; 186 } 187 register(ContentResolver cr)188 public void register(ContentResolver cr) { 189 cr.registerContentObserver(mKeyChordVolumePowerUpUri, false, this); 190 cr.registerContentObserver(mVolumeHushGestureUri, false, this); 191 } 192 unregister(ContentResolver cr)193 public void unregister(ContentResolver cr) { 194 cr.unregisterContentObserver(this); 195 } 196 197 @Override onChange(boolean selfChange, Uri uri)198 public void onChange(boolean selfChange, Uri uri) { 199 super.onChange(selfChange, uri); 200 if (uri == null || mVolumeHushGestureUri.equals(uri) 201 || mKeyChordVolumePowerUpUri.equals(uri)) { 202 updateState(mPreference); 203 } 204 } 205 } 206 } 207