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