• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 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.BluetoothA2dp;
20 import android.bluetooth.BluetoothCodecConfig;
21 import android.bluetooth.BluetoothCodecStatus;
22 import android.bluetooth.BluetoothDevice;
23 import android.content.Context;
24 
25 import androidx.annotation.VisibleForTesting;
26 import androidx.preference.ListPreference;
27 import androidx.preference.Preference;
28 import androidx.preference.PreferenceScreen;
29 
30 import com.android.settings.R;
31 import com.android.settings.core.PreferenceControllerMixin;
32 import com.android.settingslib.core.lifecycle.Lifecycle;
33 import com.android.settingslib.core.lifecycle.LifecycleObserver;
34 import com.android.settingslib.core.lifecycle.events.OnDestroy;
35 import com.android.settingslib.development.DeveloperOptionsPreferenceController;
36 
37 public abstract class AbstractBluetoothA2dpPreferenceController extends
38         DeveloperOptionsPreferenceController implements Preference.OnPreferenceChangeListener,
39         PreferenceControllerMixin, BluetoothServiceConnectionListener, LifecycleObserver,
40         OnDestroy {
41 
42     @VisibleForTesting
43     static final int STREAMING_LABEL_ID = R.string.bluetooth_select_a2dp_codec_streaming_label;
44 
45     protected final BluetoothA2dpConfigStore mBluetoothA2dpConfigStore;
46     protected BluetoothA2dp mBluetoothA2dp;
47     protected ListPreference mPreference;
48     private final String[] mListValues;
49     private final String[] mListSummaries;
50 
AbstractBluetoothA2dpPreferenceController(Context context, Lifecycle lifecycle, BluetoothA2dpConfigStore store)51     public AbstractBluetoothA2dpPreferenceController(Context context, Lifecycle lifecycle,
52             BluetoothA2dpConfigStore store) {
53         super(context);
54 
55         mBluetoothA2dpConfigStore = store;
56         mListValues = getListValues();
57         mListSummaries = getListSummaries();
58 
59         if (lifecycle != null) {
60             lifecycle.addObserver(this);
61         }
62     }
63 
64     @Override
displayPreference(PreferenceScreen screen)65     public void displayPreference(PreferenceScreen screen) {
66         super.displayPreference(screen);
67 
68         mPreference = screen.findPreference(getPreferenceKey());
69 
70         // Set a default value because BluetoothCodecConfig is null initially.
71         mPreference.setValue(mListValues[getDefaultIndex()]);
72         mPreference.setSummary(mListSummaries[getDefaultIndex()]);
73     }
74 
75     @Override
onPreferenceChange(Preference preference, Object newValue)76     public boolean onPreferenceChange(Preference preference, Object newValue) {
77         if (mBluetoothA2dp == null) {
78             return false;
79         }
80 
81         writeConfigurationValues(newValue);
82 
83         final BluetoothCodecConfig codecConfig = mBluetoothA2dpConfigStore.createCodecConfig();
84         synchronized (mBluetoothA2dpConfigStore) {
85             if (mBluetoothA2dp != null) {
86                 BluetoothDevice activeDevice = mBluetoothA2dp.getActiveDevice();
87                 if (activeDevice == null) {
88                     return false;
89                 }
90                 setCodecConfigPreference(activeDevice, codecConfig);
91             }
92         }
93         // Because the setting is not persisted into permanent storage, we cannot call update state
94         // here to update the preference.
95         // Instead, we just assume it was set and update the preference here.
96         final int index = mPreference.findIndexOfValue(newValue.toString());
97         // We only want to append "Streaming" if not using default
98         if (index == getDefaultIndex()) {
99             mPreference.setSummary(mListSummaries[index]);
100         } else {
101             mPreference.setSummary(
102                     mContext.getResources().getString(STREAMING_LABEL_ID, mListSummaries[index]));
103         }
104         return true;
105     }
106 
107     @Override
updateState(Preference preference)108     public void updateState(Preference preference) {
109         BluetoothDevice activeDevice = mBluetoothA2dp.getActiveDevice();
110         if (activeDevice == null || getCodecConfig(activeDevice) == null || mPreference == null) {
111             return;
112         }
113 
114         BluetoothCodecConfig codecConfig;
115         synchronized (mBluetoothA2dpConfigStore) {
116             codecConfig = getCodecConfig(activeDevice);
117         }
118 
119         final int index = getCurrentA2dpSettingIndex(codecConfig);
120         mPreference.setValue(mListValues[index]);
121 
122         // We only want to append "Streaming" if not using default
123         if (index == getDefaultIndex()) {
124             mPreference.setSummary(mListSummaries[index]);
125         } else {
126             mPreference.setSummary(
127                     mContext.getResources().getString(STREAMING_LABEL_ID, mListSummaries[index]));
128         }
129 
130         writeConfigurationValues(mListValues[index]);
131     }
132 
133     @Override
onBluetoothServiceConnected(BluetoothA2dp bluetoothA2dp)134     public void onBluetoothServiceConnected(BluetoothA2dp bluetoothA2dp) {
135         mBluetoothA2dp = bluetoothA2dp;
136         updateState(mPreference);
137     }
138 
139     @Override
onBluetoothCodecUpdated()140     public void onBluetoothCodecUpdated() {
141         // intentional no-op
142         // We do not want to call update state here because the setting is not persisted in
143         // permanent storage.
144     }
145 
146     @Override
onBluetoothServiceDisconnected()147     public void onBluetoothServiceDisconnected() {
148         mBluetoothA2dp = null;
149     }
150 
151     @Override
onDestroy()152     public void onDestroy() {
153         mBluetoothA2dp = null;
154     }
155 
156     /**
157      * @return an array of string values that correspond to the current {@link ListPreference}.
158      */
getListValues()159     protected abstract String[] getListValues();
160 
161     /**
162      * @return an array of string summaries that correspond to the current {@link ListPreference}.
163      */
getListSummaries()164     protected abstract String[] getListSummaries();
165 
166     /**
167      * Updates the new value to the {@link BluetoothA2dpConfigStore} and the {@link BluetoothA2dp}.
168      *
169      * @param newValue the new setting value
170      */
writeConfigurationValues(Object newValue)171     protected abstract void writeConfigurationValues(Object newValue);
172 
173     /**
174      * @return the current selected index for the {@link ListPreference}.
175      */
getCurrentA2dpSettingIndex(BluetoothCodecConfig config)176     protected abstract int getCurrentA2dpSettingIndex(BluetoothCodecConfig config);
177 
178     /**
179      * @return default setting index for the {@link ListPreference}.
180      */
getDefaultIndex()181     protected abstract int getDefaultIndex();
182 
183     @VisibleForTesting
setCodecConfigPreference(BluetoothDevice device, BluetoothCodecConfig config)184     void setCodecConfigPreference(BluetoothDevice device,
185             BluetoothCodecConfig config) {
186         BluetoothDevice bluetoothDevice =
187                 (device != null) ? device : mBluetoothA2dp.getActiveDevice();
188         if (bluetoothDevice == null) {
189             return;
190         }
191         mBluetoothA2dp.setCodecConfigPreference(bluetoothDevice, config);
192     }
193 
194     @VisibleForTesting
getCodecConfig(BluetoothDevice device)195     BluetoothCodecConfig getCodecConfig(BluetoothDevice device) {
196         if (mBluetoothA2dp != null) {
197             BluetoothDevice bluetoothDevice =
198                     (device != null) ? device : mBluetoothA2dp.getActiveDevice();
199             if (bluetoothDevice == null) {
200                 return null;
201             }
202             BluetoothCodecStatus codecStatus = mBluetoothA2dp.getCodecStatus(bluetoothDevice);
203             if (codecStatus != null) {
204                 return codecStatus.getCodecConfig();
205             }
206         }
207         return null;
208     }
209 }
210