Home | History | Annotate | Download | only in sound
      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 
     17 package com.android.settings.sound;
     18 
     19 import static android.bluetooth.IBluetoothHearingAid.HI_SYNC_ID_INVALID;
     20 import static android.media.AudioManager.STREAM_MUSIC;
     21 import static android.media.AudioSystem.DEVICE_OUT_REMOTE_SUBMIX;
     22 import static android.media.AudioSystem.DEVICE_OUT_USB_HEADSET;
     23 
     24 import com.android.settingslib.Utils;
     25 
     26 import android.bluetooth.BluetoothDevice;
     27 import android.content.Context;
     28 import android.media.AudioManager;
     29 import android.support.v7.preference.Preference;
     30 
     31 import com.android.settings.R;
     32 import com.android.settingslib.bluetooth.A2dpProfile;
     33 import 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  */
     42 public 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