1/* 2 * Copyright (C) 2018 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 17package com.android.settings.sound; 18 19import static android.bluetooth.IBluetoothHearingAid.HI_SYNC_ID_INVALID; 20import static android.media.AudioManager.STREAM_MUSIC; 21import static android.media.AudioSystem.DEVICE_OUT_REMOTE_SUBMIX; 22import static android.media.AudioSystem.DEVICE_OUT_USB_HEADSET; 23 24import com.android.settingslib.Utils; 25 26import android.bluetooth.BluetoothDevice; 27import android.content.Context; 28import android.media.AudioManager; 29import android.support.v7.preference.Preference; 30 31import com.android.settings.R; 32import com.android.settingslib.bluetooth.A2dpProfile; 33import com.android.settingslib.bluetooth.HearingAidProfile; 34 35/** 36 * This class which allows switching between A2dp-connected & HAP-connected BT devices. 37 * A few conditions will disable this switcher: 38 * - No available BT device(s) 39 * - Media stream captured by cast device 40 * - During a call. 41 */ 42public class MediaOutputPreferenceController extends AudioSwitchPreferenceController { 43 44 public MediaOutputPreferenceController(Context context, String key) { 45 super(context, key); 46 } 47 48 @Override 49 public void updateState(Preference preference) { 50 if (preference == null) { 51 // In case UI is not ready. 52 return; 53 } 54 55 if (isStreamFromOutputDevice(STREAM_MUSIC, DEVICE_OUT_REMOTE_SUBMIX)) { 56 // In cast mode, disable switch entry. 57 mPreference.setVisible(false); 58 preference.setSummary(mContext.getText(R.string.media_output_summary_unavailable)); 59 return; 60 } 61 62 if (Utils.isAudioModeOngoingCall(mContext)) { 63 // Ongoing call status, switch entry for media will be disabled. 64 mPreference.setVisible(false); 65 preference.setSummary( 66 mContext.getText(R.string.media_out_summary_ongoing_call_state)); 67 return; 68 } 69 70 mConnectedDevices.clear(); 71 // Otherwise, list all of the A2DP connected device and display the active device. 72 if (mAudioManager.getMode() == AudioManager.MODE_NORMAL) { 73 mConnectedDevices.addAll(getConnectedA2dpDevices()); 74 mConnectedDevices.addAll(getConnectedHearingAidDevices()); 75 } 76 77 final int numDevices = mConnectedDevices.size(); 78 if (numDevices == 0) { 79 // Disable switch entry if there is no connected devices. 80 mPreference.setVisible(false); 81 final CharSequence summary = mContext.getText(R.string.media_output_default_summary); 82 final CharSequence[] defaultMediaOutput = new CharSequence[]{summary}; 83 mSelectedIndex = getDefaultDeviceIndex(); 84 preference.setSummary(summary); 85 setPreference(defaultMediaOutput, defaultMediaOutput, preference); 86 return; 87 } 88 89 mPreference.setVisible(true); 90 CharSequence[] mediaOutputs = new CharSequence[numDevices + 1]; 91 CharSequence[] mediaValues = new CharSequence[numDevices + 1]; 92 93 // Setup devices entries, select active connected device 94 setupPreferenceEntries(mediaOutputs, mediaValues, findActiveDevice(STREAM_MUSIC)); 95 96 if (isStreamFromOutputDevice(STREAM_MUSIC, DEVICE_OUT_USB_HEADSET)) { 97 // If wired headset is plugged in and active, select to default device. 98 mSelectedIndex = getDefaultDeviceIndex(); 99 } 100 101 // Display connected devices, default device and show the active device 102 setPreference(mediaOutputs, mediaValues, preference); 103 } 104 105 @Override 106 public void setActiveBluetoothDevice(BluetoothDevice device) { 107 if (mAudioManager.getMode() != AudioManager.MODE_NORMAL) { 108 return; 109 } 110 final HearingAidProfile hapProfile = mProfileManager.getHearingAidProfile(); 111 final A2dpProfile a2dpProfile = mProfileManager.getA2dpProfile(); 112 if (hapProfile != null && a2dpProfile != null && device == null) { 113 hapProfile.setActiveDevice(null); 114 a2dpProfile.setActiveDevice(null); 115 return; 116 } 117 if (hapProfile != null && hapProfile.getHiSyncId(device) != HI_SYNC_ID_INVALID) { 118 hapProfile.setActiveDevice(device); 119 } 120 if (a2dpProfile != null) { 121 a2dpProfile.setActiveDevice(device); 122 } 123 } 124} 125