• 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                 setCodecConfigPreference(null, codecConfig);    // Use current active device
87             }
88         }
89         // Because the setting is not persisted into permanent storage, we cannot call update state
90         // here to update the preference.
91         // Instead, we just assume it was set and update the preference here.
92         final int index = mPreference.findIndexOfValue(newValue.toString());
93         // We only want to append "Streaming" if not using default
94         if (index == getDefaultIndex()) {
95             mPreference.setSummary(mListSummaries[index]);
96         } else {
97             mPreference.setSummary(
98                     mContext.getResources().getString(STREAMING_LABEL_ID, mListSummaries[index]));
99         }
100         return true;
101     }
102 
103     @Override
updateState(Preference preference)104     public void updateState(Preference preference) {
105         if (getCodecConfig(null) == null || mPreference == null) { // Use current active device
106             return;
107         }
108 
109         BluetoothCodecConfig codecConfig;
110         synchronized (mBluetoothA2dpConfigStore) {
111             codecConfig = getCodecConfig(null);         // Use current active device
112         }
113 
114         final int index = getCurrentA2dpSettingIndex(codecConfig);
115         mPreference.setValue(mListValues[index]);
116 
117         // We only want to append "Streaming" if not using default
118         if (index == getDefaultIndex()) {
119             mPreference.setSummary(mListSummaries[index]);
120         } else {
121             mPreference.setSummary(
122                     mContext.getResources().getString(STREAMING_LABEL_ID, mListSummaries[index]));
123         }
124 
125         writeConfigurationValues(mListValues[index]);
126     }
127 
128     @Override
onBluetoothServiceConnected(BluetoothA2dp bluetoothA2dp)129     public void onBluetoothServiceConnected(BluetoothA2dp bluetoothA2dp) {
130         mBluetoothA2dp = bluetoothA2dp;
131         updateState(mPreference);
132     }
133 
134     @Override
onBluetoothCodecUpdated()135     public void onBluetoothCodecUpdated() {
136         // intentional no-op
137         // We do not want to call update state here because the setting is not persisted in
138         // permanent storage.
139     }
140 
141     @Override
onBluetoothServiceDisconnected()142     public void onBluetoothServiceDisconnected() {
143         mBluetoothA2dp = null;
144     }
145 
146     @Override
onDestroy()147     public void onDestroy() {
148         mBluetoothA2dp = null;
149     }
150 
151     /**
152      * @return an array of string values that correspond to the current {@link ListPreference}.
153      */
getListValues()154     protected abstract String[] getListValues();
155 
156     /**
157      * @return an array of string summaries that correspond to the current {@link ListPreference}.
158      */
getListSummaries()159     protected abstract String[] getListSummaries();
160 
161     /**
162      * Updates the new value to the {@link BluetoothA2dpConfigStore} and the {@link BluetoothA2dp}.
163      *
164      * @param newValue the new setting value
165      */
writeConfigurationValues(Object newValue)166     protected abstract void writeConfigurationValues(Object newValue);
167 
168     /**
169      * @return the current selected index for the {@link ListPreference}.
170      */
getCurrentA2dpSettingIndex(BluetoothCodecConfig config)171     protected abstract int getCurrentA2dpSettingIndex(BluetoothCodecConfig config);
172 
173     /**
174      * @return default setting index for the {@link ListPreference}.
175      */
getDefaultIndex()176     protected abstract int getDefaultIndex();
177 
178     @VisibleForTesting
setCodecConfigPreference(BluetoothDevice device, BluetoothCodecConfig config)179     void setCodecConfigPreference(BluetoothDevice device,
180             BluetoothCodecConfig config) {
181         mBluetoothA2dp.setCodecConfigPreference(device, config);
182     }
183 
184     @VisibleForTesting
getCodecConfig(BluetoothDevice device)185     BluetoothCodecConfig getCodecConfig(BluetoothDevice device) {
186         if (mBluetoothA2dp != null) {
187             BluetoothCodecStatus codecStatus = mBluetoothA2dp.getCodecStatus(device);
188             if (codecStatus != null) {
189                 return codecStatus.getCodecConfig();
190             }
191         }
192         return null;
193     }
194 }
195