auto import from //depot/cupcake/@135843
diff --git a/libs/audioflinger/A2dpAudioInterface.cpp b/libs/audioflinger/A2dpAudioInterface.cpp
new file mode 100644
index 0000000..eb00f8c
--- /dev/null
+++ b/libs/audioflinger/A2dpAudioInterface.cpp
@@ -0,0 +1,242 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <math.h>
+
+#define LOG_NDEBUG 0
+#define LOG_TAG "A2dpAudioInterface"
+#include <utils/Log.h>
+#include <utils/String8.h>
+
+#include "A2dpAudioInterface.h"
+#include "audio/liba2dp.h"
+
+
+namespace android {
+
+// ----------------------------------------------------------------------------
+
+A2dpAudioInterface::A2dpAudioInterface() :
+    mOutput(0)
+{
+}
+
+A2dpAudioInterface::~A2dpAudioInterface()
+{
+    delete mOutput;
+}
+
+status_t A2dpAudioInterface::initCheck()
+{
+    return 0;
+}
+
+AudioStreamOut* A2dpAudioInterface::openOutputStream(
+        int format, int channelCount, uint32_t sampleRate, status_t *status)
+{
+    LOGD("A2dpAudioInterface::openOutputStream %d, %d, %d\n", format, channelCount, sampleRate);
+    Mutex::Autolock lock(mLock);
+    status_t err = 0;
+
+    // only one output stream allowed
+    if (mOutput) {
+        if (status)
+            *status = -1;
+        return NULL;
+    }
+
+    // create new output stream
+    A2dpAudioStreamOut* out = new A2dpAudioStreamOut();
+    if ((err = out->set(format, channelCount, sampleRate)) == NO_ERROR) {
+        mOutput = out;
+    } else {
+        delete out;
+    }
+    
+    if (status)
+        *status = err;
+    return mOutput;
+}
+
+AudioStreamIn* A2dpAudioInterface::openInputStream(
+        int format, int channelCount, uint32_t sampleRate, status_t *status,
+        AudioSystem::audio_in_acoustics acoustics)
+{
+    if (status)
+        *status = -1;
+    return NULL;
+}
+
+status_t A2dpAudioInterface::setMicMute(bool state)
+{
+    return 0;
+}
+
+status_t A2dpAudioInterface::getMicMute(bool* state)
+{
+    return 0;
+}
+
+status_t A2dpAudioInterface::setParameter(const char *key, const char *value)
+{
+    LOGD("setParameter %s,%s\n", key, value);
+    
+    if (!key || !value)
+        return -EINVAL;
+    
+    if (strcmp(key, "a2dp_sink_address") == 0) {        
+        return mOutput->setAddress(value);
+    }
+    if (strcmp(key, "bluetooth_enabled") == 0 &&
+        strcmp(value, "false") == 0) {
+        return mOutput->close();
+    }
+
+    return 0;
+}
+
+status_t A2dpAudioInterface::setVoiceVolume(float v)
+{
+    return 0;
+}
+
+status_t A2dpAudioInterface::setMasterVolume(float v)
+{
+    return 0;
+}
+
+status_t A2dpAudioInterface::doRouting()
+{
+    return 0;
+}
+
+status_t A2dpAudioInterface::dump(int fd, const Vector<String16>& args)
+{
+    return 0;
+}
+
+// ----------------------------------------------------------------------------
+
+A2dpAudioInterface::A2dpAudioStreamOut::A2dpAudioStreamOut() :
+    mFd(-1), mStandby(true), mStartCount(0), mRetryCount(0), mData(NULL)
+{
+    // use any address by default
+    strncpy(mA2dpAddress, "00:00:00:00:00:00", sizeof(mA2dpAddress));
+}
+
+status_t A2dpAudioInterface::A2dpAudioStreamOut::set(
+        int format, int channels, uint32_t rate)
+{
+    LOGD("A2dpAudioStreamOut::set %d, %d, %d\n", format, channels, rate);
+
+    // fix up defaults
+    if (format == 0) format = AudioSystem::PCM_16_BIT;
+    if (channels == 0) channels = channelCount();
+    if (rate == 0) rate = sampleRate();
+
+    // check values
+    if ((format != AudioSystem::PCM_16_BIT) ||
+            (channels != channelCount()) ||
+            (rate != sampleRate()))
+        return BAD_VALUE;
+
+    return NO_ERROR;
+}
+
+A2dpAudioInterface::A2dpAudioStreamOut::~A2dpAudioStreamOut()
+{
+    close();
+}
+
+ssize_t A2dpAudioInterface::A2dpAudioStreamOut::write(const void* buffer, size_t bytes)
+{    
+    status_t status = NO_INIT;
+    size_t remaining = bytes;
+
+    if (!mData) {
+        status = a2dp_init(44100, 2, &mData);
+        if (status < 0) {
+            LOGE("a2dp_init failed err: %d\n", status);
+            mData = NULL;
+            goto Error;
+        }
+        a2dp_set_sink(mData, mA2dpAddress);
+    }
+    
+    while (remaining > 0) {
+        status = a2dp_write(mData, buffer, remaining);
+        if (status <= 0) {
+            LOGE("a2dp_write failed err: %d\n", status);
+            goto Error;
+        }
+        remaining -= status;
+        buffer = ((char *)buffer) + status;
+    }
+
+    mStandby = false;
+    
+    return bytes;
+
+Error:
+    // Simulate audio output timing in case of error
+    usleep(bytes * 1000000 / frameSize() / sampleRate());
+
+    return status;
+}
+
+status_t A2dpAudioInterface::A2dpAudioStreamOut::standby()
+{
+    int result = 0;
+
+    if (!mStandby) {
+        result = a2dp_stop(mData);
+        if (result == 0)
+            mStandby = true;
+    }
+
+    return result;
+}
+
+status_t A2dpAudioInterface::A2dpAudioStreamOut::setAddress(const char* address)
+{
+    if (strlen(address) < sizeof(mA2dpAddress))
+        return -EINVAL;
+
+    if (strcmp(address, mA2dpAddress)) {
+        strcpy(mA2dpAddress, address);
+        if (mData)
+            a2dp_set_sink(mData, mA2dpAddress);
+    }
+    
+    return NO_ERROR;
+}
+
+status_t A2dpAudioInterface::A2dpAudioStreamOut::close()
+{
+    if (mData) {
+        a2dp_cleanup(mData);
+        mData = NULL;
+    }
+    return NO_ERROR;
+}
+
+status_t A2dpAudioInterface::A2dpAudioStreamOut::dump(int fd, const Vector<String16>& args)
+{
+    return NO_ERROR;
+}
+
+
+}; // namespace android