AudioSwitchPreferenceController.java revision 63bdfa8998791eb08fb70c21ea37d23c910e5057
15738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/* 25738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project * Copyright (C) 2018 The Android Open Source Project 35b790feeeb211c42bf78ca3ae9c26aa30e516765Jakub Pawlowski * 45738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 55738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project * you may not use this file except in compliance with the License. 65738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project * You may obtain a copy of the License at 75738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project * 85738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 95738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project * 105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project * See the License for the specific language governing permissions and 145738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project * limitations under the License. 155738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project */ 165738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 175738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectpackage com.android.settings.sound; 185738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1949a86709488e5cfd5e23759da18bf9613e15b04dMarie Janssen 2049120dc867c7818511b5afec461dfc97d17eef58Marie Janssenimport static android.media.AudioManager.STREAM_DEVICES_CHANGED_ACTION; 21f2af1c42ccb2f642b241c2261b42d0be61d45438Jack Heimport static android.media.MediaRouter.ROUTE_TYPE_REMOTE_DISPLAY; 22911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectimport android.bluetooth.BluetoothDevice; 245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectimport android.content.BroadcastReceiver; 255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectimport android.content.Context; 26aa0f6ecc4cfd5c401e6278ee7139ce0cacc40483Chris Mantonimport android.content.Intent; 27aa0f6ecc4cfd5c401e6278ee7139ce0cacc40483Chris Mantonimport android.content.IntentFilter; 285738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectimport android.media.AudioDeviceCallback; 29db554581079863974af8e1289646f5deea6fc044Marie Janssenimport android.media.AudioDeviceInfo; 30911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonimport android.media.AudioManager; 31aa0f6ecc4cfd5c401e6278ee7139ce0cacc40483Chris Mantonimport android.media.MediaRouter; 32db554581079863974af8e1289646f5deea6fc044Marie Janssenimport android.media.MediaRouter.Callback; 33db554581079863974af8e1289646f5deea6fc044Marie Janssenimport android.os.Handler; 345738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectimport android.os.Looper; 355738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectimport android.support.v7.preference.ListPreference; 36911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonimport android.support.v7.preference.Preference; 37db554581079863974af8e1289646f5deea6fc044Marie Janssenimport android.support.v7.preference.PreferenceScreen; 38db554581079863974af8e1289646f5deea6fc044Marie Janssenimport android.text.TextUtils; 39db554581079863974af8e1289646f5deea6fc044Marie Janssenimport android.util.FeatureFlagUtils; 40db554581079863974af8e1289646f5deea6fc044Marie Janssen 419891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnsonimport com.android.internal.util.ArrayUtils; 42aa0f6ecc4cfd5c401e6278ee7139ce0cacc40483Chris Mantonimport com.android.settings.R; 435738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectimport com.android.settings.bluetooth.Utils; 44f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavovimport com.android.settings.core.BasePreferenceController; 45d19e0785e662e640191a075eda07acce61c2aedaMarie Janssenimport com.android.settings.core.FeatureFlags; 465738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectimport com.android.settingslib.bluetooth.BluetoothCallback; 475738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectimport com.android.settingslib.bluetooth.CachedBluetoothDevice; 48d19e0785e662e640191a075eda07acce61c2aedaMarie Janssenimport com.android.settingslib.bluetooth.LocalBluetoothManager; 495738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectimport com.android.settingslib.bluetooth.LocalBluetoothProfileManager; 505738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectimport com.android.settingslib.core.lifecycle.LifecycleObserver; 518843cc830b522cfe6f1e361297fc28fd331a1378Hemant Guptaimport com.android.settingslib.core.lifecycle.events.OnStart; 528843cc830b522cfe6f1e361297fc28fd331a1378Hemant Guptaimport com.android.settingslib.core.lifecycle.events.OnStop; 538843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta 548843cc830b522cfe6f1e361297fc28fd331a1378Hemant Guptaimport java.util.List; 558843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta 568843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta/** 578843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta * Abstract class for audio switcher controller to notify subclass 58ead3cde4bac0c3e32cd31f149093f004eef8ceebGanesh Ganapathi Batta * updating the current status of switcher entry. Subclasses must overwrite 595738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project * {@link #setActiveBluetoothDevice(BluetoothDevice)} to set the 605738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project * active device for corresponding profile. 615738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project */ 625738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectpublic abstract class AudioSwitchPreferenceController extends BasePreferenceController 635738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project implements Preference.OnPreferenceChangeListener, BluetoothCallback, 645738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project LifecycleObserver, OnStart, OnStop { 657a3819f092b17536e247b4d147cac6a8cdfd0138Gurpreet Ghai 665738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project private static final int INVALID_INDEX = -1; 675738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 68911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson protected final AudioManager mAudioManager; 695738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project protected final MediaRouter mMediaRouter; 705738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project protected final LocalBluetoothProfileManager mProfileManager; 715738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project protected int mSelectedIndex; 72aa0f6ecc4cfd5c401e6278ee7139ce0cacc40483Chris Manton protected Preference mPreference; 73911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson protected List<BluetoothDevice> mConnectedDevices; 74911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 75911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson private final AudioManagerAudioDeviceCallback mAudioManagerAudioDeviceCallback; 76911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson private final LocalBluetoothManager mLocalBluetoothManager; 77911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson private final MediaRouterCallback mMediaRouterCallback; 78911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson private final WiredHeadsetBroadcastReceiver mReceiver; 79911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson private final Handler mHandler; 80911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 81911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson public AudioSwitchPreferenceController(Context context, String preferenceKey) { 82911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson super(context, preferenceKey); 83aa0f6ecc4cfd5c401e6278ee7139ce0cacc40483Chris Manton mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); 84aa0f6ecc4cfd5c401e6278ee7139ce0cacc40483Chris Manton mMediaRouter = (MediaRouter) context.getSystemService(Context.MEDIA_ROUTER_SERVICE); 85aa0f6ecc4cfd5c401e6278ee7139ce0cacc40483Chris Manton mLocalBluetoothManager = Utils.getLocalBtManager(mContext); 86aa0f6ecc4cfd5c401e6278ee7139ce0cacc40483Chris Manton mLocalBluetoothManager.setForegroundActivity(context); 875738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project mProfileManager = mLocalBluetoothManager.getProfileManager(); 885738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project mHandler = new Handler(Looper.getMainLooper()); 89aa0f6ecc4cfd5c401e6278ee7139ce0cacc40483Chris Manton mAudioManagerAudioDeviceCallback = new AudioManagerAudioDeviceCallback(); 90911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson mReceiver = new WiredHeadsetBroadcastReceiver(); 91911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson mMediaRouterCallback = new MediaRouterCallback(); 92911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 93911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 94911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /** 95911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson * Make this method as final, ensure that subclass will checking 96911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson * the feature flag and they could mistakenly break it via overriding. 97911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson */ 98911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson @Override 99911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson public final int getAvailabilityStatus() { 100911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return FeatureFlagUtils.isEnabled(mContext, FeatureFlags.AUDIO_SWITCHER_SETTINGS) 101911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson ? AVAILABLE : DISABLED_UNSUPPORTED; 102d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen } 103911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 104911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson @Override 1055738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project public boolean onPreferenceChange(Preference preference, Object newValue) { 106911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson final String address = (String) newValue; 107911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (!(preference instanceof ListPreference)) { 1088843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta return false; 1098843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta } 1108843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta 1118843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta final ListPreference listPreference = (ListPreference) preference; 112d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen if (TextUtils.equals(address, mContext.getText(R.string.media_output_default_summary))) { 113911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson // Switch to default device which address is device name 114911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson mSelectedIndex = getDefaultDeviceIndex(); 1155738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project setActiveBluetoothDevice(null); 116911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson listPreference.setSummary(mContext.getText(R.string.media_output_default_summary)); 117911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } else { 118911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson // Switch to BT device which address is hardware address 119911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson final int connectedDeviceIndex = getConnectedDeviceIndex(address); 1208843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta if (connectedDeviceIndex == INVALID_INDEX) { 1218843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta return false; 1228843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta } 1238843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta final BluetoothDevice btDevice = mConnectedDevices.get(connectedDeviceIndex); 124911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson mSelectedIndex = connectedDeviceIndex; 125911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson setActiveBluetoothDevice(btDevice); 126911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson listPreference.setSummary(btDevice.getName()); 127911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 128911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return true; 129911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 130911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 131911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson public abstract void setActiveBluetoothDevice(BluetoothDevice device); 132911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 133911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson @Override 134911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson public void displayPreference(PreferenceScreen screen) { 1357a3819f092b17536e247b4d147cac6a8cdfd0138Gurpreet Ghai super.displayPreference(screen); 136aa0f6ecc4cfd5c401e6278ee7139ce0cacc40483Chris Manton mPreference = screen.findPreference(mPreferenceKey); 137911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 138aa0f6ecc4cfd5c401e6278ee7139ce0cacc40483Chris Manton 139aa0f6ecc4cfd5c401e6278ee7139ce0cacc40483Chris Manton @Override 140aa0f6ecc4cfd5c401e6278ee7139ce0cacc40483Chris Manton public void onStart() { 141aa0f6ecc4cfd5c401e6278ee7139ce0cacc40483Chris Manton register(); 142aa0f6ecc4cfd5c401e6278ee7139ce0cacc40483Chris Manton } 143aa0f6ecc4cfd5c401e6278ee7139ce0cacc40483Chris Manton 144911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson @Override 145aa0f6ecc4cfd5c401e6278ee7139ce0cacc40483Chris Manton public void onStop() { 146db554581079863974af8e1289646f5deea6fc044Marie Janssen unregister(); 147aa0f6ecc4cfd5c401e6278ee7139ce0cacc40483Chris Manton } 148aa0f6ecc4cfd5c401e6278ee7139ce0cacc40483Chris Manton 149db554581079863974af8e1289646f5deea6fc044Marie Janssen /** 150aa0f6ecc4cfd5c401e6278ee7139ce0cacc40483Chris Manton * Only concerned about whether the local adapter is connected to any profile of any device and 151aa0f6ecc4cfd5c401e6278ee7139ce0cacc40483Chris Manton * are not really concerned about which profile. 152aa0f6ecc4cfd5c401e6278ee7139ce0cacc40483Chris Manton */ 153db554581079863974af8e1289646f5deea6fc044Marie Janssen @Override 154aa0f6ecc4cfd5c401e6278ee7139ce0cacc40483Chris Manton public void onConnectionStateChanged(CachedBluetoothDevice cachedDevice, int state) { 155aa0f6ecc4cfd5c401e6278ee7139ce0cacc40483Chris Manton updateState(mPreference); 156db554581079863974af8e1289646f5deea6fc044Marie Janssen } 157aa0f6ecc4cfd5c401e6278ee7139ce0cacc40483Chris Manton 158aa0f6ecc4cfd5c401e6278ee7139ce0cacc40483Chris Manton @Override 1599ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson public void onActiveDeviceChanged(CachedBluetoothDevice activeDevice, int bluetoothProfile) { 1605d700dd909645dd1fe120014d817041aaed43b8dMyles Watson updateState(mPreference); 1615d700dd909645dd1fe120014d817041aaed43b8dMyles Watson } 162aa0f6ecc4cfd5c401e6278ee7139ce0cacc40483Chris Manton 163aa0f6ecc4cfd5c401e6278ee7139ce0cacc40483Chris Manton @Override 164aa0f6ecc4cfd5c401e6278ee7139ce0cacc40483Chris Manton public void onAudioModeChanged() { 1655738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project updateState(mPreference); 166aa0f6ecc4cfd5c401e6278ee7139ce0cacc40483Chris Manton } 167aa0f6ecc4cfd5c401e6278ee7139ce0cacc40483Chris Manton 168911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson @Override 1695738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project public void onBluetoothStateChanged(int bluetoothState) { 170aa0f6ecc4cfd5c401e6278ee7139ce0cacc40483Chris Manton } 171aa0f6ecc4cfd5c401e6278ee7139ce0cacc40483Chris Manton 172aa0f6ecc4cfd5c401e6278ee7139ce0cacc40483Chris Manton /** 173aa0f6ecc4cfd5c401e6278ee7139ce0cacc40483Chris Manton * The local Bluetooth adapter has started the remote device discovery process. 174911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson */ 175aa0f6ecc4cfd5c401e6278ee7139ce0cacc40483Chris Manton @Override 176aa0f6ecc4cfd5c401e6278ee7139ce0cacc40483Chris Manton public void onScanningStateChanged(boolean started) { 177aa0f6ecc4cfd5c401e6278ee7139ce0cacc40483Chris Manton } 178aa0f6ecc4cfd5c401e6278ee7139ce0cacc40483Chris Manton 179aa0f6ecc4cfd5c401e6278ee7139ce0cacc40483Chris Manton /** 180911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson * Indicates a change in the bond state of a remote 181aa0f6ecc4cfd5c401e6278ee7139ce0cacc40483Chris Manton * device. For example, if a device is bonded (paired). 18278bcff79e1b1f0efce436b33bdd6da88745bfc8aPavlin Radoslavov */ 1835738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project @Override 1849891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson public void onDeviceAdded(CachedBluetoothDevice cachedDevice) { 185911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson updateState(mPreference); 186f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He } 1879891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson 188911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson @Override 189911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson public void onDeviceDeleted(CachedBluetoothDevice cachedDevice) { 190f3fb316634973d26cc4b4f55656b86e2a15bd69cJakub Pawlowski } 191f3fb316634973d26cc4b4f55656b86e2a15bd69cJakub Pawlowski 192911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson @Override 19395f6f1bed91aa523ba280667d109ee67bd6def0bEagle Kang public void onDeviceBondStateChanged(CachedBluetoothDevice cachedDevice, int bondState) { 19495f6f1bed91aa523ba280667d109ee67bd6def0bEagle Kang } 195911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1969891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson protected boolean isOngoingCallStatus() { 1979891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson int audioMode = mAudioManager.getMode(); 1989891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson return audioMode == AudioManager.MODE_RINGTONE 199911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson || audioMode == AudioManager.MODE_IN_CALL 200911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson || audioMode == AudioManager.MODE_IN_COMMUNICATION; 2019891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson } 202db554581079863974af8e1289646f5deea6fc044Marie Janssen 2039891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson int getDefaultDeviceIndex() { 2049891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson // Default device is after all connected devices. 2059891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson return ArrayUtils.size(mConnectedDevices); 20675b83661eaecceeb48c73891ced70904bf0ce01bJakub Pawlowski } 20775b83661eaecceeb48c73891ced70904bf0ce01bJakub Pawlowski 2089891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson void setupPreferenceEntries(CharSequence[] mediaOutputs, CharSequence[] mediaValues, 2099891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson BluetoothDevice activeDevice) { 2109891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson // default to current device 2119891f32471b5c01cf58e4d7dadb04cb3024a9a88Zach Johnson mSelectedIndex = getDefaultDeviceIndex(); 212b2a292b5d8df2f359c38b0787bc01181225a9bc9Pavlin Radoslavov // default device is after all connected devices. 213911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson mediaOutputs[mSelectedIndex] = mContext.getText(R.string.media_output_default_summary); 214911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson // use default device name as address 215911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson mediaValues[mSelectedIndex] = mContext.getText(R.string.media_output_default_summary); 216911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson for (int i = 0, size = mConnectedDevices.size(); i < size; i++) { 217911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson final BluetoothDevice btDevice = mConnectedDevices.get(i); 218911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson mediaOutputs[i] = btDevice.getName(); 219 mediaValues[i] = btDevice.getAddress(); 220 if (btDevice.equals(activeDevice)) { 221 // select the active connected device. 222 mSelectedIndex = i; 223 } 224 } 225 } 226 227 void setPreference(CharSequence[] mediaOutputs, CharSequence[] mediaValues, 228 Preference preference) { 229 final ListPreference listPreference = (ListPreference) preference; 230 listPreference.setEntries(mediaOutputs); 231 listPreference.setEntryValues(mediaValues); 232 listPreference.setValueIndex(mSelectedIndex); 233 listPreference.setSummary(mediaOutputs[mSelectedIndex]); 234 } 235 236 private int getConnectedDeviceIndex(String hardwareAddress) { 237 if (mConnectedDevices != null) { 238 for (int i = 0, size = mConnectedDevices.size(); i < size; i++) { 239 final BluetoothDevice btDevice = mConnectedDevices.get(i); 240 if (TextUtils.equals(btDevice.getAddress(), hardwareAddress)) { 241 return i; 242 } 243 } 244 } 245 return INVALID_INDEX; 246 } 247 248 private void register() { 249 mLocalBluetoothManager.getEventManager().registerCallback(this); 250 mAudioManager.registerAudioDeviceCallback(mAudioManagerAudioDeviceCallback, mHandler); 251 mMediaRouter.addCallback(ROUTE_TYPE_REMOTE_DISPLAY, mMediaRouterCallback); 252 253 // Register for misc other intent broadcasts. 254 IntentFilter intentFilter = new IntentFilter(Intent.ACTION_HEADSET_PLUG); 255 intentFilter.addAction(STREAM_DEVICES_CHANGED_ACTION); 256 mContext.registerReceiver(mReceiver, intentFilter); 257 } 258 259 private void unregister() { 260 mLocalBluetoothManager.getEventManager().unregisterCallback(this); 261 mAudioManager.unregisterAudioDeviceCallback(mAudioManagerAudioDeviceCallback); 262 mMediaRouter.removeCallback(mMediaRouterCallback); 263 mContext.unregisterReceiver(mReceiver); 264 } 265 266 /** Callback for headset plugged and unplugged events. */ 267 private class AudioManagerAudioDeviceCallback extends AudioDeviceCallback { 268 @Override 269 public void onAudioDevicesAdded(AudioDeviceInfo[] addedDevices) { 270 updateState(mPreference); 271 } 272 273 @Override 274 public void onAudioDevicesRemoved(AudioDeviceInfo[] devices) { 275 updateState(mPreference); 276 } 277 } 278 279 /** Receiver for wired headset plugged and unplugged events. */ 280 private class WiredHeadsetBroadcastReceiver extends BroadcastReceiver { 281 @Override 282 public void onReceive(Context context, Intent intent) { 283 final String action = intent.getAction(); 284 if (AudioManager.ACTION_HEADSET_PLUG.equals(action) || 285 AudioManager.STREAM_DEVICES_CHANGED_ACTION.equals(action)) { 286 updateState(mPreference); 287 } 288 } 289 } 290 291 /** Callback for cast device events. */ 292 private class MediaRouterCallback extends Callback { 293 @Override 294 public void onRouteSelected(MediaRouter router, int type, MediaRouter.RouteInfo info) { 295 } 296 297 @Override 298 public void onRouteUnselected(MediaRouter router, int type, MediaRouter.RouteInfo info) { 299 } 300 301 @Override 302 public void onRouteAdded(MediaRouter router, MediaRouter.RouteInfo info) { 303 if (info != null && !info.isDefault()) { 304 // cast mode 305 updateState(mPreference); 306 } 307 } 308 309 @Override 310 public void onRouteRemoved(MediaRouter router, MediaRouter.RouteInfo info) { 311 } 312 313 @Override 314 public void onRouteChanged(MediaRouter router, MediaRouter.RouteInfo info) { 315 if (info != null && !info.isDefault()) { 316 // cast mode 317 updateState(mPreference); 318 } 319 } 320 321 @Override 322 public void onRouteGrouped(MediaRouter router, MediaRouter.RouteInfo info, 323 MediaRouter.RouteGroup group, int index) { 324 } 325 326 @Override 327 public void onRouteUngrouped(MediaRouter router, MediaRouter.RouteInfo info, 328 MediaRouter.RouteGroup group) { 329 } 330 331 @Override 332 public void onRouteVolumeChanged(MediaRouter router, MediaRouter.RouteInfo info) { 333 } 334 } 335} 336