1 /* 2 * Copyright 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.development; 18 19 import static com.android.settings.development.BluetoothA2dpHwOffloadPreferenceController.A2DP_OFFLOAD_DISABLED_PROPERTY; 20 21 import android.bluetooth.BluetoothAdapter; 22 import android.bluetooth.BluetoothManager; 23 import android.bluetooth.BluetoothStatusCodes; 24 import android.content.Context; 25 import android.os.SystemProperties; 26 27 import androidx.annotation.Nullable; 28 import androidx.annotation.VisibleForTesting; 29 import androidx.preference.Preference; 30 import androidx.preference.TwoStatePreference; 31 32 import com.android.settings.core.PreferenceControllerMixin; 33 import com.android.settingslib.development.DeveloperOptionsPreferenceController; 34 35 /** 36 * Preference controller to control Bluetooth LE audio offload 37 */ 38 public class BluetoothLeAudioHwOffloadPreferenceController 39 extends DeveloperOptionsPreferenceController 40 implements Preference.OnPreferenceChangeListener, PreferenceControllerMixin { 41 42 private static final String PREFERENCE_KEY = "bluetooth_disable_le_audio_hw_offload"; 43 @Nullable private final DevelopmentSettingsDashboardFragment mFragment; 44 45 static final String LE_AUDIO_OFFLOAD_DISABLED_PROPERTY = 46 "persist.bluetooth.leaudio_offload.disabled"; 47 static final String LE_AUDIO_OFFLOAD_SUPPORTED_PROPERTY = 48 "ro.bluetooth.leaudio_offload.supported"; 49 50 @VisibleForTesting 51 BluetoothAdapter mBluetoothAdapter; 52 53 @VisibleForTesting 54 boolean mChanged = false; 55 BluetoothLeAudioHwOffloadPreferenceController(Context context, @Nullable DevelopmentSettingsDashboardFragment fragment)56 public BluetoothLeAudioHwOffloadPreferenceController(Context context, 57 @Nullable DevelopmentSettingsDashboardFragment fragment) { 58 super(context); 59 mFragment = fragment; 60 mBluetoothAdapter = context.getSystemService(BluetoothManager.class).getAdapter(); 61 } 62 63 @Override getPreferenceKey()64 public String getPreferenceKey() { 65 return PREFERENCE_KEY; 66 } 67 68 @Override onPreferenceChange(Preference preference, Object newValue)69 public boolean onPreferenceChange(Preference preference, Object newValue) { 70 BluetoothRebootDialog.show(mFragment); 71 mChanged = true; 72 return false; 73 } 74 75 @Override updateState(Preference preference)76 public void updateState(Preference preference) { 77 if (mBluetoothAdapter == null) { 78 return; 79 } 80 81 final boolean leAudioEnabled = 82 (mBluetoothAdapter.isLeAudioSupported() == BluetoothStatusCodes.FEATURE_SUPPORTED); 83 final boolean leAudioOffloadSupported = 84 SystemProperties.getBoolean(LE_AUDIO_OFFLOAD_SUPPORTED_PROPERTY, false); 85 final boolean a2dpOffloadDisabled = 86 SystemProperties.getBoolean(A2DP_OFFLOAD_DISABLED_PROPERTY, false); 87 if (leAudioEnabled && leAudioOffloadSupported && !a2dpOffloadDisabled) { 88 final boolean offloadDisabled = 89 SystemProperties.getBoolean(LE_AUDIO_OFFLOAD_DISABLED_PROPERTY, true); 90 ((TwoStatePreference) mPreference).setChecked(offloadDisabled); 91 } else { 92 mPreference.setEnabled(false); 93 ((TwoStatePreference) mPreference).setChecked(true); 94 } 95 } 96 97 @Override onDeveloperOptionsSwitchDisabled()98 protected void onDeveloperOptionsSwitchDisabled() { 99 super.onDeveloperOptionsSwitchDisabled(); 100 if (mBluetoothAdapter == null) { 101 return; 102 } 103 104 final boolean leAudioEnabled = 105 (mBluetoothAdapter.isLeAudioSupported() == BluetoothStatusCodes.FEATURE_SUPPORTED); 106 final boolean leAudioOffloadSupported = 107 SystemProperties.getBoolean(LE_AUDIO_OFFLOAD_SUPPORTED_PROPERTY, false); 108 final boolean a2dpOffloadDisabled = 109 SystemProperties.getBoolean(A2DP_OFFLOAD_DISABLED_PROPERTY, false); 110 if (leAudioEnabled && leAudioOffloadSupported && !a2dpOffloadDisabled) { 111 ((TwoStatePreference) mPreference).setChecked(true); 112 SystemProperties.set(LE_AUDIO_OFFLOAD_DISABLED_PROPERTY, "true"); 113 } else { 114 mPreference.setEnabled(false); 115 } 116 } 117 118 /** 119 * Check if the le audio offload setting is default value. 120 */ isDefaultValue()121 public boolean isDefaultValue() { 122 final boolean offloadSupported = 123 !SystemProperties.getBoolean(A2DP_OFFLOAD_DISABLED_PROPERTY, false) 124 && SystemProperties.getBoolean(LE_AUDIO_OFFLOAD_SUPPORTED_PROPERTY, false); 125 final boolean offloadDisabled = 126 SystemProperties.getBoolean(LE_AUDIO_OFFLOAD_DISABLED_PROPERTY, false); 127 return offloadSupported ? offloadDisabled : true; 128 } 129 130 /** 131 * Called when the RebootDialog confirm is clicked. 132 */ onRebootDialogConfirmed()133 public void onRebootDialogConfirmed() { 134 if (!mChanged) { 135 return; 136 } 137 138 final boolean leaudioOffloadDisabled = 139 SystemProperties.getBoolean(LE_AUDIO_OFFLOAD_DISABLED_PROPERTY, 140 false); 141 SystemProperties.set(LE_AUDIO_OFFLOAD_DISABLED_PROPERTY, 142 Boolean.toString(!leaudioOffloadDisabled)); 143 } 144 145 /** 146 * Called when the RebootDialog cancel is clicked. 147 */ onRebootDialogCanceled()148 public void onRebootDialogCanceled() { 149 mChanged = false; 150 } 151 } 152