1 /*
2  * Copyright 2024 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 import android.sysprop.BluetoothProperties;
25 import android.text.TextUtils;
26 
27 import androidx.annotation.NonNull;
28 import androidx.annotation.Nullable;
29 import androidx.annotation.VisibleForTesting;
30 import androidx.preference.ListPreference;
31 import androidx.preference.Preference;
32 
33 import com.android.settings.R;
34 import com.android.settings.core.PreferenceControllerMixin;
35 import com.android.settingslib.development.DeveloperOptionsPreferenceController;
36 
37 
38 /**
39  * Preference controller to control Bluetooth LE audio mode
40  */
41 public class BluetoothLeAudioModePreferenceController
42         extends DeveloperOptionsPreferenceController
43         implements Preference.OnPreferenceChangeListener, PreferenceControllerMixin {
44 
45     private static final String PREFERENCE_KEY = "bluetooth_leaudio_mode";
46 
47     static final String LE_AUDIO_DYNAMIC_SWITCHER_MODE_PROPERTY =
48             "persist.bluetooth.leaudio_dynamic_switcher.mode";
49 
50     @Nullable private final DevelopmentSettingsDashboardFragment mFragment;
51 
52     private final String[] mListValues;
53     private final String[] mListSummaries;
54     @VisibleForTesting
55     @Nullable String mNewMode;
56     @VisibleForTesting
57     BluetoothAdapter mBluetoothAdapter;
58 
59     boolean mChanged = false;
60 
BluetoothLeAudioModePreferenceController(@onNull Context context, @Nullable DevelopmentSettingsDashboardFragment fragment)61     public BluetoothLeAudioModePreferenceController(@NonNull Context context,
62             @Nullable DevelopmentSettingsDashboardFragment fragment) {
63         super(context);
64         mFragment = fragment;
65         mBluetoothAdapter = context.getSystemService(BluetoothManager.class).getAdapter();
66 
67         mListValues = context.getResources().getStringArray(R.array.bluetooth_leaudio_mode_values);
68         mListSummaries = context.getResources().getStringArray(R.array.bluetooth_leaudio_mode);
69     }
70 
71     @Override
getPreferenceKey()72     @NonNull public String getPreferenceKey() {
73         return PREFERENCE_KEY;
74     }
75 
76     @Override
isAvailable()77     public boolean isAvailable() {
78         return BluetoothProperties.isProfileBapBroadcastSourceEnabled().orElse(false);
79     }
80 
81     @Override
onPreferenceChange(@onNull Preference preference, Object newValue)82     public boolean onPreferenceChange(@NonNull Preference preference, Object newValue) {
83         if (mFragment == null) {
84             return false;
85         }
86 
87         BluetoothRebootDialog.show(mFragment);
88         mChanged = true;
89         mNewMode = newValue.toString();
90         return false;
91     }
92 
93     @Override
updateState(@onNull Preference preference)94     public void updateState(@NonNull Preference preference) {
95         if (mBluetoothAdapter == null) {
96             return;
97         }
98 
99         String currentValue;
100         if (mBluetoothAdapter.isLeAudioBroadcastSourceSupported()
101                 == BluetoothStatusCodes.FEATURE_SUPPORTED) {
102             currentValue = "broadcast";
103         } else if (mBluetoothAdapter.isLeAudioSupported()
104                 == BluetoothStatusCodes.FEATURE_SUPPORTED) {
105             currentValue = "unicast";
106         } else {
107             currentValue = "disabled";
108         }
109 
110         int index = 0;
111         for (int i = 0; i < mListValues.length; i++) {
112             if (TextUtils.equals(currentValue, mListValues[i])) {
113                 index = i;
114                 break;
115             }
116         }
117 
118         final ListPreference listPreference = (ListPreference) preference;
119         listPreference.setValue(mListValues[index]);
120         listPreference.setSummary(mListSummaries[index]);
121 
122         if (!mBluetoothAdapter.isEnabled()) {
123             listPreference.setEnabled(false);
124             return;
125         }
126     }
127 
128     /**
129      * Called when the RebootDialog confirm is clicked.
130      */
onRebootDialogConfirmed()131     public void onRebootDialogConfirmed() {
132         if (!mChanged) {
133             return;
134         }
135         SystemProperties.set(LE_AUDIO_DYNAMIC_SWITCHER_MODE_PROPERTY, mNewMode);
136     }
137 
138     /**
139      * Called when the RebootDialog cancel is clicked.
140      */
onRebootDialogCanceled()141     public void onRebootDialogCanceled() {
142         mChanged = false;
143     }
144 }
145