2 * Copyright (C) 2008 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 //#define LOG_NDEBUG 0
20 #define LOG_TAG "A2dpAudioInterface"
21 #include <utils/Log.h>
22 #include <utils/String8.h>
24 #include "A2dpAudioInterface.h"
25 #include "audio/liba2dp.h"
26 #include <hardware_legacy/power.h>
30 static const char *sA2dpWakeLock = "A2dpOutputStream";
31 #define MAX_WRITE_RETRIES 5
33 // ----------------------------------------------------------------------------
35 //AudioHardwareInterface* A2dpAudioInterface::createA2dpInterface()
37 // AudioHardwareInterface* hw = 0;
39 // hw = AudioHardwareInterface::create();
40 // LOGD("new A2dpAudioInterface(hw: %p)", hw);
41 // hw = new A2dpAudioInterface(hw);
45 A2dpAudioInterface::A2dpAudioInterface(AudioHardwareInterface* hw) :
46 mOutput(0), mHardwareInterface(hw), mBluetoothEnabled(true), mSuspended(false)
50 A2dpAudioInterface::~A2dpAudioInterface()
52 closeOutputStream((AudioStreamOut *)mOutput);
53 delete mHardwareInterface;
56 status_t A2dpAudioInterface::initCheck()
58 if (mHardwareInterface == 0) return NO_INIT;
59 return mHardwareInterface->initCheck();
62 AudioStreamOut* A2dpAudioInterface::openOutputStream(
63 uint32_t devices, int *format, uint32_t *channels, uint32_t *sampleRate, status_t *status)
65 if (!AudioSystem::isA2dpDevice((AudioSystem::audio_devices)devices)) {
66 LOGV("A2dpAudioInterface::openOutputStream() open HW device: %x", devices);
67 return mHardwareInterface->openOutputStream(devices, format, channels, sampleRate, status);
72 // only one output stream allowed
79 // create new output stream
80 A2dpAudioStreamOut* out = new A2dpAudioStreamOut();
81 if ((err = out->set(devices, format, channels, sampleRate)) == NO_ERROR) {
83 mOutput->setBluetoothEnabled(mBluetoothEnabled);
84 mOutput->setSuspended(mSuspended);
94 void A2dpAudioInterface::closeOutputStream(AudioStreamOut* out) {
95 if (mOutput == 0 || mOutput != out) {
96 mHardwareInterface->closeOutputStream(out);
105 AudioStreamIn* A2dpAudioInterface::openInputStream(
106 uint32_t devices, int *format, uint32_t *channels, uint32_t *sampleRate, status_t *status,
107 AudioSystem::audio_in_acoustics acoustics)
109 return mHardwareInterface->openInputStream(devices, format, channels, sampleRate, status, acoustics);
112 void A2dpAudioInterface::closeInputStream(AudioStreamIn* in)
114 return mHardwareInterface->closeInputStream(in);
117 status_t A2dpAudioInterface::setMode(int mode)
119 return mHardwareInterface->setMode(mode);
122 status_t A2dpAudioInterface::setMicMute(bool state)
124 return mHardwareInterface->setMicMute(state);
127 status_t A2dpAudioInterface::getMicMute(bool* state)
129 return mHardwareInterface->getMicMute(state);
132 status_t A2dpAudioInterface::setParameters(const String8& keyValuePairs)
134 AudioParameter param = AudioParameter(keyValuePairs);
137 status_t status = NO_ERROR;
139 LOGV("setParameters() %s", keyValuePairs.string());
141 key = "bluetooth_enabled";
142 if (param.get(key, value) == NO_ERROR) {
143 mBluetoothEnabled = (value == "true");
145 mOutput->setBluetoothEnabled(mBluetoothEnabled);
149 key = String8("A2dpSuspended");
150 if (param.get(key, value) == NO_ERROR) {
151 mSuspended = (value == "true");
153 mOutput->setSuspended(mSuspended);
159 status_t hwStatus = mHardwareInterface->setParameters(param.toString());
160 if (status == NO_ERROR) {
168 String8 A2dpAudioInterface::getParameters(const String8& keys)
170 AudioParameter param = AudioParameter(keys);
171 AudioParameter a2dpParam = AudioParameter();
175 key = "bluetooth_enabled";
176 if (param.get(key, value) == NO_ERROR) {
177 value = mBluetoothEnabled ? "true" : "false";
178 a2dpParam.add(key, value);
181 key = "A2dpSuspended";
182 if (param.get(key, value) == NO_ERROR) {
183 value = mSuspended ? "true" : "false";
184 a2dpParam.add(key, value);
188 String8 keyValuePairs = a2dpParam.toString();
191 if (keyValuePairs != "") {
192 keyValuePairs += ";";
194 keyValuePairs += mHardwareInterface->getParameters(param.toString());
197 LOGV("getParameters() %s", keyValuePairs.string());
198 return keyValuePairs;
201 size_t A2dpAudioInterface::getInputBufferSize(uint32_t sampleRate, int format, int channelCount)
203 return mHardwareInterface->getInputBufferSize(sampleRate, format, channelCount);
206 status_t A2dpAudioInterface::setVoiceVolume(float v)
208 return mHardwareInterface->setVoiceVolume(v);
211 status_t A2dpAudioInterface::setMasterVolume(float v)
213 return mHardwareInterface->setMasterVolume(v);
216 status_t A2dpAudioInterface::dump(int fd, const Vector<String16>& args)
218 return mHardwareInterface->dumpState(fd, args);
221 // ----------------------------------------------------------------------------
223 A2dpAudioInterface::A2dpAudioStreamOut::A2dpAudioStreamOut() :
224 mFd(-1), mStandby(true), mStartCount(0), mRetryCount(0), mData(NULL),
225 // assume BT enabled to start, this is safe because its only the
226 // enabled->disabled transition we are worried about
227 mBluetoothEnabled(true), mDevice(0), mClosing(false), mSuspended(false)
229 // use any address by default
230 strcpy(mA2dpAddress, "00:00:00:00:00:00");
234 status_t A2dpAudioInterface::A2dpAudioStreamOut::set(
235 uint32_t device, int *pFormat, uint32_t *pChannels, uint32_t *pRate)
237 int lFormat = pFormat ? *pFormat : 0;
238 uint32_t lChannels = pChannels ? *pChannels : 0;
239 uint32_t lRate = pRate ? *pRate : 0;
241 LOGD("A2dpAudioStreamOut::set %x, %d, %d, %d\n", device, lFormat, lChannels, lRate);
244 if (lFormat == 0) lFormat = format();
245 if (lChannels == 0) lChannels = channels();
246 if (lRate == 0) lRate = sampleRate();
249 if ((lFormat != format()) ||
250 (lChannels != channels()) ||
251 (lRate != sampleRate())){
252 if (pFormat) *pFormat = format();
253 if (pChannels) *pChannels = channels();
254 if (pRate) *pRate = sampleRate();
258 if (pFormat) *pFormat = lFormat;
259 if (pChannels) *pChannels = lChannels;
260 if (pRate) *pRate = lRate;
263 mBufferDurationUs = ((bufferSize() * 1000 )/ frameSize() / sampleRate()) * 1000;
267 A2dpAudioInterface::A2dpAudioStreamOut::~A2dpAudioStreamOut()
269 LOGV("A2dpAudioStreamOut destructor");
271 LOGV("A2dpAudioStreamOut destructor returning from close()");
274 ssize_t A2dpAudioInterface::A2dpAudioStreamOut::write(const void* buffer, size_t bytes)
276 status_t status = -1;
278 Mutex::Autolock lock(mLock);
280 size_t remaining = bytes;
282 if (!mBluetoothEnabled || mClosing || mSuspended) {
283 LOGV("A2dpAudioStreamOut::write(), but bluetooth disabled \
284 mBluetoothEnabled %d, mClosing %d, mSuspended %d",
285 mBluetoothEnabled, mClosing, mSuspended);
290 acquire_wake_lock (PARTIAL_WAKE_LOCK, sA2dpWakeLock);
292 mLastWriteTime = systemTime();
299 int retries = MAX_WRITE_RETRIES;
300 while (remaining > 0 && retries) {
301 status = a2dp_write(mData, buffer, remaining);
303 LOGE("a2dp_write failed err: %d\n", status);
310 buffer = (char *)buffer + status;
313 // if A2DP sink runs abnormally fast, sleep a little so that audioflinger mixer thread
314 // does no spin and starve other threads.
315 // NOTE: It is likely that the A2DP headset is being disconnected
316 nsecs_t now = systemTime();
317 if ((uint32_t)ns2us(now - mLastWriteTime) < (mBufferDurationUs >> 2)) {
318 LOGV("A2DP sink runs too fast");
319 usleep(mBufferDurationUs - (uint32_t)ns2us(now - mLastWriteTime));
321 mLastWriteTime = now;
329 // Simulate audio output timing in case of error
330 usleep(mBufferDurationUs);
335 status_t A2dpAudioInterface::A2dpAudioStreamOut::init()
338 status_t status = a2dp_init(44100, 2, &mData);
340 LOGE("a2dp_init failed err: %d\n", status);
344 a2dp_set_sink(mData, mA2dpAddress);
350 status_t A2dpAudioInterface::A2dpAudioStreamOut::standby()
352 Mutex::Autolock lock(mLock);
356 status_t A2dpAudioInterface::A2dpAudioStreamOut::standby_l()
358 int result = NO_ERROR;
361 LOGV_IF(mClosing || !mBluetoothEnabled, "Standby skip stop: closing %d enabled %d",
362 mClosing, mBluetoothEnabled);
363 if (!mClosing && mBluetoothEnabled) {
364 result = a2dp_stop(mData);
366 release_wake_lock(sA2dpWakeLock);
373 status_t A2dpAudioInterface::A2dpAudioStreamOut::setParameters(const String8& keyValuePairs)
375 AudioParameter param = AudioParameter(keyValuePairs);
377 String8 key = String8("a2dp_sink_address");
378 status_t status = NO_ERROR;
380 LOGV("A2dpAudioStreamOut::setParameters() %s", keyValuePairs.string());
382 if (param.get(key, value) == NO_ERROR) {
383 if (value.length() != strlen("00:00:00:00:00:00")) {
386 setAddress(value.string());
390 key = String8("closing");
391 if (param.get(key, value) == NO_ERROR) {
392 mClosing = (value == "true");
398 key = AudioParameter::keyRouting;
399 if (param.getInt(key, device) == NO_ERROR) {
400 if (AudioSystem::isA2dpDevice((AudioSystem::audio_devices)device)) {
415 String8 A2dpAudioInterface::A2dpAudioStreamOut::getParameters(const String8& keys)
417 AudioParameter param = AudioParameter(keys);
419 String8 key = String8("a2dp_sink_address");
421 if (param.get(key, value) == NO_ERROR) {
422 value = mA2dpAddress;
423 param.add(key, value);
425 key = AudioParameter::keyRouting;
426 if (param.get(key, value) == NO_ERROR) {
427 param.addInt(key, (int)mDevice);
430 LOGV("A2dpAudioStreamOut::getParameters() %s", param.toString().string());
431 return param.toString();
434 status_t A2dpAudioInterface::A2dpAudioStreamOut::setAddress(const char* address)
436 Mutex::Autolock lock(mLock);
438 if (strlen(address) != strlen("00:00:00:00:00:00"))
441 strcpy(mA2dpAddress, address);
443 a2dp_set_sink(mData, mA2dpAddress);
448 status_t A2dpAudioInterface::A2dpAudioStreamOut::setBluetoothEnabled(bool enabled)
450 LOGD("setBluetoothEnabled %d", enabled);
452 Mutex::Autolock lock(mLock);
454 mBluetoothEnabled = enabled;
461 status_t A2dpAudioInterface::A2dpAudioStreamOut::setSuspended(bool onOff)
463 LOGV("setSuspended %d", onOff);
469 status_t A2dpAudioInterface::A2dpAudioStreamOut::close()
471 Mutex::Autolock lock(mLock);
472 LOGV("A2dpAudioStreamOut::close() calling close_l()");
476 status_t A2dpAudioInterface::A2dpAudioStreamOut::close_l()
480 LOGV("A2dpAudioStreamOut::close_l() calling a2dp_cleanup(mData)");
487 status_t A2dpAudioInterface::A2dpAudioStreamOut::dump(int fd, const Vector<String16>& args)
492 status_t A2dpAudioInterface::A2dpAudioStreamOut::getRenderPosition(uint32_t *driverFrames)
494 //TODO: enable when supported by driver
495 return INVALID_OPERATION;
498 }; // namespace android