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