1 /*
2  * Copyright 2023 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 android.bluetooth.BluetoothAdapter;
20 import android.bluetooth.BluetoothManager;
21 import android.bluetooth.BluetoothStatusCodes;
22 import android.content.Context;
23 import android.os.SystemProperties;
24 
25 import androidx.annotation.VisibleForTesting;
26 import androidx.preference.Preference;
27 import androidx.preference.TwoStatePreference;
28 
29 import com.android.settings.core.PreferenceControllerMixin;
30 import com.android.settingslib.development.DeveloperOptionsPreferenceController;
31 
32 /**
33  * Preference controller to control whether display Bluetooth LE audio toggle in device detail
34  * settings page or not.
35  */
36 public class BluetoothLeAudioDeviceDetailsPreferenceController
37         extends DeveloperOptionsPreferenceController
38         implements Preference.OnPreferenceChangeListener, PreferenceControllerMixin {
39 
40     private static final String PREFERENCE_KEY = "bluetooth_show_leaudio_device_details";
41     private static final String LE_AUDIO_CONNECTION_BY_DEFAULT_PROPERTY =
42             "ro.bluetooth.leaudio.le_audio_connection_by_default";
43     private static final boolean LE_AUDIO_TOGGLE_VISIBLE_DEFAULT_VALUE = true;
44     static int sLeAudioSupportedStateCache = BluetoothStatusCodes.ERROR_UNKNOWN;
45 
46     static final String LE_AUDIO_TOGGLE_VISIBLE_PROPERTY =
47             "persist.bluetooth.leaudio.toggle_visible";
48 
49     @VisibleForTesting
50     BluetoothAdapter mBluetoothAdapter;
51     @VisibleForTesting boolean mLeAudioEnabledByDefault;
52 
BluetoothLeAudioDeviceDetailsPreferenceController(Context context)53     public BluetoothLeAudioDeviceDetailsPreferenceController(Context context) {
54         super(context);
55         mBluetoothAdapter = context.getSystemService(BluetoothManager.class).getAdapter();
56         mLeAudioEnabledByDefault =
57                 SystemProperties.getBoolean(LE_AUDIO_CONNECTION_BY_DEFAULT_PROPERTY, true);
58     }
59 
60     @Override
getPreferenceKey()61     public String getPreferenceKey() {
62         return PREFERENCE_KEY;
63     }
64 
65     @Override
isAvailable()66     public boolean isAvailable() {
67         if (sLeAudioSupportedStateCache == BluetoothStatusCodes.ERROR_UNKNOWN
68                 && mBluetoothAdapter != null) {
69             int isLeAudioSupported = mBluetoothAdapter.isLeAudioSupported();
70             if (isLeAudioSupported != BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED) {
71                 sLeAudioSupportedStateCache = isLeAudioSupported;
72             }
73         }
74 
75         // Display the option only if LE Audio is supported
76         return !mLeAudioEnabledByDefault
77                 && (sLeAudioSupportedStateCache == BluetoothStatusCodes.FEATURE_SUPPORTED);
78     }
79 
80     @Override
onPreferenceChange(Preference preference, Object newValue)81     public boolean onPreferenceChange(Preference preference, Object newValue) {
82         final boolean isEnabled = (Boolean) newValue;
83         SystemProperties.set(LE_AUDIO_TOGGLE_VISIBLE_PROPERTY, Boolean.toString(isEnabled));
84         return true;
85     }
86 
87     @Override
updateState(Preference preference)88     public void updateState(Preference preference) {
89         if (!isAvailable()) {
90             return;
91         }
92 
93         final boolean isLeAudioToggleVisible = SystemProperties.getBoolean(
94                 LE_AUDIO_TOGGLE_VISIBLE_PROPERTY, LE_AUDIO_TOGGLE_VISIBLE_DEFAULT_VALUE);
95 
96         ((TwoStatePreference) mPreference).setChecked(isLeAudioToggleVisible);
97     }
98 }
99