diff --git a/services/audioflinger/A2dpAudioInterface.cpp b/services/audioflinger/A2dpAudioInterface.cpp
new file mode 100644
index 0000000..995e31c
--- /dev/null
+++ b/services/audioflinger/A2dpAudioInterface.cpp
@@ -0,0 +1,466 @@
+/*
+ * 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 {
+
+// ----------------------------------------------------------------------------
+
+//AudioHardwareInterface* A2dpAudioInterface::createA2dpInterface()
+//{
+//    AudioHardwareInterface* hw = 0;
+//
+//    hw = AudioHardwareInterface::create();
+//    LOGD("new A2dpAudioInterface(hw: %p)", hw);
+//    hw = new A2dpAudioInterface(hw);
+//    return hw;
+//}
+
+A2dpAudioInterface::A2dpAudioInterface(AudioHardwareInterface* hw) :
+    mOutput(0), mHardwareInterface(hw), mBluetoothEnabled(true), mSuspended(false)
+{
+}
+
+A2dpAudioInterface::~A2dpAudioInterface()
+{
+    closeOutputStream((AudioStreamOut *)mOutput);
+    delete mHardwareInterface;
+}
+
+status_t A2dpAudioInterface::initCheck()
+{
+    if (mHardwareInterface == 0) return NO_INIT;
+    return mHardwareInterface->initCheck();
+}
+
+AudioStreamOut* A2dpAudioInterface::openOutputStream(
+        uint32_t devices, int *format, uint32_t *channels, uint32_t *sampleRate, status_t *status)
+{
+    if (!AudioSystem::isA2dpDevice((AudioSystem::audio_devices)devices)) {
+        LOGV("A2dpAudioInterface::openOutputStream() open HW device: %x", devices);
+        return mHardwareInterface->openOutputStream(devices, format, channels, sampleRate, status);
+    }
+
+    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(devices, format, channels, sampleRate)) == NO_ERROR) {
+        mOutput = out;
+        mOutput->setBluetoothEnabled(mBluetoothEnabled);
+        mOutput->setSuspended(mSuspended);
+    } else {
+        delete out;
+    }
+
+    if (status)
+        *status = err;
+    return mOutput;
+}
+
+void A2dpAudioInterface::closeOutputStream(AudioStreamOut* out) {
+    if (mOutput == 0 || mOutput != out) {
+        mHardwareInterface->closeOutputStream(out);
+    }
+    else {
+        delete mOutput;
+        mOutput = 0;
+    }
+}
+
+
+AudioStreamIn* A2dpAudioInterface::openInputStream(
+        uint32_t devices, int *format, uint32_t *channels, uint32_t *sampleRate, status_t *status,
+        AudioSystem::audio_in_acoustics acoustics)
+{
+    return mHardwareInterface->openInputStream(devices, format, channels, sampleRate, status, acoustics);
+}
+
+void A2dpAudioInterface::closeInputStream(AudioStreamIn* in)
+{
+    return mHardwareInterface->closeInputStream(in);
+}
+
+status_t A2dpAudioInterface::setMode(int mode)
+{
+    return mHardwareInterface->setMode(mode);
+}
+
+status_t A2dpAudioInterface::setMicMute(bool state)
+{
+    return mHardwareInterface->setMicMute(state);
+}
+
+status_t A2dpAudioInterface::getMicMute(bool* state)
+{
+    return mHardwareInterface->getMicMute(state);
+}
+
+status_t A2dpAudioInterface::setParameters(const String8& keyValuePairs)
+{
+    AudioParameter param = AudioParameter(keyValuePairs);
+    String8 value;
+    String8 key;
+    status_t status = NO_ERROR;
+
+    LOGV("setParameters() %s", keyValuePairs.string());
+
+    key = "bluetooth_enabled";
+    if (param.get(key, value) == NO_ERROR) {
+        mBluetoothEnabled = (value == "true");
+        if (mOutput) {
+            mOutput->setBluetoothEnabled(mBluetoothEnabled);
+        }
+        param.remove(key);
+    }
+    key = String8("A2dpSuspended");
+    if (param.get(key, value) == NO_ERROR) {
+        mSuspended = (value == "true");
+        if (mOutput) {
+            mOutput->setSuspended(mSuspended);
+        }
+        param.remove(key);
+    }
+
+    if (param.size()) {
+        status_t hwStatus = mHardwareInterface->setParameters(param.toString());
+        if (status == NO_ERROR) {
+            status = hwStatus;
+        }
+    }
+
+    return status;
+}
+
+String8 A2dpAudioInterface::getParameters(const String8& keys)
+{
+    AudioParameter param = AudioParameter(keys);
+    AudioParameter a2dpParam = AudioParameter();
+    String8 value;
+    String8 key;
+
+    key = "bluetooth_enabled";
+    if (param.get(key, value) == NO_ERROR) {
+        value = mBluetoothEnabled ? "true" : "false";
+        a2dpParam.add(key, value);
+        param.remove(key);
+    }
+    key = "A2dpSuspended";
+    if (param.get(key, value) == NO_ERROR) {
+        value = mSuspended ? "true" : "false";
+        a2dpParam.add(key, value);
+        param.remove(key);
+    }
+
+    String8 keyValuePairs  = a2dpParam.toString();
+
+    if (param.size()) {
+        if (keyValuePairs != "") {
+            keyValuePairs += ";";
+        }
+        keyValuePairs += mHardwareInterface->getParameters(param.toString());
+    }
+
+    LOGV("getParameters() %s", keyValuePairs.string());
+    return keyValuePairs;
+}
+
+size_t A2dpAudioInterface::getInputBufferSize(uint32_t sampleRate, int format, int channelCount)
+{
+    return mHardwareInterface->getInputBufferSize(sampleRate, format, channelCount);
+}
+
+status_t A2dpAudioInterface::setVoiceVolume(float v)
+{
+    return mHardwareInterface->setVoiceVolume(v);
+}
+
+status_t A2dpAudioInterface::setMasterVolume(float v)
+{
+    return mHardwareInterface->setMasterVolume(v);
+}
+
+status_t A2dpAudioInterface::dump(int fd, const Vector<String16>& args)
+{
+    return mHardwareInterface->dumpState(fd, args);
+}
+
+// ----------------------------------------------------------------------------
+
+A2dpAudioInterface::A2dpAudioStreamOut::A2dpAudioStreamOut() :
+    mFd(-1), mStandby(true), mStartCount(0), mRetryCount(0), mData(NULL),
+    // assume BT enabled to start, this is safe because its only the
+    // enabled->disabled transition we are worried about
+    mBluetoothEnabled(true), mDevice(0), mClosing(false), mSuspended(false)
+{
+    // use any address by default
+    strcpy(mA2dpAddress, "00:00:00:00:00:00");
+    init();
+}
+
+status_t A2dpAudioInterface::A2dpAudioStreamOut::set(
+        uint32_t device, int *pFormat, uint32_t *pChannels, uint32_t *pRate)
+{
+    int lFormat = pFormat ? *pFormat : 0;
+    uint32_t lChannels = pChannels ? *pChannels : 0;
+    uint32_t lRate = pRate ? *pRate : 0;
+
+    LOGD("A2dpAudioStreamOut::set %x, %d, %d, %d\n", device, lFormat, lChannels, lRate);
+
+    // fix up defaults
+    if (lFormat == 0) lFormat = format();
+    if (lChannels == 0) lChannels = channels();
+    if (lRate == 0) lRate = sampleRate();
+
+    // check values
+    if ((lFormat != format()) ||
+            (lChannels != channels()) ||
+            (lRate != sampleRate())){
+        if (pFormat) *pFormat = format();
+        if (pChannels) *pChannels = channels();
+        if (pRate) *pRate = sampleRate();
+        return BAD_VALUE;
+    }
+
+    if (pFormat) *pFormat = lFormat;
+    if (pChannels) *pChannels = lChannels;
+    if (pRate) *pRate = lRate;
+
+    mDevice = device;
+    return NO_ERROR;
+}
+
+A2dpAudioInterface::A2dpAudioStreamOut::~A2dpAudioStreamOut()
+{
+    LOGV("A2dpAudioStreamOut destructor");
+    standby();
+    close();
+    LOGV("A2dpAudioStreamOut destructor returning from close()");
+}
+
+ssize_t A2dpAudioInterface::A2dpAudioStreamOut::write(const void* buffer, size_t bytes)
+{
+    Mutex::Autolock lock(mLock);
+
+    size_t remaining = bytes;
+    status_t status = -1;
+
+    if (!mBluetoothEnabled || mClosing || mSuspended) {
+        LOGV("A2dpAudioStreamOut::write(), but bluetooth disabled \
+               mBluetoothEnabled %d, mClosing %d, mSuspended %d",
+                mBluetoothEnabled, mClosing, mSuspended);
+        goto Error;
+    }
+
+    status = init();
+    if (status < 0)
+        goto Error;
+
+    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 * 1000 )/ frameSize() / sampleRate()) * 1000);
+
+    return status;
+}
+
+status_t A2dpAudioInterface::A2dpAudioStreamOut::init()
+{
+    if (!mData) {
+        status_t status = a2dp_init(44100, 2, &mData);
+        if (status < 0) {
+            LOGE("a2dp_init failed err: %d\n", status);
+            mData = NULL;
+            return status;
+        }
+        a2dp_set_sink(mData, mA2dpAddress);
+    }
+
+    return 0;
+}
+
+status_t A2dpAudioInterface::A2dpAudioStreamOut::standby()
+{
+    int result = 0;
+
+    if (mClosing) {
+        LOGV("Ignore standby, closing");
+        return result;
+    }
+
+    Mutex::Autolock lock(mLock);
+
+    if (!mStandby) {
+        result = a2dp_stop(mData);
+        if (result == 0)
+            mStandby = true;
+    }
+
+    return result;
+}
+
+status_t A2dpAudioInterface::A2dpAudioStreamOut::setParameters(const String8& keyValuePairs)
+{
+    AudioParameter param = AudioParameter(keyValuePairs);
+    String8 value;
+    String8 key = String8("a2dp_sink_address");
+    status_t status = NO_ERROR;
+    int device;
+    LOGV("A2dpAudioStreamOut::setParameters() %s", keyValuePairs.string());
+
+    if (param.get(key, value) == NO_ERROR) {
+        if (value.length() != strlen("00:00:00:00:00:00")) {
+            status = BAD_VALUE;
+        } else {
+            setAddress(value.string());
+        }
+        param.remove(key);
+    }
+    key = String8("closing");
+    if (param.get(key, value) == NO_ERROR) {
+        mClosing = (value == "true");
+        param.remove(key);
+    }
+    key = AudioParameter::keyRouting;
+    if (param.getInt(key, device) == NO_ERROR) {
+        if (AudioSystem::isA2dpDevice((AudioSystem::audio_devices)device)) {
+            mDevice = device;
+            status = NO_ERROR;
+        } else {
+            status = BAD_VALUE;
+        }
+        param.remove(key);
+    }
+
+    if (param.size()) {
+        status = BAD_VALUE;
+    }
+    return status;
+}
+
+String8 A2dpAudioInterface::A2dpAudioStreamOut::getParameters(const String8& keys)
+{
+    AudioParameter param = AudioParameter(keys);
+    String8 value;
+    String8 key = String8("a2dp_sink_address");
+
+    if (param.get(key, value) == NO_ERROR) {
+        value = mA2dpAddress;
+        param.add(key, value);
+    }
+    key = AudioParameter::keyRouting;
+    if (param.get(key, value) == NO_ERROR) {
+        param.addInt(key, (int)mDevice);
+    }
+
+    LOGV("A2dpAudioStreamOut::getParameters() %s", param.toString().string());
+    return param.toString();
+}
+
+status_t A2dpAudioInterface::A2dpAudioStreamOut::setAddress(const char* address)
+{
+    Mutex::Autolock lock(mLock);
+
+    if (strlen(address) != strlen("00:00:00:00:00:00"))
+        return -EINVAL;
+
+    strcpy(mA2dpAddress, address);
+    if (mData)
+        a2dp_set_sink(mData, mA2dpAddress);
+
+    return NO_ERROR;
+}
+
+status_t A2dpAudioInterface::A2dpAudioStreamOut::setBluetoothEnabled(bool enabled)
+{
+    LOGD("setBluetoothEnabled %d", enabled);
+
+    Mutex::Autolock lock(mLock);
+
+    mBluetoothEnabled = enabled;
+    if (!enabled) {
+        return close_l();
+    }
+    return NO_ERROR;
+}
+
+status_t A2dpAudioInterface::A2dpAudioStreamOut::setSuspended(bool onOff)
+{
+    LOGV("setSuspended %d", onOff);
+    mSuspended = onOff;
+    standby();
+    return NO_ERROR;
+}
+
+status_t A2dpAudioInterface::A2dpAudioStreamOut::close()
+{
+    Mutex::Autolock lock(mLock);
+    LOGV("A2dpAudioStreamOut::close() calling close_l()");
+    return close_l();
+}
+
+status_t A2dpAudioInterface::A2dpAudioStreamOut::close_l()
+{
+    if (mData) {
+        LOGV("A2dpAudioStreamOut::close_l() calling a2dp_cleanup(mData)");
+        a2dp_cleanup(mData);
+        mData = NULL;
+    }
+    return NO_ERROR;
+}
+
+status_t A2dpAudioInterface::A2dpAudioStreamOut::dump(int fd, const Vector<String16>& args)
+{
+    return NO_ERROR;
+}
+
+status_t A2dpAudioInterface::A2dpAudioStreamOut::getRenderPosition(uint32_t *driverFrames)
+{
+    //TODO: enable when supported by driver
+    return INVALID_OPERATION;
+}
+
+}; // namespace android
