1f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin/*
2f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin * Copyright (C) 2008 The Android Open Source Project
3f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin *
4f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin * Licensed under the Apache License, Version 2.0 (the "License");
5f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin * you may not use this file except in compliance with the License.
6f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin * You may obtain a copy of the License at
7f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin *
8f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin *      http://www.apache.org/licenses/LICENSE-2.0
9f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin *
10f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin * Unless required by applicable law or agreed to in writing, software
11f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin * distributed under the License is distributed on an "AS IS" BASIS,
12f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin * See the License for the specific language governing permissions and
14f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin * limitations under the License.
15f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin */
16f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin
17f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin#include <math.h>
18f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin
19f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin//#define LOG_NDEBUG 0
20f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin#define LOG_TAG "A2dpAudioInterface"
21f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin#include <utils/Log.h>
22f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin#include <utils/String8.h>
23f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin
24f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin#include "A2dpAudioInterface.h"
25f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin#include "audio/liba2dp.h"
26f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin#include <hardware_legacy/power.h>
27f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin
28e81531e91ecae92aff471dbff9cbeb0f95ff4a80Dima Zavin
29e81531e91ecae92aff471dbff9cbeb0f95ff4a80Dima Zavinnamespace android_audio_legacy {
30f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin
31f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavinstatic const char *sA2dpWakeLock = "A2dpOutputStream";
32f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin#define MAX_WRITE_RETRIES  5
33f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin
34f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin// ----------------------------------------------------------------------------
35f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin
36f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin//AudioHardwareInterface* A2dpAudioInterface::createA2dpInterface()
37f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin//{
38f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin//    AudioHardwareInterface* hw = 0;
39f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin//
40f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin//    hw = AudioHardwareInterface::create();
41b381b932acfa441da5607f37ac4ef6573ed5be96Steve Block//    ALOGD("new A2dpAudioInterface(hw: %p)", hw);
42f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin//    hw = new A2dpAudioInterface(hw);
43f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin//    return hw;
44f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin//}
45f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin
46f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima ZavinA2dpAudioInterface::A2dpAudioInterface(AudioHardwareInterface* hw) :
47f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    mOutput(0), mHardwareInterface(hw), mBluetoothEnabled(true), mSuspended(false)
48f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin{
49f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin}
50f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin
51f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima ZavinA2dpAudioInterface::~A2dpAudioInterface()
52f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin{
53f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    closeOutputStream((AudioStreamOut *)mOutput);
54f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    delete mHardwareInterface;
55f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin}
56f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin
57f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavinstatus_t A2dpAudioInterface::initCheck()
58f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin{
59f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    if (mHardwareInterface == 0) return NO_INIT;
60f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    return mHardwareInterface->initCheck();
61f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin}
62f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin
63f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima ZavinAudioStreamOut* A2dpAudioInterface::openOutputStream(
64f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin        uint32_t devices, int *format, uint32_t *channels, uint32_t *sampleRate, status_t *status)
65f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin{
6633bf1b0fe363bd4892349d160f54d860567fab12Mike Lockwood    if (!audio_is_a2dp_out_device(devices)) {
676a70518b93928d1c91457ff805e375c82d76b0e5Steve Block        ALOGV("A2dpAudioInterface::openOutputStream() open HW device: %x", devices);
68f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin        return mHardwareInterface->openOutputStream(devices, format, channels, sampleRate, status);
69f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    }
70f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin
71f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    status_t err = 0;
72f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin
73f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    // only one output stream allowed
74f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    if (mOutput) {
75f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin        if (status)
76f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin            *status = -1;
77f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin        return NULL;
78f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    }
79f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin
80f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    // create new output stream
81f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    A2dpAudioStreamOut* out = new A2dpAudioStreamOut();
82f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    if ((err = out->set(devices, format, channels, sampleRate)) == NO_ERROR) {
83f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin        mOutput = out;
84f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin        mOutput->setBluetoothEnabled(mBluetoothEnabled);
85f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin        mOutput->setSuspended(mSuspended);
86f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    } else {
87f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin        delete out;
88f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    }
89f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin
90f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    if (status)
91f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin        *status = err;
92f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    return mOutput;
93f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin}
94f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin
95f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavinvoid A2dpAudioInterface::closeOutputStream(AudioStreamOut* out) {
96f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    if (mOutput == 0 || mOutput != out) {
97f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin        mHardwareInterface->closeOutputStream(out);
98f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    }
99f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    else {
100f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin        delete mOutput;
101f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin        mOutput = 0;
102f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    }
103f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin}
104f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin
105f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin
106f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima ZavinAudioStreamIn* A2dpAudioInterface::openInputStream(
107f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin        uint32_t devices, int *format, uint32_t *channels, uint32_t *sampleRate, status_t *status,
108f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin        AudioSystem::audio_in_acoustics acoustics)
109f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin{
110f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    return mHardwareInterface->openInputStream(devices, format, channels, sampleRate, status, acoustics);
111f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin}
112f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin
113f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavinvoid A2dpAudioInterface::closeInputStream(AudioStreamIn* in)
114f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin{
115f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    return mHardwareInterface->closeInputStream(in);
116f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin}
117f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin
118f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavinstatus_t A2dpAudioInterface::setMode(int mode)
119f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin{
120f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    return mHardwareInterface->setMode(mode);
121f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin}
122f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin
123f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavinstatus_t A2dpAudioInterface::setMicMute(bool state)
124f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin{
125f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    return mHardwareInterface->setMicMute(state);
126f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin}
127f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin
128f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavinstatus_t A2dpAudioInterface::getMicMute(bool* state)
129f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin{
130f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    return mHardwareInterface->getMicMute(state);
131f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin}
132f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin
133f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavinstatus_t A2dpAudioInterface::setParameters(const String8& keyValuePairs)
134f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin{
135f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    AudioParameter param = AudioParameter(keyValuePairs);
136f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    String8 value;
137f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    String8 key;
138f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    status_t status = NO_ERROR;
139f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin
1406a70518b93928d1c91457ff805e375c82d76b0e5Steve Block    ALOGV("setParameters() %s", keyValuePairs.string());
141f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin
142f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    key = "bluetooth_enabled";
143f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    if (param.get(key, value) == NO_ERROR) {
144f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin        mBluetoothEnabled = (value == "true");
145f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin        if (mOutput) {
146f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin            mOutput->setBluetoothEnabled(mBluetoothEnabled);
147f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin        }
148f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin        param.remove(key);
149f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    }
150f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    key = String8("A2dpSuspended");
151f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    if (param.get(key, value) == NO_ERROR) {
152f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin        mSuspended = (value == "true");
153f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin        if (mOutput) {
154f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin            mOutput->setSuspended(mSuspended);
155f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin        }
156f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin        param.remove(key);
157f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    }
158f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin
159f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    if (param.size()) {
160f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin        status_t hwStatus = mHardwareInterface->setParameters(param.toString());
161f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin        if (status == NO_ERROR) {
162f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin            status = hwStatus;
163f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin        }
164f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    }
165f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin
166f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    return status;
167f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin}
168f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin
169f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima ZavinString8 A2dpAudioInterface::getParameters(const String8& keys)
170f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin{
171f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    AudioParameter param = AudioParameter(keys);
172f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    AudioParameter a2dpParam = AudioParameter();
173f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    String8 value;
174f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    String8 key;
175f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin
176f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    key = "bluetooth_enabled";
177f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    if (param.get(key, value) == NO_ERROR) {
178f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin        value = mBluetoothEnabled ? "true" : "false";
179f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin        a2dpParam.add(key, value);
180f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin        param.remove(key);
181f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    }
182f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    key = "A2dpSuspended";
183f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    if (param.get(key, value) == NO_ERROR) {
184f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin        value = mSuspended ? "true" : "false";
185f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin        a2dpParam.add(key, value);
186f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin        param.remove(key);
187f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    }
188f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin
189f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    String8 keyValuePairs  = a2dpParam.toString();
190f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin
191f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    if (param.size()) {
192f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin        if (keyValuePairs != "") {
193f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin            keyValuePairs += ";";
194f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin        }
195f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin        keyValuePairs += mHardwareInterface->getParameters(param.toString());
196f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    }
197f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin
1986a70518b93928d1c91457ff805e375c82d76b0e5Steve Block    ALOGV("getParameters() %s", keyValuePairs.string());
199f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    return keyValuePairs;
200f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin}
201f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin
202f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavinsize_t A2dpAudioInterface::getInputBufferSize(uint32_t sampleRate, int format, int channelCount)
203f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin{
204f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    return mHardwareInterface->getInputBufferSize(sampleRate, format, channelCount);
205f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin}
206f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin
207f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavinstatus_t A2dpAudioInterface::setVoiceVolume(float v)
208f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin{
209f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    return mHardwareInterface->setVoiceVolume(v);
210f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin}
211f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin
212f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavinstatus_t A2dpAudioInterface::setMasterVolume(float v)
213f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin{
214f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    return mHardwareInterface->setMasterVolume(v);
215f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin}
216f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin
217f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavinstatus_t A2dpAudioInterface::dump(int fd, const Vector<String16>& args)
218f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin{
219f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    return mHardwareInterface->dumpState(fd, args);
220f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin}
221f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin
222f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin// ----------------------------------------------------------------------------
223f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin
224f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima ZavinA2dpAudioInterface::A2dpAudioStreamOut::A2dpAudioStreamOut() :
225f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    mFd(-1), mStandby(true), mStartCount(0), mRetryCount(0), mData(NULL),
226f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    // assume BT enabled to start, this is safe because its only the
227f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    // enabled->disabled transition we are worried about
228f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    mBluetoothEnabled(true), mDevice(0), mClosing(false), mSuspended(false)
229f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin{
230f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    // use any address by default
231f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    strcpy(mA2dpAddress, "00:00:00:00:00:00");
232f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    init();
233f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin}
234f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin
235f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavinstatus_t A2dpAudioInterface::A2dpAudioStreamOut::set(
236f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin        uint32_t device, int *pFormat, uint32_t *pChannels, uint32_t *pRate)
237f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin{
238f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    int lFormat = pFormat ? *pFormat : 0;
239f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    uint32_t lChannels = pChannels ? *pChannels : 0;
240f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    uint32_t lRate = pRate ? *pRate : 0;
241f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin
242b381b932acfa441da5607f37ac4ef6573ed5be96Steve Block    ALOGD("A2dpAudioStreamOut::set %x, %d, %d, %d\n", device, lFormat, lChannels, lRate);
243f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin
244f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    // fix up defaults
245f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    if (lFormat == 0) lFormat = format();
246f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    if (lChannels == 0) lChannels = channels();
247f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    if (lRate == 0) lRate = sampleRate();
248f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin
249f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    // check values
250f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    if ((lFormat != format()) ||
251f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin            (lChannels != channels()) ||
252f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin            (lRate != sampleRate())){
253f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin        if (pFormat) *pFormat = format();
254f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin        if (pChannels) *pChannels = channels();
255f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin        if (pRate) *pRate = sampleRate();
256f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin        return BAD_VALUE;
257f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    }
258f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin
259f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    if (pFormat) *pFormat = lFormat;
260f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    if (pChannels) *pChannels = lChannels;
261f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    if (pRate) *pRate = lRate;
262f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin
263f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    mDevice = device;
264f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    mBufferDurationUs = ((bufferSize() * 1000 )/ frameSize() / sampleRate()) * 1000;
265f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    return NO_ERROR;
266f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin}
267f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin
268f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima ZavinA2dpAudioInterface::A2dpAudioStreamOut::~A2dpAudioStreamOut()
269f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin{
2706a70518b93928d1c91457ff805e375c82d76b0e5Steve Block    ALOGV("A2dpAudioStreamOut destructor");
271f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    close();
2726a70518b93928d1c91457ff805e375c82d76b0e5Steve Block    ALOGV("A2dpAudioStreamOut destructor returning from close()");
273f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin}
274f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin
275f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavinssize_t A2dpAudioInterface::A2dpAudioStreamOut::write(const void* buffer, size_t bytes)
276f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin{
277f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    status_t status = -1;
278f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    {
279f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin        Mutex::Autolock lock(mLock);
280f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin
281f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin        size_t remaining = bytes;
282f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin
283f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin        if (!mBluetoothEnabled || mClosing || mSuspended) {
2846a70518b93928d1c91457ff805e375c82d76b0e5Steve Block            ALOGV("A2dpAudioStreamOut::write(), but bluetooth disabled \
285f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin                   mBluetoothEnabled %d, mClosing %d, mSuspended %d",
286f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin                    mBluetoothEnabled, mClosing, mSuspended);
287f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin            goto Error;
288f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin        }
289f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin
290f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin        if (mStandby) {
291f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin            acquire_wake_lock (PARTIAL_WAKE_LOCK, sA2dpWakeLock);
292f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin            mStandby = false;
293f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin            mLastWriteTime = systemTime();
294f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin        }
295f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin
296f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin        status = init();
297f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin        if (status < 0)
298f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin            goto Error;
299f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin
300f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin        int retries = MAX_WRITE_RETRIES;
301f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin        while (remaining > 0 && retries) {
302f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin            status = a2dp_write(mData, buffer, remaining);
303f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin            if (status < 0) {
3045efbd421e0029d6fc44b1cc65c0e5e0d85e5161fSteve Block                ALOGE("a2dp_write failed err: %d\n", status);
305f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin                goto Error;
306f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin            }
307f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin            if (status == 0) {
308f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin                retries--;
309f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin            }
310f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin            remaining -= status;
311f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin            buffer = (char *)buffer + status;
312f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin        }
313f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin
314f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin        // if A2DP sink runs abnormally fast, sleep a little so that audioflinger mixer thread
315f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin        // does no spin and starve other threads.
316f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin        // NOTE: It is likely that the A2DP headset is being disconnected
317f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin        nsecs_t now = systemTime();
318f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin        if ((uint32_t)ns2us(now - mLastWriteTime) < (mBufferDurationUs >> 2)) {
3196a70518b93928d1c91457ff805e375c82d76b0e5Steve Block            ALOGV("A2DP sink runs too fast");
320f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin            usleep(mBufferDurationUs - (uint32_t)ns2us(now - mLastWriteTime));
321f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin        }
322f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin        mLastWriteTime = now;
323f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin        return bytes;
324f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin
325f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    }
326f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima ZavinError:
327f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin
328f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    standby();
329f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin
330f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    // Simulate audio output timing in case of error
331f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    usleep(mBufferDurationUs);
332f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin
333f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    return status;
334f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin}
335f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin
336f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavinstatus_t A2dpAudioInterface::A2dpAudioStreamOut::init()
337f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin{
338f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    if (!mData) {
339f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin        status_t status = a2dp_init(44100, 2, &mData);
340f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin        if (status < 0) {
3415efbd421e0029d6fc44b1cc65c0e5e0d85e5161fSteve Block            ALOGE("a2dp_init failed err: %d\n", status);
342f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin            mData = NULL;
343f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin            return status;
344f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin        }
345f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin        a2dp_set_sink(mData, mA2dpAddress);
346f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    }
347f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin
348f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    return 0;
349f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin}
350f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin
351f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavinstatus_t A2dpAudioInterface::A2dpAudioStreamOut::standby()
352f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin{
353f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    Mutex::Autolock lock(mLock);
354f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    return standby_l();
355f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin}
356f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin
357f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavinstatus_t A2dpAudioInterface::A2dpAudioStreamOut::standby_l()
358f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin{
359f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    int result = NO_ERROR;
360f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin
361f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    if (!mStandby) {
3626a70518b93928d1c91457ff805e375c82d76b0e5Steve Block        ALOGV_IF(mClosing || !mBluetoothEnabled, "Standby skip stop: closing %d enabled %d",
363f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin                mClosing, mBluetoothEnabled);
364f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin        if (!mClosing && mBluetoothEnabled) {
365f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin            result = a2dp_stop(mData);
366f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin        }
367f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin        release_wake_lock(sA2dpWakeLock);
368f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin        mStandby = true;
369f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    }
370f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin
371f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    return result;
372f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin}
373f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin
374f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavinstatus_t A2dpAudioInterface::A2dpAudioStreamOut::setParameters(const String8& keyValuePairs)
375f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin{
376f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    AudioParameter param = AudioParameter(keyValuePairs);
377f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    String8 value;
378f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    String8 key = String8("a2dp_sink_address");
379f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    status_t status = NO_ERROR;
380f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    int device;
3816a70518b93928d1c91457ff805e375c82d76b0e5Steve Block    ALOGV("A2dpAudioStreamOut::setParameters() %s", keyValuePairs.string());
382f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin
383f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    if (param.get(key, value) == NO_ERROR) {
384f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin        if (value.length() != strlen("00:00:00:00:00:00")) {
385f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin            status = BAD_VALUE;
386f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin        } else {
387f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin            setAddress(value.string());
388f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin        }
389f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin        param.remove(key);
390f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    }
391f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    key = String8("closing");
392f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    if (param.get(key, value) == NO_ERROR) {
393f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin        mClosing = (value == "true");
394f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin        if (mClosing) {
395f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin            standby();
396f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin        }
397f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin        param.remove(key);
398f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    }
399f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    key = AudioParameter::keyRouting;
400f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    if (param.getInt(key, device) == NO_ERROR) {
40133bf1b0fe363bd4892349d160f54d860567fab12Mike Lockwood        if (audio_is_a2dp_out_device(device)) {
402f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin            mDevice = device;
403f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin            status = NO_ERROR;
404f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin        } else {
405f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin            status = BAD_VALUE;
406f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin        }
407f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin        param.remove(key);
408f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    }
409f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin
410f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    if (param.size()) {
411f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin        status = BAD_VALUE;
412f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    }
413f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    return status;
414f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin}
415f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin
416f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima ZavinString8 A2dpAudioInterface::A2dpAudioStreamOut::getParameters(const String8& keys)
417f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin{
418f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    AudioParameter param = AudioParameter(keys);
419f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    String8 value;
420f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    String8 key = String8("a2dp_sink_address");
421f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin
422f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    if (param.get(key, value) == NO_ERROR) {
423f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin        value = mA2dpAddress;
424f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin        param.add(key, value);
425f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    }
426f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    key = AudioParameter::keyRouting;
427f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    if (param.get(key, value) == NO_ERROR) {
428f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin        param.addInt(key, (int)mDevice);
429f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    }
430f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin
4316a70518b93928d1c91457ff805e375c82d76b0e5Steve Block    ALOGV("A2dpAudioStreamOut::getParameters() %s", param.toString().string());
432f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    return param.toString();
433f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin}
434f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin
435f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavinstatus_t A2dpAudioInterface::A2dpAudioStreamOut::setAddress(const char* address)
436f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin{
437f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    Mutex::Autolock lock(mLock);
438f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin
439f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    if (strlen(address) != strlen("00:00:00:00:00:00"))
440f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin        return -EINVAL;
441f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin
442f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    strcpy(mA2dpAddress, address);
443f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    if (mData)
444f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin        a2dp_set_sink(mData, mA2dpAddress);
445f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin
446f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    return NO_ERROR;
447f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin}
448f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin
449f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavinstatus_t A2dpAudioInterface::A2dpAudioStreamOut::setBluetoothEnabled(bool enabled)
450f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin{
451b381b932acfa441da5607f37ac4ef6573ed5be96Steve Block    ALOGD("setBluetoothEnabled %d", enabled);
452f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin
453f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    Mutex::Autolock lock(mLock);
454f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin
455f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    mBluetoothEnabled = enabled;
456f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    if (!enabled) {
457f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin        return close_l();
458f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    }
459f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    return NO_ERROR;
460f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin}
461f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin
462f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavinstatus_t A2dpAudioInterface::A2dpAudioStreamOut::setSuspended(bool onOff)
463f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin{
4646a70518b93928d1c91457ff805e375c82d76b0e5Steve Block    ALOGV("setSuspended %d", onOff);
465f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    mSuspended = onOff;
466f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    standby();
467f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    return NO_ERROR;
468f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin}
469f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin
470f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavinstatus_t A2dpAudioInterface::A2dpAudioStreamOut::close()
471f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin{
472f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    Mutex::Autolock lock(mLock);
4736a70518b93928d1c91457ff805e375c82d76b0e5Steve Block    ALOGV("A2dpAudioStreamOut::close() calling close_l()");
474f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    return close_l();
475f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin}
476f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin
477f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavinstatus_t A2dpAudioInterface::A2dpAudioStreamOut::close_l()
478f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin{
479f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    standby_l();
480f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    if (mData) {
4816a70518b93928d1c91457ff805e375c82d76b0e5Steve Block        ALOGV("A2dpAudioStreamOut::close_l() calling a2dp_cleanup(mData)");
482f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin        a2dp_cleanup(mData);
483f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin        mData = NULL;
484f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    }
485f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    return NO_ERROR;
486f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin}
487f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin
488f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavinstatus_t A2dpAudioInterface::A2dpAudioStreamOut::dump(int fd, const Vector<String16>& args)
489f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin{
490f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    return NO_ERROR;
491f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin}
492f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin
493f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavinstatus_t A2dpAudioInterface::A2dpAudioStreamOut::getRenderPosition(uint32_t *driverFrames)
494f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin{
495f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    //TODO: enable when supported by driver
496f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin    return INVALID_OPERATION;
497f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin}
498f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin
499f01215993dda68b6b52111d754bd0c7c2d5bcfa3Dima Zavin}; // namespace android
500