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