Fix issue 1795088       Improve audio routing code

Initial commit for review.
Integrated comments after patch set 1 review.
Fixed lockup in AudioFlinger::ThreadBase::exit()
Fixed lockup when playing tone with AudioPlocyService startTone()
diff --git a/media/libmedia/Android.mk b/media/libmedia/Android.mk
index 07c81f7..9d442c3 100644
--- a/media/libmedia/Android.mk
+++ b/media/libmedia/Android.mk
@@ -20,7 +20,8 @@
     mediametadataretriever.cpp \
     ToneGenerator.cpp \
     JetPlayer.cpp \
-    IOMX.cpp
+    IOMX.cpp \
+ 	IAudioPolicyService.cpp
 
 LOCAL_SHARED_LIBRARIES := \
 	libui libcutils libutils libbinder libsonivox
diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp
index 0a6f4f7..5e35564 100644
--- a/media/libmedia/AudioRecord.cpp
+++ b/media/libmedia/AudioRecord.cpp
@@ -28,6 +28,7 @@
 
 #include <media/AudioSystem.h>
 #include <media/AudioRecord.h>
+#include <media/mediarecorder.h>
 
 #include <binder/IServiceManager.h>
 #include <utils/Log.h>
@@ -45,7 +46,7 @@
 // ---------------------------------------------------------------------------
 
 AudioRecord::AudioRecord()
-    : mStatus(NO_INIT)
+    : mStatus(NO_INIT), mInput(0)
 {
 }
 
@@ -53,15 +54,15 @@
         int inputSource,
         uint32_t sampleRate,
         int format,
-        int channelCount,
+        uint32_t channels,
         int frameCount,
         uint32_t flags,
         callback_t cbf,
         void* user,
         int notificationFrames)
-    : mStatus(NO_INIT)
+    : mStatus(NO_INIT), mInput(0)
 {
-    mStatus = set(inputSource, sampleRate, format, channelCount,
+    mStatus = set(inputSource, sampleRate, format, channels,
             frameCount, flags, cbf, user, notificationFrames);
 }
 
@@ -78,6 +79,7 @@
         }
         mAudioRecord.clear();
         IPCThreadState::self()->flushCommands();
+        AudioSystem::releaseInput(mInput);
     }
 }
 
@@ -85,7 +87,7 @@
         int inputSource,
         uint32_t sampleRate,
         int format,
-        int channelCount,
+        uint32_t channels,
         int frameCount,
         uint32_t flags,
         callback_t cbf,
@@ -94,7 +96,7 @@
         bool threadCanCallJava)
 {
 
-    LOGV("set(): sampleRate %d, channelCount %d, frameCount %d",sampleRate, channelCount, frameCount);
+    LOGV("set(): sampleRate %d, channels %d, frameCount %d",sampleRate, channels, frameCount);
     if (mAudioRecord != 0) {
         return INVALID_OPERATION;
     }
@@ -104,8 +106,8 @@
         return NO_INIT;
     }
 
-    if (inputSource == DEFAULT_INPUT) {
-        inputSource = MIC_INPUT;
+    if (inputSource == AUDIO_SOURCE_DEFAULT) {
+        inputSource = AUDIO_SOURCE_MIC;
     }
 
     if (sampleRate == 0) {
@@ -115,15 +117,21 @@
     if (format == 0) {
         format = AudioSystem::PCM_16_BIT;
     }
-    if (channelCount == 0) {
-        channelCount = 1;
-    }
-
     // validate parameters
-    if (format != AudioSystem::PCM_16_BIT) {
+    if (!AudioSystem::isValidFormat(format)) {
+        LOGE("Invalid format");
         return BAD_VALUE;
     }
-    if (channelCount != 1 && channelCount != 2) {
+
+    if (!AudioSystem::isInputChannel(channels)) {
+        return BAD_VALUE;
+    }
+    int channelCount = AudioSystem::popCount(channels);
+
+    mInput = AudioSystem::getInput(inputSource,
+                                    sampleRate, format, channels, (AudioSystem::audio_in_acoustics)flags);
+    if (mInput == 0) {
+        LOGE("Could not get audio output for stream type %d", inputSource);
         return BAD_VALUE;
     }
 
@@ -132,14 +140,22 @@
     if (AudioSystem::getInputBufferSize(sampleRate, format, channelCount, &inputBuffSizeInBytes)
             != NO_ERROR) {
         LOGE("AudioSystem could not query the input buffer size.");
-        return NO_INIT;    
+        return NO_INIT;
     }
+
     if (inputBuffSizeInBytes == 0) {
         LOGE("Recording parameters are not supported: sampleRate %d, channelCount %d, format %d",
             sampleRate, channelCount, format);
         return BAD_VALUE;
     }
+
     int frameSizeInBytes = channelCount * (format == AudioSystem::PCM_16_BIT ? 2 : 1);
+    if (AudioSystem::isLinearPCM(format)) {
+        frameSizeInBytes = channelCount * (format == AudioSystem::PCM_16_BIT ? sizeof(int16_t) : sizeof(int8_t));
+    } else {
+        frameSizeInBytes = sizeof(int8_t);
+    }
+
 
     // We use 2* size of input buffer for ping pong use of record buffer.
     int minFrameCount = 2 * inputBuffSizeInBytes / frameSizeInBytes;
@@ -157,11 +173,11 @@
 
     // open record channel
     status_t status;
-    sp<IAudioRecord> record = audioFlinger->openRecord(getpid(), inputSource,
+    sp<IAudioRecord> record = audioFlinger->openRecord(getpid(), mInput,
                                                        sampleRate, format,
                                                        channelCount,
                                                        frameCount,
-                                                       ((uint16_t)flags) << 16, 
+                                                       ((uint16_t)flags) << 16,
                                                        &status);
     if (record == 0) {
         LOGE("AudioFlinger could not create record track, status: %d", status);
@@ -188,7 +204,7 @@
     mFormat = format;
     // Update buffer size in case it has been limited by AudioFlinger during track creation
     mFrameCount = mCblk->frameCount;
-    mChannelCount = channelCount;
+    mChannelCount = (uint8_t)channelCount;
     mActive = 0;
     mCbf = cbf;
     mNotificationFrames = notificationFrames;
@@ -234,7 +250,11 @@
 
 int AudioRecord::frameSize() const
 {
-    return channelCount()*((format() == AudioSystem::PCM_8_BIT) ? sizeof(uint8_t) : sizeof(int16_t));
+    if (AudioSystem::isLinearPCM(mFormat)) {
+        return channelCount()*((format() == AudioSystem::PCM_8_BIT) ? sizeof(uint8_t) : sizeof(int16_t));
+    } else {
+        return sizeof(uint8_t);
+    }
 }
 
 int AudioRecord::inputSource() const
@@ -262,15 +282,18 @@
      }
 
     if (android_atomic_or(1, &mActive) == 0) {
-        mNewPosition = mCblk->user + mUpdatePeriod;
-        mCblk->bufferTimeoutMs = MAX_RUN_TIMEOUT_MS;
-        mCblk->waitTimeMs = 0;
-        if (t != 0) {
-           t->run("ClientRecordThread", THREAD_PRIORITY_AUDIO_CLIENT);
-        } else {
-            setpriority(PRIO_PROCESS, 0, THREAD_PRIORITY_AUDIO_CLIENT);
+        ret = AudioSystem::startInput(mInput);
+        if (ret == NO_ERROR) {
+            mNewPosition = mCblk->user + mUpdatePeriod;
+            mCblk->bufferTimeoutMs = MAX_RUN_TIMEOUT_MS;
+            mCblk->waitTimeMs = 0;
+            if (t != 0) {
+               t->run("ClientRecordThread", THREAD_PRIORITY_AUDIO_CLIENT);
+            } else {
+                setpriority(PRIO_PROCESS, 0, THREAD_PRIORITY_AUDIO_CLIENT);
+            }
+            ret = mAudioRecord->start();
         }
-        ret = mAudioRecord->start();
     }
 
     if (t != 0) {
@@ -301,6 +324,7 @@
         } else {
             setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_NORMAL);
         }
+        AudioSystem::stopInput(mInput);
     }
 
     if (t != 0) {
@@ -421,7 +445,7 @@
         "this shouldn't happen (user=%08x, server=%08x)", cblk->user, cblk->server);
 
     cblk->waitTimeMs = 0;
-    
+
     if (framesReq > framesReady) {
         framesReq = framesReady;
     }
@@ -437,7 +461,7 @@
     audioBuffer->channelCount= mChannelCount;
     audioBuffer->format      = mFormat;
     audioBuffer->frameCount  = framesReq;
-    audioBuffer->size        = framesReq*mChannelCount*sizeof(int16_t);
+    audioBuffer->size        = framesReq*cblk->frameSize;
     audioBuffer->raw         = (int8_t*)cblk->buffer(u);
     active = mActive;
     return active ? status_t(NO_ERROR) : status_t(STOPPED);
@@ -468,7 +492,7 @@
 
     do {
 
-        audioBuffer.frameCount = userSize/mChannelCount/sizeof(int16_t);
+        audioBuffer.frameCount = userSize/frameSize();
 
         // Calling obtainBuffer() with a negative wait count causes
         // an (almost) infinite wait time.
@@ -519,8 +543,8 @@
 
     do {
         audioBuffer.frameCount = frames;
-        // Calling obtainBuffer() with a wait count of 1 
-        // limits wait time to WAIT_PERIOD_MS. This prevents from being 
+        // Calling obtainBuffer() with a wait count of 1
+        // limits wait time to WAIT_PERIOD_MS. This prevents from being
         // stuck here not being able to handle timed events (position, markers).
         status_t err = obtainBuffer(&audioBuffer, 1);
         if (err < NO_ERROR) {
@@ -548,14 +572,14 @@
         if (readSize > reqSize) readSize = reqSize;
 
         audioBuffer.size = readSize;
-        audioBuffer.frameCount = readSize/mChannelCount/sizeof(int16_t);
+        audioBuffer.frameCount = readSize/frameSize();
         frames -= audioBuffer.frameCount;
 
         releaseBuffer(&audioBuffer);
 
     } while (frames);
 
-    
+
     // Manage overrun callback
     if (mActive && (mCblk->framesAvailable_l() == 0)) {
         LOGV("Overrun user: %x, server: %x, flowControlFlag %d", mCblk->user, mCblk->server, mCblk->flowControlFlag);
diff --git a/media/libmedia/AudioSystem.cpp b/media/libmedia/AudioSystem.cpp
index 86d0542..1fc1024 100644
--- a/media/libmedia/AudioSystem.cpp
+++ b/media/libmedia/AudioSystem.cpp
@@ -20,8 +20,18 @@
 #include <utils/Log.h>
 #include <binder/IServiceManager.h>
 #include <media/AudioSystem.h>
+#include <media/IAudioPolicyService.h>
 #include <math.h>
 
+// ----------------------------------------------------------------------------
+// the sim build doesn't have gettid
+
+#ifndef HAVE_GETTID
+# define gettid getpid
+#endif
+
+// ----------------------------------------------------------------------------
+
 namespace android {
 
 // client singleton for AudioFlinger binder interface
@@ -30,10 +40,9 @@
 sp<AudioSystem::AudioFlingerClient> AudioSystem::gAudioFlingerClient;
 audio_error_callback AudioSystem::gAudioErrorCallback = NULL;
 // Cached values
-int AudioSystem::gOutSamplingRate[NUM_AUDIO_OUTPUT_TYPES];
-int AudioSystem::gOutFrameCount[NUM_AUDIO_OUTPUT_TYPES];
-uint32_t AudioSystem::gOutLatency[NUM_AUDIO_OUTPUT_TYPES];
-bool AudioSystem::gA2dpEnabled;
+DefaultKeyedVector<int, audio_io_handle_t> AudioSystem::gStreamOutputMap(0);
+DefaultKeyedVector<audio_io_handle_t, AudioSystem::OutputDescriptor *> AudioSystem::gOutputs(0);
+
 // Cached values for recording queries
 uint32_t AudioSystem::gPrevInSamplingRate = 16000;
 int AudioSystem::gPrevInFormat = AudioSystem::PCM_16_BIT;
@@ -65,44 +74,12 @@
         binder->linkToDeath(gAudioFlingerClient);
         gAudioFlinger = interface_cast<IAudioFlinger>(binder);
         gAudioFlinger->registerClient(gAudioFlingerClient);
-        // Cache frequently accessed parameters 
-        for (int output = 0; output < NUM_AUDIO_OUTPUT_TYPES; output++) {
-            gOutFrameCount[output] = (int)gAudioFlinger->frameCount(output);
-            gOutSamplingRate[output] = (int)gAudioFlinger->sampleRate(output);
-            gOutLatency[output] = gAudioFlinger->latency(output);
-        }
-        gA2dpEnabled = gAudioFlinger->isA2dpEnabled();
     }
     LOGE_IF(gAudioFlinger==0, "no AudioFlinger!?");
+
     return gAudioFlinger;
 }
 
-// routing helper functions
-status_t AudioSystem::speakerphone(bool state) {
-    uint32_t routes = state ? ROUTE_SPEAKER : ROUTE_EARPIECE;
-    return setRouting(MODE_IN_CALL, routes, ROUTE_ALL);
-}
-
-status_t AudioSystem::isSpeakerphoneOn(bool* state) {
-    uint32_t routes = 0;
-    status_t s = getRouting(MODE_IN_CALL, &routes);
-    *state = !!(routes & ROUTE_SPEAKER);
-    return s;
-}
-
-status_t AudioSystem::bluetoothSco(bool state) {
-    uint32_t mask = ROUTE_BLUETOOTH_SCO;
-    uint32_t routes = state ? mask : ROUTE_EARPIECE;
-    return setRouting(MODE_IN_CALL, routes, ROUTE_ALL);
-}
-
-status_t AudioSystem::isBluetoothScoOn(bool* state) {
-    uint32_t routes = 0;
-    status_t s = getRouting(MODE_IN_CALL, &routes);
-    *state = !!(routes & ROUTE_BLUETOOTH_SCO);
-    return s;
-}
-
 status_t AudioSystem::muteMicrophone(bool state) {
     const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
     if (af == 0) return PERMISSION_DENIED;
@@ -148,12 +125,12 @@
     return NO_ERROR;
 }
 
-status_t AudioSystem::setStreamVolume(int stream, float value)
+status_t AudioSystem::setStreamVolume(int stream, float value, void *output)
 {
     if (uint32_t(stream) >= NUM_STREAM_TYPES) return BAD_VALUE;
     const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
     if (af == 0) return PERMISSION_DENIED;
-    af->setStreamVolume(stream, value);
+    af->setStreamVolume(stream, value, output);
     return NO_ERROR;
 }
 
@@ -166,12 +143,12 @@
     return NO_ERROR;
 }
 
-status_t AudioSystem::getStreamVolume(int stream, float* volume)
+status_t AudioSystem::getStreamVolume(int stream, float* volume, void *output)
 {
     if (uint32_t(stream) >= NUM_STREAM_TYPES) return BAD_VALUE;
     const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
     if (af == 0) return PERMISSION_DENIED;
-    *volume = af->streamVolume(stream);
+    *volume = af->streamVolume(stream, output);
     return NO_ERROR;
 }
 
@@ -192,29 +169,6 @@
     return af->setMode(mode);
 }
 
-status_t AudioSystem::getMode(int* mode)
-{
-    const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
-    if (af == 0) return PERMISSION_DENIED;
-    *mode = af->getMode();
-    return NO_ERROR;
-}
-
-status_t AudioSystem::setRouting(int mode, uint32_t routes, uint32_t mask)
-{
-    const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
-    if (af == 0) return PERMISSION_DENIED;
-    return af->setRouting(mode, routes, mask);
-}
-
-status_t AudioSystem::getRouting(int mode, uint32_t* routes)
-{
-    const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
-    if (af == 0) return PERMISSION_DENIED;
-    uint32_t r = af->getRouting(mode);
-    *routes = r;
-    return NO_ERROR;
-}
 
 status_t AudioSystem::isMusicActive(bool* state) {
     const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
@@ -223,12 +177,20 @@
     return NO_ERROR;
 }
 
-// Temporary interface, do not use
-// TODO: Replace with a more generic key:value get/set mechanism
-status_t AudioSystem::setParameter(const char* key, const char* value) {
+
+status_t AudioSystem::setParameters(audio_io_handle_t ioHandle, const String8& keyValuePairs) {
     const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
     if (af == 0) return PERMISSION_DENIED;
-    return af->setParameter(key, value);
+    return af->setParameters(ioHandle, keyValuePairs);
+}
+
+String8 AudioSystem::getParameters(audio_io_handle_t ioHandle, const String8& keys) {
+    const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
+    String8 result = String8("");
+    if (af == 0) return result;
+
+    result = af->getParameters(ioHandle, keys);
+    return result;
 }
 
 // convert volume steps to natural log scale
@@ -257,55 +219,108 @@
 
 status_t AudioSystem::getOutputSamplingRate(int* samplingRate, int streamType)
 {
-    int output = getOutput(streamType);
-    
-    if (output == NUM_AUDIO_OUTPUT_TYPES) return PERMISSION_DENIED;
+    OutputDescriptor *outputDesc;
+    audio_io_handle_t output;
 
-    // gOutSamplingRate[] is updated by getOutput() which calls get_audio_flinger()
-    LOGV("getOutputSamplingRate() streamType %d, output %d, sampling rate %d", streamType, output, gOutSamplingRate[output]);
-    
-    *samplingRate = gOutSamplingRate[output];
-    
+    if (streamType == DEFAULT) {
+        streamType = MUSIC;
+    }
+
+    output = getOutput((stream_type)streamType);
+    if (output == 0) {
+        return PERMISSION_DENIED;
+    }
+
+    gLock.lock();
+    outputDesc = AudioSystem::gOutputs.valueFor(output);
+    if (outputDesc == 0) {
+        LOGV("getOutputSamplingRate() no output descriptor for output %p in gOutputs", output);
+        gLock.unlock();
+        const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
+        if (af == 0) return PERMISSION_DENIED;
+        *samplingRate = af->sampleRate(output);
+    } else {
+        LOGV("getOutputSamplingRate() reading from output desc");
+        *samplingRate = outputDesc->samplingRate;
+        gLock.unlock();
+    }
+
+    LOGV("getOutputSamplingRate() streamType %d, output %p, sampling rate %d", streamType, output, *samplingRate);
+
     return NO_ERROR;
 }
 
 status_t AudioSystem::getOutputFrameCount(int* frameCount, int streamType)
 {
-    int output = getOutput(streamType);
+    OutputDescriptor *outputDesc;
+    audio_io_handle_t output;
 
-    if (output == NUM_AUDIO_OUTPUT_TYPES) return PERMISSION_DENIED;
+    if (streamType == DEFAULT) {
+        streamType = MUSIC;
+    }
 
-    // gOutFrameCount[] is updated by getOutput() which calls get_audio_flinger()
-    LOGV("getOutputFrameCount() streamType %d, output %d, frame count %d", streamType, output, gOutFrameCount[output]);
+    output = getOutput((stream_type)streamType);
+    if (output == 0) {
+        return PERMISSION_DENIED;
+    }
 
-    *frameCount = gOutFrameCount[output];
-    
+    gLock.lock();
+    outputDesc = AudioSystem::gOutputs.valueFor(output);
+    if (outputDesc == 0) {
+        gLock.unlock();
+        const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
+        if (af == 0) return PERMISSION_DENIED;
+        *frameCount = af->frameCount(output);
+    } else {
+        *frameCount = outputDesc->frameCount;
+        gLock.unlock();
+    }
+
+    LOGV("getOutputFrameCount() streamType %d, output %p, frameCount %d", streamType, output, *frameCount);
+
     return NO_ERROR;
 }
 
 status_t AudioSystem::getOutputLatency(uint32_t* latency, int streamType)
 {
-    int output = getOutput(streamType);
+    OutputDescriptor *outputDesc;
+    audio_io_handle_t output;
 
-    if (output == NUM_AUDIO_OUTPUT_TYPES) return PERMISSION_DENIED;
+    if (streamType == DEFAULT) {
+        streamType = MUSIC;
+    }
 
-    // gOutLatency[] is updated by getOutput() which calls get_audio_flinger()
-    LOGV("getOutputLatency() streamType %d, output %d, latency %d", streamType, output, gOutLatency[output]);
+    output = getOutput((stream_type)streamType);
+    if (output == 0) {
+        return PERMISSION_DENIED;
+    }
 
-    *latency = gOutLatency[output];
-    
+    gLock.lock();
+    outputDesc = AudioSystem::gOutputs.valueFor(output);
+    if (outputDesc == 0) {
+        gLock.unlock();
+        const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
+        if (af == 0) return PERMISSION_DENIED;
+        *latency = af->latency(output);
+    } else {
+        *latency = outputDesc->latency;
+        gLock.unlock();
+    }
+
+    LOGV("getOutputLatency() streamType %d, output %p, latency %d", streamType, output, *latency);
+
     return NO_ERROR;
 }
 
-status_t AudioSystem::getInputBufferSize(uint32_t sampleRate, int format, int channelCount, 
+status_t AudioSystem::getInputBufferSize(uint32_t sampleRate, int format, int channelCount,
     size_t* buffSize)
 {
     // Do we have a stale gInBufferSize or are we requesting the input buffer size for new values
-    if ((gInBuffSize == 0) || (sampleRate != gPrevInSamplingRate) || (format != gPrevInFormat) 
+    if ((gInBuffSize == 0) || (sampleRate != gPrevInSamplingRate) || (format != gPrevInFormat)
         || (channelCount != gPrevInChannelCount)) {
         // save the request params
         gPrevInSamplingRate = sampleRate;
-        gPrevInFormat = format; 
+        gPrevInFormat = format;
         gPrevInChannelCount = channelCount;
 
         gInBuffSize = 0;
@@ -314,24 +329,18 @@
             return PERMISSION_DENIED;
         }
         gInBuffSize = af->getInputBufferSize(sampleRate, format, channelCount);
-    } 
+    }
     *buffSize = gInBuffSize;
-    
+
     return NO_ERROR;
 }
 
 // ---------------------------------------------------------------------------
 
-void AudioSystem::AudioFlingerClient::binderDied(const wp<IBinder>& who) {   
+void AudioSystem::AudioFlingerClient::binderDied(const wp<IBinder>& who) {
     Mutex::Autolock _l(AudioSystem::gLock);
-    AudioSystem::gAudioFlinger.clear();
 
-    for (int output = 0; output < NUM_AUDIO_OUTPUT_TYPES; output++) {
-        gOutFrameCount[output] = 0;
-        gOutSamplingRate[output] = 0;
-        gOutLatency[output] = 0;
-    }
-    AudioSystem::gInBuffSize = 0;
+    AudioSystem::gAudioFlinger.clear();
 
     if (gAudioErrorCallback) {
         gAudioErrorCallback(DEAD_OBJECT);
@@ -339,33 +348,83 @@
     LOGW("AudioFlinger server died!");
 }
 
-void AudioSystem::AudioFlingerClient::a2dpEnabledChanged(bool enabled) {
-    gA2dpEnabled = enabled;        
-    LOGV("AudioFlinger A2DP enabled status changed! %d", enabled);
+void AudioSystem::AudioFlingerClient::ioConfigChanged(int event, void *param1, void *param2) {
+    LOGV("ioConfigChanged() event %d", event);
+    audio_io_handle_t ioHandle = (audio_io_handle_t)param1;
+    OutputDescriptor *desc;
+    uint32_t stream;
+
+    if (param1 == 0) return;
+
+    Mutex::Autolock _l(AudioSystem::gLock);
+
+    switch (event) {
+    case STREAM_CONFIG_CHANGED:
+        if (param2 == 0) break;
+        stream = *(uint32_t *)param2;
+        LOGV("ioConfigChanged() STREAM_CONFIG_CHANGED stream %d, output %p", stream, ioHandle);
+        if (gStreamOutputMap.indexOfKey(stream) >= 0) {
+            gStreamOutputMap.replaceValueFor(stream, ioHandle);
+        }
+        break;
+    case OUTPUT_OPENED: {
+        if (gOutputs.indexOfKey(ioHandle) >= 0) {
+            LOGV("ioConfigChanged() opening already existing output! %p", ioHandle);
+            break;
+        }
+        if (param2 == 0) break;
+        desc = (OutputDescriptor *)param2;
+
+        OutputDescriptor *outputDesc =  new OutputDescriptor(*desc);
+        gOutputs.add(ioHandle, outputDesc);
+        LOGV("ioConfigChanged() new output samplingRate %d, format %d channels %d frameCount %d latency %d",
+                outputDesc->samplingRate, outputDesc->format, outputDesc->channels, outputDesc->frameCount, outputDesc->latency);
+        } break;
+    case OUTPUT_CLOSED: {
+        if (gOutputs.indexOfKey(ioHandle) < 0) {
+            LOGW("ioConfigChanged() closing unknow output! %p", ioHandle);
+            break;
+        }
+        LOGV("ioConfigChanged() output %p closed", ioHandle);
+
+        gOutputs.removeItem(ioHandle);
+        for (int i = gStreamOutputMap.size() - 1; i >= 0 ; i--) {
+            if (gStreamOutputMap.valueAt(i) == ioHandle) {
+                gStreamOutputMap.removeItemsAt(i);
+            }
+        }
+        } break;
+
+    case OUTPUT_CONFIG_CHANGED: {
+        int index = gOutputs.indexOfKey(ioHandle);
+        if (index < 0) {
+            LOGW("ioConfigChanged() modifying unknow output! %p", ioHandle);
+            break;
+        }
+        if (param2 == 0) break;
+        desc = (OutputDescriptor *)param2;
+
+        LOGV("ioConfigChanged() new config for output %p samplingRate %d, format %d channels %d frameCount %d latency %d",
+                ioHandle, desc->samplingRate, desc->format,
+                desc->channels, desc->frameCount, desc->latency);
+        OutputDescriptor *outputDesc = gOutputs.valueAt(index);
+        delete outputDesc;
+        outputDesc =  new OutputDescriptor(*desc);
+        gOutputs.replaceValueFor(ioHandle, outputDesc);
+    } break;
+    case INPUT_OPENED:
+    case INPUT_CLOSED:
+    case INPUT_CONFIG_CHANGED:
+        break;
+
+    }
 }
 
 void AudioSystem::setErrorCallback(audio_error_callback cb) {
-    Mutex::Autolock _l(AudioSystem::gLock);
+    Mutex::Autolock _l(gLock);
     gAudioErrorCallback = cb;
 }
 
-int AudioSystem::getOutput(int streamType)
-{   
-    // make sure that gA2dpEnabled is valid by calling get_audio_flinger() which in turn 
-    // will call gAudioFlinger->isA2dpEnabled()
-    const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
-    if (af == 0) return NUM_AUDIO_OUTPUT_TYPES;
-
-    if (streamType == DEFAULT) {
-        streamType = MUSIC;
-    }
-    if (gA2dpEnabled && routedToA2dpOutput(streamType)) {
-        return AUDIO_OUTPUT_A2DP;
-    } else {
-        return AUDIO_OUTPUT_HARDWARE;
-    }
-}
-
 bool AudioSystem::routedToA2dpOutput(int streamType) {
     switch(streamType) {
     case MUSIC:
@@ -379,6 +438,451 @@
 }
 
 
+// client singleton for AudioPolicyService binder interface
+sp<IAudioPolicyService> AudioSystem::gAudioPolicyService;
+sp<AudioSystem::AudioPolicyServiceClient> AudioSystem::gAudioPolicyServiceClient;
+
+
+// establish binder interface to AudioFlinger service
+const sp<IAudioPolicyService>& AudioSystem::get_audio_policy_service()
+{
+    gLock.lock();
+    if (gAudioPolicyService.get() == 0) {
+        sp<IServiceManager> sm = defaultServiceManager();
+        sp<IBinder> binder;
+        do {
+            binder = sm->getService(String16("media.audio_policy"));
+            if (binder != 0)
+                break;
+            LOGW("AudioPolicyService not published, waiting...");
+            usleep(500000); // 0.5 s
+        } while(true);
+        if (gAudioPolicyServiceClient == NULL) {
+            gAudioPolicyServiceClient = new AudioPolicyServiceClient();
+        }
+        binder->linkToDeath(gAudioPolicyServiceClient);
+        gAudioPolicyService = interface_cast<IAudioPolicyService>(binder);
+        gLock.unlock();
+    } else {
+        gLock.unlock();
+    }
+    return gAudioPolicyService;
+}
+
+status_t AudioSystem::setDeviceConnectionState(audio_devices device,
+                                                  device_connection_state state,
+                                                  const char *device_address)
+{
+    const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+    if (aps == 0) return PERMISSION_DENIED;
+
+    return aps->setDeviceConnectionState(device, state, device_address);
+}
+
+AudioSystem::device_connection_state AudioSystem::getDeviceConnectionState(audio_devices device,
+                                                  const char *device_address)
+{
+    const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+    if (aps == 0) return DEVICE_STATE_UNAVAILABLE;
+
+    return aps->getDeviceConnectionState(device, device_address);
+}
+
+status_t AudioSystem::setPhoneState(int state)
+{
+    const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+    if (aps == 0) return PERMISSION_DENIED;
+
+    return aps->setPhoneState(state);
+}
+
+status_t AudioSystem::setRingerMode(uint32_t mode, uint32_t mask)
+{
+    const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+    if (aps == 0) return PERMISSION_DENIED;
+    return aps->setRingerMode(mode, mask);
+}
+
+status_t AudioSystem::setForceUse(force_use usage, forced_config config)
+{
+    const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+    if (aps == 0) return PERMISSION_DENIED;
+    return aps->setForceUse(usage, config);
+}
+
+AudioSystem::forced_config AudioSystem::getForceUse(force_use usage)
+{
+    const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+    if (aps == 0) return FORCE_NONE;
+    return aps->getForceUse(usage);
+}
+
+
+audio_io_handle_t AudioSystem::getOutput(stream_type stream,
+                                    uint32_t samplingRate,
+                                    uint32_t format,
+                                    uint32_t channels,
+                                    output_flags flags)
+{
+    audio_io_handle_t output = NULL;
+    if ((flags & AudioSystem::OUTPUT_FLAG_DIRECT) == 0) {
+        Mutex::Autolock _l(gLock);
+        output = AudioSystem::gStreamOutputMap.valueFor(stream);
+        LOGV_IF((output != NULL), "getOutput() read %p from cache for stream %d", output, stream);
+    }
+    if (output == NULL) {
+        const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+        if (aps == 0) return NULL;
+        output = aps->getOutput(stream, samplingRate, format, channels, flags);
+        if ((flags & AudioSystem::OUTPUT_FLAG_DIRECT) == 0) {
+            Mutex::Autolock _l(gLock);
+            AudioSystem::gStreamOutputMap.add(stream, output);
+        }
+    }
+    return output;
+}
+
+status_t AudioSystem::startOutput(audio_io_handle_t output, AudioSystem::stream_type stream)
+{
+    const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+    if (aps == 0) return PERMISSION_DENIED;
+    return aps->startOutput(output, stream);
+}
+
+status_t AudioSystem::stopOutput(audio_io_handle_t output, AudioSystem::stream_type stream)
+{
+    const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+    if (aps == 0) return PERMISSION_DENIED;
+    return aps->stopOutput(output, stream);
+}
+
+void AudioSystem::releaseOutput(audio_io_handle_t output)
+{
+    const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+    if (aps == 0) return;
+    aps->releaseOutput(output);
+}
+
+audio_io_handle_t AudioSystem::getInput(int inputSource,
+                                    uint32_t samplingRate,
+                                    uint32_t format,
+                                    uint32_t channels,
+                                    audio_in_acoustics acoustics)
+{
+    const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+    if (aps == 0) return NULL;
+    return aps->getInput(inputSource, samplingRate, format, channels, acoustics);
+}
+
+status_t AudioSystem::startInput(audio_io_handle_t input)
+{
+    const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+    if (aps == 0) return PERMISSION_DENIED;
+    return aps->startInput(input);
+}
+
+status_t AudioSystem::stopInput(audio_io_handle_t input)
+{
+    const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+    if (aps == 0) return PERMISSION_DENIED;
+    return aps->stopInput(input);
+}
+
+void AudioSystem::releaseInput(audio_io_handle_t input)
+{
+    const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+    if (aps == 0) return;
+    aps->releaseInput(input);
+}
+
+status_t AudioSystem::initStreamVolume(stream_type stream,
+                                    int indexMin,
+                                    int indexMax)
+{
+    const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+    if (aps == 0) return PERMISSION_DENIED;
+    return aps->initStreamVolume(stream, indexMin, indexMax);
+}
+
+status_t AudioSystem::setStreamVolumeIndex(stream_type stream, int index)
+{
+    const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+    if (aps == 0) return PERMISSION_DENIED;
+    return aps->setStreamVolumeIndex(stream, index);
+}
+
+status_t AudioSystem::getStreamVolumeIndex(stream_type stream, int *index)
+{
+    const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+    if (aps == 0) return PERMISSION_DENIED;
+    return aps->getStreamVolumeIndex(stream, index);
+}
+
+// ---------------------------------------------------------------------------
+
+void AudioSystem::AudioPolicyServiceClient::binderDied(const wp<IBinder>& who) {
+    Mutex::Autolock _l(AudioSystem::gLock);
+    AudioSystem::gAudioPolicyService.clear();
+
+    LOGW("AudioPolicyService server died!");
+}
+
+// ---------------------------------------------------------------------------
+
+
+// use emulated popcount optimization
+// http://www.df.lth.se/~john_e/gems/gem002d.html
+uint32_t AudioSystem::popCount(uint32_t u)
+{
+    u = ((u&0x55555555) + ((u>>1)&0x55555555));
+    u = ((u&0x33333333) + ((u>>2)&0x33333333));
+    u = ((u&0x0f0f0f0f) + ((u>>4)&0x0f0f0f0f));
+    u = ((u&0x00ff00ff) + ((u>>8)&0x00ff00ff));
+    u = ( u&0x0000ffff) + (u>>16);
+    return u;
+}
+
+bool AudioSystem::isOutputDevice(audio_devices device)
+{
+    if ((popCount(device) == 1 ) &&
+        ((device & ~AudioSystem::DEVICE_OUT_ALL) == 0)) {
+        return true;
+    } else {
+        return false;
+    }
+}
+
+bool AudioSystem::isInputDevice(audio_devices device)
+{
+    if ((popCount(device) == 1 ) &&
+        ((device & ~AudioSystem::DEVICE_IN_ALL) == 0)) {
+        return true;
+    } else {
+        return false;
+    }
+}
+
+bool AudioSystem::isA2dpDevice(audio_devices device)
+{
+    if ((popCount(device) == 1 ) &&
+        (device & (AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP |
+                   AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES |
+                   AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER))) {
+        return true;
+    } else {
+        return false;
+    }
+}
+
+bool AudioSystem::isBluetoothScoDevice(audio_devices device)
+{
+    if ((popCount(device) == 1 ) &&
+        (device & (AudioSystem::DEVICE_OUT_BLUETOOTH_SCO |
+                   AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_HEADSET |
+                   AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_CARKIT))) {
+        return true;
+    } else {
+        return false;
+    }
+}
+
+bool AudioSystem::isLowVisibility(stream_type stream)
+{
+    if (stream == AudioSystem::SYSTEM || stream == AudioSystem::NOTIFICATION) {
+        return true;
+    } else {
+        return false;
+    }
+}
+
+bool AudioSystem::isInputChannel(uint32_t channel)
+{
+    if ((channel & ~AudioSystem::CHANNEL_IN_ALL) == 0) {
+        return true;
+    } else {
+        return false;
+    }
+}
+
+bool AudioSystem::isOutputChannel(uint32_t channel)
+{
+    if ((channel & ~AudioSystem::CHANNEL_OUT_ALL) == 0) {
+        return true;
+    } else {
+        return false;
+    }
+}
+
+bool AudioSystem::isValidFormat(uint32_t format)
+{
+    switch (format & MAIN_FORMAT_MASK) {
+    case         PCM:
+    case         MP3:
+    case         AMR_NB:
+    case         AMR_WB:
+    case         AAC:
+    case         HE_AAC_V1:
+    case         HE_AAC_V2:
+    case         VORBIS:
+        return true;
+    default:
+        return false;
+    }
+}
+
+bool AudioSystem::isLinearPCM(uint32_t format)
+{
+    switch (format) {
+    case         PCM_16_BIT:
+    case         PCM_8_BIT:
+        return true;
+    default:
+        return false;
+    }
+}
+
+//------------------------- AudioParameter class implementation ---------------
+
+const char *AudioParameter::keyRouting = "routing";
+const char *AudioParameter::keySamplingRate = "sampling_rate";
+const char *AudioParameter::keyFormat = "format";
+const char *AudioParameter::keyChannels = "channels";
+const char *AudioParameter::keyFrameCount = "frame_count";
+
+AudioParameter::AudioParameter(const String8& keyValuePairs)
+{
+    char *str = new char[keyValuePairs.length()+1];
+    mKeyValuePairs = keyValuePairs;
+
+    strcpy(str, keyValuePairs.string());
+    char *pair = strtok(str, ";");
+    while (pair != NULL) {
+        if (strlen(pair) != 0) {
+            size_t eqIdx = strcspn(pair, "=");
+            String8 key = String8(pair, eqIdx);
+            String8 value;
+            if (eqIdx == strlen(pair)) {
+                value = String8("");
+            } else {
+                value = String8(pair + eqIdx + 1);
+            }
+            if (mParameters.indexOfKey(key) < 0) {
+                mParameters.add(key, value);
+            } else {
+                mParameters.replaceValueFor(key, value);
+            }
+        } else {
+            LOGV("AudioParameter() cstor empty key value pair");
+        }
+        pair = strtok(NULL, ";");
+    }
+
+    delete[] str;
+}
+
+AudioParameter::~AudioParameter()
+{
+    mParameters.clear();
+}
+
+String8 AudioParameter::toString()
+{
+    String8 str = String8("");
+
+    size_t size = mParameters.size();
+    for (size_t i = 0; i < size; i++) {
+        str += mParameters.keyAt(i);
+        str += "=";
+        str += mParameters.valueAt(i);
+        if (i < (size - 1)) str += ";";
+    }
+    return str;
+}
+
+status_t AudioParameter::add(const String8& key, const String8& value)
+{
+    if (mParameters.indexOfKey(key) < 0) {
+        mParameters.add(key, value);
+        return NO_ERROR;
+    } else {
+        mParameters.replaceValueFor(key, value);
+        return ALREADY_EXISTS;
+    }
+}
+
+status_t AudioParameter::addInt(const String8& key, const int value)
+{
+    char str[12];
+    if (snprintf(str, 12, "%d", value) > 0) {
+        String8 str8 = String8(str);
+        return add(key, str8);
+    } else {
+        return BAD_VALUE;
+    }
+}
+
+status_t AudioParameter::addFloat(const String8& key, const float value)
+{
+    char str[23];
+    if (snprintf(str, 23, "%.10f", value) > 0) {
+        String8 str8 = String8(str);
+        return add(key, str8);
+    } else {
+        return BAD_VALUE;
+    }
+}
+
+status_t AudioParameter::remove(const String8& key)
+{
+    if (mParameters.indexOfKey(key) >= 0) {
+        mParameters.removeItem(key);
+        return NO_ERROR;
+    } else {
+        return BAD_VALUE;
+    }
+}
+
+status_t AudioParameter::get(const String8& key, String8& value)
+{
+    if (mParameters.indexOfKey(key) >= 0) {
+        value = mParameters.valueFor(key);
+        return NO_ERROR;
+    } else {
+        return BAD_VALUE;
+    }
+}
+
+status_t AudioParameter::getInt(const String8& key, int& value)
+{
+    String8 str8;
+    status_t result = get(key, str8);
+    value = 0;
+    if (result == NO_ERROR) {
+        int val;
+        if (sscanf(str8.string(), "%d", &val) == 1) {
+            value = val;
+        } else {
+            result = INVALID_OPERATION;
+        }
+    }
+    return result;
+}
+
+status_t AudioParameter::getFloat(const String8& key, float& value)
+{
+    String8 str8;
+    status_t result = get(key, str8);
+    value = 0;
+    if (result == NO_ERROR) {
+        float val;
+        if (sscanf(str8.string(), "%f", &val) == 1) {
+            value = val;
+        } else {
+            result = INVALID_OPERATION;
+        }
+    }
+    return result;
+}
 
 }; // namespace android
 
diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp
index 7b9eda7..b147d25 100644
--- a/media/libmedia/AudioTrack.cpp
+++ b/media/libmedia/AudioTrack.cpp
@@ -54,7 +54,7 @@
         int streamType,
         uint32_t sampleRate,
         int format,
-        int channelCount,
+        int channels,
         int frameCount,
         uint32_t flags,
         callback_t cbf,
@@ -62,7 +62,7 @@
         int notificationFrames)
     : mStatus(NO_INIT)
 {
-    mStatus = set(streamType, sampleRate, format, channelCount,
+    mStatus = set(streamType, sampleRate, format, channels,
             frameCount, flags, cbf, user, notificationFrames, 0);
 }
 
@@ -70,7 +70,7 @@
         int streamType,
         uint32_t sampleRate,
         int format,
-        int channelCount,
+        int channels,
         const sp<IMemory>& sharedBuffer,
         uint32_t flags,
         callback_t cbf,
@@ -78,7 +78,7 @@
         int notificationFrames)
     : mStatus(NO_INIT)
 {
-    mStatus = set(streamType, sampleRate, format, channelCount,
+    mStatus = set(streamType, sampleRate, format, channels,
             0, flags, cbf, user, notificationFrames, sharedBuffer);
 }
 
@@ -97,6 +97,7 @@
         }
         mAudioTrack.clear();
         IPCThreadState::self()->flushCommands();
+        AudioSystem::releaseOutput(getOutput());
     }
 }
 
@@ -104,7 +105,7 @@
         int streamType,
         uint32_t sampleRate,
         int format,
-        int channelCount,
+        int channels,
         int frameCount,
         uint32_t flags,
         callback_t cbf,
@@ -150,63 +151,84 @@
     if (format == 0) {
         format = AudioSystem::PCM_16_BIT;
     }
-    if (channelCount == 0) {
-        channelCount = 2;
+    if (channels == 0) {
+        channels = AudioSystem::CHANNEL_OUT_STEREO;
     }
 
     // validate parameters
-    if (((format != AudioSystem::PCM_8_BIT) || sharedBuffer != 0) &&
-        (format != AudioSystem::PCM_16_BIT)) {
+    if (!AudioSystem::isValidFormat(format)) {
         LOGE("Invalid format");
         return BAD_VALUE;
     }
-    if (channelCount != 1 && channelCount != 2) {
-        LOGE("Invalid channel number");
+
+    // force direct flag if format is not linear PCM
+    if (!AudioSystem::isLinearPCM(format)) {
+        flags |= AudioSystem::OUTPUT_FLAG_DIRECT;
+    }
+
+    if (!AudioSystem::isOutputChannel(channels)) {
+        LOGE("Invalid channel mask");
+        return BAD_VALUE;
+    }
+    uint32_t channelCount = AudioSystem::popCount(channels);
+
+    audio_io_handle_t output = AudioSystem::getOutput((AudioSystem::stream_type)streamType,
+            sampleRate, format, channels, (AudioSystem::output_flags)flags);
+
+    if (output == 0) {
+        LOGE("Could not get audio output for stream type %d", streamType);
         return BAD_VALUE;
     }
 
-    // Ensure that buffer depth covers at least audio hardware latency
-    uint32_t minBufCount = afLatency / ((1000 * afFrameCount)/afSampleRate);
-    if (minBufCount < 2) minBufCount = 2;
-
-    // When playing from shared buffer, playback will start even if last audioflinger
-    // block is partly filled.
-    if (sharedBuffer != 0 && minBufCount > 1) {
-        minBufCount--;
-    }
-
-    int minFrameCount = (afFrameCount*sampleRate*minBufCount)/afSampleRate;
-
-    if (sharedBuffer == 0) {
-        if (frameCount == 0) {
-            frameCount = minFrameCount;
-        }
-        if (notificationFrames == 0) {
-            notificationFrames = frameCount/2;
-        }
-        // Make sure that application is notified with sufficient margin
-        // before underrun
-        if (notificationFrames > frameCount/2) {
-            notificationFrames = frameCount/2;
+    if (!AudioSystem::isLinearPCM(format)) {
+        if (sharedBuffer != 0) {
+            frameCount = sharedBuffer->size();
         }
     } else {
-        // Ensure that buffer alignment matches channelcount
-        if (((uint32_t)sharedBuffer->pointer() & (channelCount | 1)) != 0) {
-            LOGE("Invalid buffer alignement: address %p, channelCount %d", sharedBuffer->pointer(), channelCount);
-            return BAD_VALUE;
-        }
-        frameCount = sharedBuffer->size()/channelCount/sizeof(int16_t);
-    }
+        // Ensure that buffer depth covers at least audio hardware latency
+        uint32_t minBufCount = afLatency / ((1000 * afFrameCount)/afSampleRate);
+        if (minBufCount < 2) minBufCount = 2;
 
-    if (frameCount < minFrameCount) {
-      LOGE("Invalid buffer size: minFrameCount %d, frameCount %d", minFrameCount, frameCount);
-      return BAD_VALUE;
+        int minFrameCount = (afFrameCount*sampleRate*minBufCount)/afSampleRate;
+
+        if (sharedBuffer == 0) {
+            if (frameCount == 0) {
+                frameCount = minFrameCount;
+            }
+            if (notificationFrames == 0) {
+                notificationFrames = frameCount/2;
+            }
+            // Make sure that application is notified with sufficient margin
+            // before underrun
+            if (notificationFrames > frameCount/2) {
+                notificationFrames = frameCount/2;
+            }
+            if (frameCount < minFrameCount) {
+              LOGE("Invalid buffer size: minFrameCount %d, frameCount %d", minFrameCount, frameCount);
+              return BAD_VALUE;
+            }
+        } else {
+            // Ensure that buffer alignment matches channelcount
+            if (((uint32_t)sharedBuffer->pointer() & (channelCount | 1)) != 0) {
+                LOGE("Invalid buffer alignement: address %p, channelCount %d", sharedBuffer->pointer(), channelCount);
+                return BAD_VALUE;
+            }
+            frameCount = sharedBuffer->size()/channelCount/sizeof(int16_t);
+        }
     }
 
     // create the track
     status_t status;
     sp<IAudioTrack> track = audioFlinger->createTrack(getpid(),
-                streamType, sampleRate, format, channelCount, frameCount, flags, sharedBuffer, &status);
+                                                      streamType,
+                                                      sampleRate,
+                                                      format,
+                                                      channelCount,
+                                                      frameCount,
+                                                      ((uint16_t)flags) << 16,
+                                                      sharedBuffer,
+                                                      output,
+                                                      &status);
 
     if (track == 0) {
         LOGE("AudioFlinger could not create track, status: %d", status);
@@ -245,6 +267,7 @@
     mVolume[RIGHT] = 1.0f;
     mStreamType = streamType;
     mFormat = format;
+    mChannels = channels;
     mChannelCount = channelCount;
     mSharedBuffer = sharedBuffer;
     mMuted = false;
@@ -259,6 +282,7 @@
     mMarkerReached = false;
     mNewPosition = 0;
     mUpdatePeriod = 0;
+    mFlags = flags;
 
     return NO_ERROR;
 }
@@ -297,7 +321,11 @@
 
 int AudioTrack::frameSize() const
 {
-    return channelCount()*((format() == AudioSystem::PCM_8_BIT) ? sizeof(uint8_t) : sizeof(int16_t));
+    if (AudioSystem::isLinearPCM(mFormat)) {
+        return channelCount()*((format() == AudioSystem::PCM_8_BIT) ? sizeof(uint8_t) : sizeof(int16_t));
+    } else {
+        return sizeof(uint8_t);
+    }
 }
 
 sp<IMemory>& AudioTrack::sharedBuffer()
@@ -323,6 +351,7 @@
      }
 
     if (android_atomic_or(1, &mActive) == 0) {
+        AudioSystem::startOutput(getOutput(), (AudioSystem::stream_type)mStreamType);
         mNewPosition = mCblk->server + mUpdatePeriod;
         mCblk->bufferTimeoutMs = MAX_STARTUP_TIMEOUT_MS;
         mCblk->waitTimeMs = 0;
@@ -367,6 +396,7 @@
         } else {
             setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_NORMAL);
         }
+        AudioSystem::stopOutput(getOutput(), (AudioSystem::stream_type)mStreamType);
     }
 
     if (t != 0) {
@@ -382,12 +412,12 @@
 void AudioTrack::flush()
 {
     LOGV("flush");
-    
+
     // clear playback marker and periodic update counter
     mMarkerPosition = 0;
     mMarkerReached = false;
     mUpdatePeriod = 0;
-    
+
 
     if (!mActive) {
         mAudioTrack->flush();
@@ -403,6 +433,7 @@
     if (android_atomic_and(~1, &mActive) == 1) {
         mActive = 0;
         mAudioTrack->pause();
+        AudioSystem::stopOutput(getOutput(), (AudioSystem::stream_type)mStreamType);
     }
 }
 
@@ -455,7 +486,6 @@
 {
     audio_track_cblk_t* cblk = mCblk;
 
-
     Mutex::Autolock _l(cblk->lock);
 
     if (loopCount == 0) {
@@ -476,7 +506,7 @@
         LOGE("setLoop invalid value: loop markers beyond data: loopStart %d, loopEnd %d, framecount %d",
             loopStart, loopEnd, mFrameCount);
         return BAD_VALUE;
-    }   
+    }
 
     cblk->loopStart = loopStart;
     cblk->loopEnd = loopEnd;
@@ -555,7 +585,7 @@
 
     mCblk->server = position;
     mCblk->forceReady = 1;
-    
+
     return NO_ERROR;
 }
 
@@ -571,7 +601,7 @@
 status_t AudioTrack::reload()
 {
     if (!stopped()) return INVALID_OPERATION;
-    
+
     flush();
 
     mCblk->stepUser(mFrameCount);
@@ -579,6 +609,12 @@
     return NO_ERROR;
 }
 
+audio_io_handle_t AudioTrack::getOutput()
+{
+    return AudioSystem::getOutput((AudioSystem::stream_type)mStreamType,
+            mCblk->sampleRate, mFormat, mChannels, (AudioSystem::output_flags)mFlags);
+}
+
 // -------------------------------------------------------------------------
 
 status_t AudioTrack::obtainBuffer(Buffer* audioBuffer, int32_t waitCount)
@@ -608,7 +644,7 @@
                 return WOULD_BLOCK;
             timeout = 0;
             result = cblk->cv.waitRelative(cblk->lock, milliseconds(waitTimeMs));
-            if (__builtin_expect(result!=NO_ERROR, false)) { 
+            if (__builtin_expect(result!=NO_ERROR, false)) {
                 cblk->waitTimeMs += waitTimeMs;
                 if (cblk->waitTimeMs >= cblk->bufferTimeoutMs) {
                     // timing out when a loop has been set and we have already written upto loop end
@@ -616,7 +652,7 @@
                     if (cblk->user < cblk->loopEnd) {
                         LOGW(   "obtainBuffer timed out (is the CPU pegged?) %p "
                                 "user=%08x, server=%08x", this, cblk->user, cblk->server);
-                        //unlock cblk mutex before calling mAudioTrack->start() (see issue #1617140) 
+                        //unlock cblk mutex before calling mAudioTrack->start() (see issue #1617140)
                         cblk->lock.unlock();
                         mAudioTrack->start();
                         cblk->lock.lock();
@@ -624,7 +660,7 @@
                     }
                     cblk->waitTimeMs = 0;
                 }
-                
+
                 if (--waitCount == 0) {
                     return TIMED_OUT;
                 }
@@ -636,7 +672,7 @@
     }
 
     cblk->waitTimeMs = 0;
-    
+
     if (framesReq > framesAvail) {
         framesReq = framesAvail;
     }
@@ -653,12 +689,16 @@
         "but didn't need to be locked. We recovered, but "
         "this shouldn't happen (user=%08x, server=%08x)", cblk->user, cblk->server);
 
-    audioBuffer->flags       = mMuted ? Buffer::MUTE : 0;
-    audioBuffer->channelCount= mChannelCount;
-    audioBuffer->format      = AudioSystem::PCM_16_BIT;
-    audioBuffer->frameCount  = framesReq;
-    audioBuffer->size = framesReq*mChannelCount*sizeof(int16_t);
-    audioBuffer->raw         = (int8_t *)cblk->buffer(u);
+    audioBuffer->flags = mMuted ? Buffer::MUTE : 0;
+    audioBuffer->channelCount = mChannelCount;
+    audioBuffer->frameCount = framesReq;
+    audioBuffer->size = framesReq * cblk->frameSize;
+    if (AudioSystem::isLinearPCM(mFormat)) {
+        audioBuffer->format = AudioSystem::PCM_16_BIT;
+    } else {
+        audioBuffer->format = mFormat;
+    }
+    audioBuffer->raw = (int8_t *)cblk->buffer(u);
     active = mActive;
     return active ? status_t(NO_ERROR) : status_t(STOPPED);
 }
@@ -690,10 +730,8 @@
     Buffer audioBuffer;
 
     do {
-        audioBuffer.frameCount = userSize/mChannelCount;
-        if (mFormat == AudioSystem::PCM_16_BIT) {
-            audioBuffer.frameCount >>= 1;
-        }
+        audioBuffer.frameCount = userSize/frameSize();
+
         // Calling obtainBuffer() with a negative wait count causes
         // an (almost) infinite wait time.
         status_t err = obtainBuffer(&audioBuffer, -1);
@@ -705,6 +743,7 @@
         }
 
         size_t toWrite;
+
         if (mFormat == AudioSystem::PCM_8_BIT) {
             // Divide capacity by 2 to take expansion into account
             toWrite = audioBuffer.size>>1;
@@ -742,13 +781,13 @@
         if (mCblk->flowControlFlag == 0) {
             mCbf(EVENT_UNDERRUN, mUserData, 0);
             if (mCblk->server == mCblk->frameCount) {
-                mCbf(EVENT_BUFFER_END, mUserData, 0);                
+                mCbf(EVENT_BUFFER_END, mUserData, 0);
             }
             mCblk->flowControlFlag = 1;
             if (mSharedBuffer != 0) return false;
         }
     }
-    
+
     // Manage loop end callback
     while (mLoopCount > mCblk->loopCount) {
         int loopCount = -1;
@@ -767,7 +806,7 @@
     }
 
     // Manage new position callback
-    if(mUpdatePeriod > 0) {
+    if (mUpdatePeriod > 0) {
         while (mCblk->server >= mNewPosition) {
             mCbf(EVENT_NEW_POS, mUserData, (void *)&mNewPosition);
             mNewPosition += mUpdatePeriod;
@@ -784,10 +823,10 @@
     do {
 
         audioBuffer.frameCount = frames;
-        
-        // Calling obtainBuffer() with a wait count of 1 
-        // limits wait time to WAIT_PERIOD_MS. This prevents from being 
-        // stuck here not being able to handle timed events (position, markers, loops). 
+
+        // Calling obtainBuffer() with a wait count of 1
+        // limits wait time to WAIT_PERIOD_MS. This prevents from being
+        // stuck here not being able to handle timed events (position, markers, loops).
         status_t err = obtainBuffer(&audioBuffer, 1);
         if (err < NO_ERROR) {
             if (err != TIMED_OUT) {
@@ -832,7 +871,11 @@
         }
 
         audioBuffer.size = writtenSize;
-        audioBuffer.frameCount = writtenSize/mChannelCount/sizeof(int16_t);
+        // NOTE: mCblk->frameSize is not equal to AudioTrack::frameSize() for
+        // 8 bit PCM data: in this case,  mCblk->frameSize is based on a sampel size of
+        // 16 bit.
+        audioBuffer.frameCount = writtenSize/mCblk->frameSize;
+
         frames -= audioBuffer.frameCount;
 
         releaseBuffer(&audioBuffer);
@@ -949,7 +992,7 @@
         // we switch to normal obtainBuffer() timeout period
         if (bufferTimeoutMs == MAX_STARTUP_TIMEOUT_MS) {
             bufferTimeoutMs = MAX_RUN_TIMEOUT_MS - 1;
-        }        
+        }
         // It is possible that we receive a flush()
         // while the mixer is processing a block: in this case,
         // stepServer() is called After the flush() has reset u & s and
@@ -981,7 +1024,7 @@
 
 void* audio_track_cblk_t::buffer(uint32_t offset) const
 {
-    return (int16_t *)this->buffers + (offset-userBase)*this->channels;
+    return (int8_t *)this->buffers + (offset - userBase) * this->frameSize;
 }
 
 uint32_t audio_track_cblk_t::framesAvailable()
diff --git a/media/libmedia/IAudioFlinger.cpp b/media/libmedia/IAudioFlinger.cpp
index 6fc0cb7..9385367 100644
--- a/media/libmedia/IAudioFlinger.cpp
+++ b/media/libmedia/IAudioFlinger.cpp
@@ -16,6 +16,7 @@
 */
 
 #define LOG_TAG "IAudioFlinger"
+//#define LOG_NDEBUG 0
 #include <utils/Log.h>
 
 #include <stdint.h>
@@ -44,17 +45,21 @@
     STREAM_VOLUME,
     STREAM_MUTE,
     SET_MODE,
-    GET_MODE,
-    SET_ROUTING,
-    GET_ROUTING,
     SET_MIC_MUTE,
     GET_MIC_MUTE,
     IS_MUSIC_ACTIVE,
-    SET_PARAMETER,
+    SET_PARAMETERS,
+    GET_PARAMETERS,
     REGISTER_CLIENT,
     GET_INPUTBUFFERSIZE,
-    WAKE_UP,
-    IS_A2DP_ENABLED
+    OPEN_OUTPUT,
+    OPEN_DUPLICATE_OUTPUT,
+    CLOSE_OUTPUT,
+    SUSPEND_OUTPUT,
+    RESTORE_OUTPUT,
+    OPEN_INPUT,
+    CLOSE_INPUT,
+    SET_STREAM_OUTPUT
 };
 
 class BpAudioFlinger : public BpInterface<IAudioFlinger>
@@ -74,6 +79,7 @@
                                 int frameCount,
                                 uint32_t flags,
                                 const sp<IMemory>& sharedBuffer,
+                                void *output,
                                 status_t *status)
     {
         Parcel data, reply;
@@ -86,6 +92,7 @@
         data.writeInt32(frameCount);
         data.writeInt32(flags);
         data.writeStrongBinder(sharedBuffer->asBinder());
+        data.write(&output, sizeof(void *));
         status_t lStatus = remote()->transact(CREATE_TRACK, data, &reply);
         if (lStatus != NO_ERROR) {
             LOGE("createTrack error: %s", strerror(-lStatus));
@@ -99,7 +106,7 @@
 
     virtual sp<IAudioRecord> openRecord(
                                 pid_t pid,
-                                int inputSource,
+                                void *input,
                                 uint32_t sampleRate,
                                 int format,
                                 int channelCount,
@@ -110,7 +117,7 @@
         Parcel data, reply;
         data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
         data.writeInt32(pid);
-        data.writeInt32(inputSource);
+        data.write(&input, sizeof(void *));
         data.writeInt32(sampleRate);
         data.writeInt32(format);
         data.writeInt32(channelCount);
@@ -124,47 +131,47 @@
         return interface_cast<IAudioRecord>(reply.readStrongBinder());
     }
 
-    virtual uint32_t sampleRate(int output) const
+    virtual uint32_t sampleRate(void *output) const
     {
         Parcel data, reply;
         data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
-        data.writeInt32(output);
+        data.write(&output, sizeof(void *));
         remote()->transact(SAMPLE_RATE, data, &reply);
         return reply.readInt32();
     }
 
-    virtual int channelCount(int output) const
+    virtual int channelCount(void *output) const
     {
         Parcel data, reply;
         data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
-        data.writeInt32(output);
+        data.write(&output, sizeof(void *));
         remote()->transact(CHANNEL_COUNT, data, &reply);
         return reply.readInt32();
     }
 
-    virtual int format(int output) const
+    virtual int format(void *output) const
     {
         Parcel data, reply;
         data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
-        data.writeInt32(output);
+        data.write(&output, sizeof(void *));
         remote()->transact(FORMAT, data, &reply);
         return reply.readInt32();
     }
 
-    virtual size_t frameCount(int output) const
+    virtual size_t frameCount(void *output) const
     {
         Parcel data, reply;
         data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
-        data.writeInt32(output);
+        data.write(&output, sizeof(void *));
         remote()->transact(FRAME_COUNT, data, &reply);
         return reply.readInt32();
     }
 
-    virtual uint32_t latency(int output) const
+    virtual uint32_t latency(void *output) const
     {
         Parcel data, reply;
         data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
-        data.writeInt32(output);
+        data.write(&output, sizeof(void *));
         remote()->transact(LATENCY, data, &reply);
         return reply.readInt32();
     }
@@ -203,12 +210,13 @@
         return reply.readInt32();
     }
 
-    virtual status_t setStreamVolume(int stream, float value)
+    virtual status_t setStreamVolume(int stream, float value, void *output)
     {
         Parcel data, reply;
         data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
         data.writeInt32(stream);
         data.writeFloat(value);
+        data.write(&output, sizeof(void *));
         remote()->transact(SET_STREAM_VOLUME, data, &reply);
         return reply.readInt32();
     }
@@ -223,11 +231,12 @@
         return reply.readInt32();
     }
 
-    virtual float streamVolume(int stream) const
+    virtual float streamVolume(int stream, void *output) const
     {
         Parcel data, reply;
         data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
         data.writeInt32(stream);
+        data.write(&output, sizeof(void *));
         remote()->transact(STREAM_VOLUME, data, &reply);
         return reply.readFloat();
     }
@@ -241,26 +250,6 @@
         return reply.readInt32();
     }
 
-    virtual status_t setRouting(int mode, uint32_t routes, uint32_t mask)
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
-        data.writeInt32(mode);
-        data.writeInt32(routes);
-        data.writeInt32(mask);
-        remote()->transact(SET_ROUTING, data, &reply);
-        return reply.readInt32();
-    }
-
-    virtual uint32_t getRouting(int mode) const
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
-        data.writeInt32(mode);
-        remote()->transact(GET_ROUTING, data, &reply);
-        return reply.readInt32();
-    }
-
     virtual status_t setMode(int mode)
     {
         Parcel data, reply;
@@ -270,14 +259,6 @@
         return reply.readInt32();
     }
 
-    virtual int getMode() const
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
-        remote()->transact(GET_MODE, data, &reply);
-        return reply.readInt32();
-    }
-
     virtual status_t setMicMute(bool state)
     {
         Parcel data, reply;
@@ -303,16 +284,26 @@
         return reply.readInt32();
     }
 
-    virtual status_t setParameter(const char* key, const char* value)
+    virtual status_t setParameters(void *ioHandle, const String8& keyValuePairs)
     {
         Parcel data, reply;
         data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
-        data.writeCString(key);
-        data.writeCString(value);
-        remote()->transact(SET_PARAMETER, data, &reply);
+        data.write(&ioHandle, sizeof(void *));
+        data.writeString8(keyValuePairs);
+        remote()->transact(SET_PARAMETERS, data, &reply);
         return reply.readInt32();
     }
-    
+
+    virtual String8 getParameters(void *ioHandle, const String8& keys)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+        data.write(&ioHandle, sizeof(void *));
+        data.writeString8(keys);
+        remote()->transact(GET_PARAMETERS, data, &reply);
+        return reply.readString8();
+    }
+
     virtual void registerClient(const sp<IAudioFlingerClient>& client)
     {
         Parcel data, reply;
@@ -320,7 +311,7 @@
         data.writeStrongBinder(client->asBinder());
         remote()->transact(REGISTER_CLIENT, data, &reply);
     }
-    
+
     virtual size_t getInputBufferSize(uint32_t sampleRate, int format, int channelCount)
     {
         Parcel data, reply;
@@ -331,21 +322,133 @@
         remote()->transact(GET_INPUTBUFFERSIZE, data, &reply);
         return reply.readInt32();
     }
-    
-    virtual void wakeUp()
+
+    virtual void *openOutput(uint32_t *pDevices,
+                            uint32_t *pSamplingRate,
+                            uint32_t *pFormat,
+                            uint32_t *pChannels,
+                            uint32_t *pLatencyMs,
+                            uint32_t flags)
     {
         Parcel data, reply;
+        uint32_t devices = pDevices ? *pDevices : 0;
+        uint32_t samplingRate = pSamplingRate ? *pSamplingRate : 0;
+        uint32_t format = pFormat ? *pFormat : 0;
+        uint32_t channels = pChannels ? *pChannels : 0;
+        uint32_t latency = pLatencyMs ? *pLatencyMs : 0;
+
         data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
-        remote()->transact(WAKE_UP, data, &reply, IBinder::FLAG_ONEWAY);
-        return;
+        data.writeInt32(devices);
+        data.writeInt32(samplingRate);
+        data.writeInt32(format);
+        data.writeInt32(channels);
+        data.writeInt32(latency);
+        data.writeInt32(flags);
+        remote()->transact(OPEN_OUTPUT, data, &reply);
+        void *output;
+        reply.read(&output, sizeof(void *));
+        LOGV("openOutput() returned output, %p", output);
+        devices = reply.readInt32();
+        if (pDevices) *pDevices = devices;
+        samplingRate = reply.readInt32();
+        if (pSamplingRate) *pSamplingRate = samplingRate;
+        format = reply.readInt32();
+        if (pFormat) *pFormat = format;
+        channels = reply.readInt32();
+        if (pChannels) *pChannels = channels;
+        latency = reply.readInt32();
+        if (pLatencyMs) *pLatencyMs = latency;
+        return output;
     }
 
-    virtual bool isA2dpEnabled() const
+    virtual void *openDuplicateOutput(void *output1, void *output2)
     {
         Parcel data, reply;
         data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
-        remote()->transact(IS_A2DP_ENABLED, data, &reply);
-        return (bool)reply.readInt32();
+        data.write(&output1, sizeof(void *));
+        data.write(&output2, sizeof(void *));
+        remote()->transact(OPEN_DUPLICATE_OUTPUT, data, &reply);
+        void *output;
+        reply.read(&output, sizeof(void *));
+        return output;
+    }
+
+    virtual status_t closeOutput(void *output)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+        data.write(&output, sizeof(void *));
+        remote()->transact(CLOSE_OUTPUT, data, &reply);
+        return reply.readInt32();
+    }
+
+    virtual status_t suspendOutput(void *output)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+        data.write(&output, sizeof(void *));
+        remote()->transact(SUSPEND_OUTPUT, data, &reply);
+        return reply.readInt32();
+    }
+
+    virtual status_t restoreOutput(void *output)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+        data.write(&output, sizeof(void *));
+        remote()->transact(RESTORE_OUTPUT, data, &reply);
+        return reply.readInt32();
+    }
+
+    virtual void *openInput(uint32_t *pDevices,
+                                        uint32_t *pSamplingRate,
+                                        uint32_t *pFormat,
+                                        uint32_t *pChannels,
+                                        uint32_t acoustics)
+    {
+        Parcel data, reply;
+        uint32_t devices = pDevices ? *pDevices : 0;
+        uint32_t samplingRate = pSamplingRate ? *pSamplingRate : 0;
+        uint32_t format = pFormat ? *pFormat : 0;
+        uint32_t channels = pChannels ? *pChannels : 0;
+
+        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+        data.writeInt32(devices);
+        data.writeInt32(samplingRate);
+        data.writeInt32(format);
+        data.writeInt32(channels);
+        data.writeInt32(acoustics);
+        remote()->transact(OPEN_INPUT, data, &reply);
+        void *input;
+        reply.read(&input, sizeof(void *));
+        devices = reply.readInt32();
+        if (pDevices) *pDevices = devices;
+        samplingRate = reply.readInt32();
+        if (pSamplingRate) *pSamplingRate = samplingRate;
+        format = reply.readInt32();
+        if (pFormat) *pFormat = format;
+        channels = reply.readInt32();
+        if (pChannels) *pChannels = channels;
+        return input;
+    }
+
+    virtual status_t closeInput(void *input)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+        data.write(&input, sizeof(void *));
+        remote()->transact(CLOSE_INPUT, data, &reply);
+        return reply.readInt32();
+    }
+
+    virtual status_t setStreamOutput(uint32_t stream, void *output)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+        data.writeInt32(stream);
+        data.write(&output, sizeof(void *));
+        remote()->transact(SET_STREAM_OUTPUT, data, &reply);
+        return reply.readInt32();
     }
 };
 
@@ -367,10 +470,12 @@
             size_t bufferCount = data.readInt32();
             uint32_t flags = data.readInt32();
             sp<IMemory> buffer = interface_cast<IMemory>(data.readStrongBinder());
+            void *output;
+            data.read(&output, sizeof(void *));
             status_t status;
             sp<IAudioTrack> track = createTrack(pid,
                     streamType, sampleRate, format,
-                    channelCount, bufferCount, flags, buffer, &status);
+                    channelCount, bufferCount, flags, buffer, output, &status);
             reply->writeInt32(status);
             reply->writeStrongBinder(track->asBinder());
             return NO_ERROR;
@@ -378,14 +483,15 @@
         case OPEN_RECORD: {
             CHECK_INTERFACE(IAudioFlinger, data, reply);
             pid_t pid = data.readInt32();
-            int inputSource = data.readInt32();
+            void *input;
+            data.read(&input, sizeof(void *));
             uint32_t sampleRate = data.readInt32();
             int format = data.readInt32();
             int channelCount = data.readInt32();
             size_t bufferCount = data.readInt32();
             uint32_t flags = data.readInt32();
             status_t status;
-            sp<IAudioRecord> record = openRecord(pid, inputSource,
+            sp<IAudioRecord> record = openRecord(pid, input,
                     sampleRate, format, channelCount, bufferCount, flags, &status);
             reply->writeInt32(status);
             reply->writeStrongBinder(record->asBinder());
@@ -393,31 +499,36 @@
         } break;
         case SAMPLE_RATE: {
             CHECK_INTERFACE(IAudioFlinger, data, reply);
-            int output = data.readInt32();
+            void *output;
+            data.read(&output, sizeof(void *));
             reply->writeInt32( sampleRate(output) );
             return NO_ERROR;
         } break;
         case CHANNEL_COUNT: {
             CHECK_INTERFACE(IAudioFlinger, data, reply);
-            int output = data.readInt32();
+            void *output;
+            data.read(&output, sizeof(void *));
             reply->writeInt32( channelCount(output) );
             return NO_ERROR;
         } break;
         case FORMAT: {
             CHECK_INTERFACE(IAudioFlinger, data, reply);
-            int output = data.readInt32();
+            void *output;
+            data.read(&output, sizeof(void *));
             reply->writeInt32( format(output) );
             return NO_ERROR;
         } break;
         case FRAME_COUNT: {
             CHECK_INTERFACE(IAudioFlinger, data, reply);
-            int output = data.readInt32();
+            void *output;
+            data.read(&output, sizeof(void *));
             reply->writeInt32( frameCount(output) );
             return NO_ERROR;
         } break;
         case LATENCY: {
             CHECK_INTERFACE(IAudioFlinger, data, reply);
-            int output = data.readInt32();
+            void *output;
+            data.read(&output, sizeof(void *));
             reply->writeInt32( latency(output) );
             return NO_ERROR;
         } break;
@@ -444,7 +555,10 @@
         case SET_STREAM_VOLUME: {
             CHECK_INTERFACE(IAudioFlinger, data, reply);
             int stream = data.readInt32();
-            reply->writeInt32( setStreamVolume(stream, data.readFloat()) );
+            float volume = data.readFloat();
+            void *output;
+            data.read(&output, sizeof(void *));
+            reply->writeInt32( setStreamVolume(stream, volume, output) );
             return NO_ERROR;
         } break;
         case SET_STREAM_MUTE: {
@@ -456,7 +570,9 @@
         case STREAM_VOLUME: {
             CHECK_INTERFACE(IAudioFlinger, data, reply);
             int stream = data.readInt32();
-            reply->writeFloat( streamVolume(stream) );
+            void *output;
+            data.read(&output, sizeof(void *));
+            reply->writeFloat( streamVolume(stream, output) );
             return NO_ERROR;
         } break;
         case STREAM_MUTE: {
@@ -465,31 +581,12 @@
             reply->writeInt32( streamMute(stream) );
             return NO_ERROR;
         } break;
-        case SET_ROUTING: {
-            CHECK_INTERFACE(IAudioFlinger, data, reply);
-            int mode = data.readInt32();
-            uint32_t routes = data.readInt32();
-            uint32_t mask = data.readInt32();
-            reply->writeInt32( setRouting(mode, routes, mask) );
-            return NO_ERROR;
-        } break;
-        case GET_ROUTING: {
-            CHECK_INTERFACE(IAudioFlinger, data, reply);
-            int mode = data.readInt32();
-            reply->writeInt32( getRouting(mode) );
-            return NO_ERROR;
-        } break;
         case SET_MODE: {
             CHECK_INTERFACE(IAudioFlinger, data, reply);
             int mode = data.readInt32();
             reply->writeInt32( setMode(mode) );
             return NO_ERROR;
         } break;
-        case GET_MODE: {
-            CHECK_INTERFACE(IAudioFlinger, data, reply);
-            reply->writeInt32( getMode() );
-            return NO_ERROR;
-        } break;
         case SET_MIC_MUTE: {
             CHECK_INTERFACE(IAudioFlinger, data, reply);
             int state = data.readInt32();
@@ -506,13 +603,23 @@
             reply->writeInt32( isMusicActive() );
             return NO_ERROR;
         } break;
-        case SET_PARAMETER: {
+        case SET_PARAMETERS: {
             CHECK_INTERFACE(IAudioFlinger, data, reply);
-            const char *key = data.readCString();
-            const char *value = data.readCString();
-            reply->writeInt32( setParameter(key, value) );
+            void *ioHandle;
+            data.read(&ioHandle, sizeof(void *));
+            String8 keyValuePairs(data.readString8());
+            reply->writeInt32(setParameters(ioHandle, keyValuePairs));
             return NO_ERROR;
-        } break;
+         } break;
+        case GET_PARAMETERS: {
+            CHECK_INTERFACE(IAudioFlinger, data, reply);
+            void *ioHandle;
+            data.read(&ioHandle, sizeof(void *));
+            String8 keys(data.readString8());
+            reply->writeString8(getParameters(ioHandle, keys));
+            return NO_ERROR;
+         } break;
+
         case REGISTER_CLIENT: {
             CHECK_INTERFACE(IAudioFlinger, data, reply);
             sp<IAudioFlingerClient> client = interface_cast<IAudioFlingerClient>(data.readStrongBinder());
@@ -527,14 +634,93 @@
             reply->writeInt32( getInputBufferSize(sampleRate, format, channelCount) );
             return NO_ERROR;
         } break;
-        case WAKE_UP: {
+        case OPEN_OUTPUT: {
             CHECK_INTERFACE(IAudioFlinger, data, reply);
-            wakeUp();
+            uint32_t devices = data.readInt32();
+            uint32_t samplingRate = data.readInt32();
+            uint32_t format = data.readInt32();
+            uint32_t channels = data.readInt32();
+            uint32_t latency = data.readInt32();
+            uint32_t flags = data.readInt32();
+            void *output = openOutput(&devices,
+                                     &samplingRate,
+                                     &format,
+                                     &channels,
+                                     &latency,
+                                     flags);
+            LOGV("OPEN_OUTPUT output, %p", output);
+            reply->write(&output, sizeof(void *));
+            reply->writeInt32(devices);
+            reply->writeInt32(samplingRate);
+            reply->writeInt32(format);
+            reply->writeInt32(channels);
+            reply->writeInt32(latency);
             return NO_ERROR;
         } break;
-        case IS_A2DP_ENABLED: {
+        case OPEN_DUPLICATE_OUTPUT: {
             CHECK_INTERFACE(IAudioFlinger, data, reply);
-            reply->writeInt32( (int)isA2dpEnabled() );
+            void *output1;
+            void *output2;
+            data.read(&output1, sizeof(void *));
+            data.read(&output2, sizeof(void *));
+            void *output = openDuplicateOutput(output1, output2);
+            reply->write(&output, sizeof(void *));
+            return NO_ERROR;
+        } break;
+        case CLOSE_OUTPUT: {
+            CHECK_INTERFACE(IAudioFlinger, data, reply);
+            void *output;
+            data.read(&output, sizeof(void *));
+            reply->writeInt32(closeOutput(output));
+            return NO_ERROR;
+        } break;
+        case SUSPEND_OUTPUT: {
+            CHECK_INTERFACE(IAudioFlinger, data, reply);
+            void *output;
+            data.read(&output, sizeof(void *));
+            reply->writeInt32(suspendOutput(output));
+            return NO_ERROR;
+        } break;
+        case RESTORE_OUTPUT: {
+            CHECK_INTERFACE(IAudioFlinger, data, reply);
+            void *output;
+            data.read(&output, sizeof(void *));
+            reply->writeInt32(restoreOutput(output));
+            return NO_ERROR;
+        } break;
+        case OPEN_INPUT: {
+            CHECK_INTERFACE(IAudioFlinger, data, reply);
+            uint32_t devices = data.readInt32();
+            uint32_t samplingRate = data.readInt32();
+            uint32_t format = data.readInt32();
+            uint32_t channels = data.readInt32();
+            uint32_t acoutics = data.readInt32();
+
+            void *input = openInput(&devices,
+                                     &samplingRate,
+                                     &format,
+                                     &channels,
+                                     acoutics);
+            reply->write(&input, sizeof(void *));
+            reply->writeInt32(devices);
+            reply->writeInt32(samplingRate);
+            reply->writeInt32(format);
+            reply->writeInt32(channels);
+            return NO_ERROR;
+        } break;
+        case CLOSE_INPUT: {
+            CHECK_INTERFACE(IAudioFlinger, data, reply);
+            void *input;
+            data.read(&input, sizeof(void *));
+            reply->writeInt32(closeInput(input));
+            return NO_ERROR;
+        } break;
+        case SET_STREAM_OUTPUT: {
+            CHECK_INTERFACE(IAudioFlinger, data, reply);
+            void *output;
+            uint32_t stream = data.readInt32();
+            data.read(&output, sizeof(void *));
+            reply->writeInt32(setStreamOutput(stream, output));
             return NO_ERROR;
         } break;
         default:
diff --git a/media/libmedia/IAudioFlingerClient.cpp b/media/libmedia/IAudioFlingerClient.cpp
index 75699b4..eaae977 100644
--- a/media/libmedia/IAudioFlingerClient.cpp
+++ b/media/libmedia/IAudioFlingerClient.cpp
@@ -23,11 +23,12 @@
 #include <binder/Parcel.h>
 
 #include <media/IAudioFlingerClient.h>
+#include <media/AudioSystem.h>
 
 namespace android {
 
 enum {
-    AUDIO_OUTPUT_CHANGED = IBinder::FIRST_CALL_TRANSACTION
+    IO_CONFIG_CHANGED = IBinder::FIRST_CALL_TRANSACTION
 };
 
 class BpAudioFlingerClient : public BpInterface<IAudioFlingerClient>
@@ -38,12 +39,25 @@
     {
     }
 
-    void a2dpEnabledChanged(bool enabled)
+    void ioConfigChanged(int event, void *param1, void *param2)
     {
         Parcel data, reply;
         data.writeInterfaceToken(IAudioFlingerClient::getInterfaceDescriptor());
-        data.writeInt32((int)enabled);
-        remote()->transact(AUDIO_OUTPUT_CHANGED, data, &reply, IBinder::FLAG_ONEWAY);
+        data.writeInt32(event);
+        data.write(&param1, sizeof(void *));
+        if (event == AudioSystem::STREAM_CONFIG_CHANGED) {
+            uint32_t stream = *(uint32_t *)param2;
+            LOGV("ioConfigChanged stream %d", stream);
+            data.writeInt32(stream);
+        } else if (event != AudioSystem::OUTPUT_CLOSED && event != AudioSystem::INPUT_CLOSED) {
+            AudioSystem::OutputDescriptor *desc = (AudioSystem::OutputDescriptor *)param2;
+            data.writeInt32(desc->samplingRate);
+            data.writeInt32(desc->format);
+            data.writeInt32(desc->channels);
+            data.writeInt32(desc->frameCount);
+            data.writeInt32(desc->latency);
+        }
+        remote()->transact(IO_CONFIG_CHANGED, data, &reply, IBinder::FLAG_ONEWAY);
     }
 };
 
@@ -55,10 +69,27 @@
     uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
 {
     switch(code) {
-        case AUDIO_OUTPUT_CHANGED: {
+    case IO_CONFIG_CHANGED: {
             CHECK_INTERFACE(IAudioFlingerClient, data, reply);
-            bool enabled = (bool)data.readInt32();
-            a2dpEnabledChanged(enabled);
+            int event = data.readInt32();
+            void *param1;
+            void *param2 = 0;
+            AudioSystem::OutputDescriptor desc;
+            uint32_t stream;
+            data.read(&param1, sizeof(void *));
+            if (event == AudioSystem::STREAM_CONFIG_CHANGED) {
+                stream = data.readInt32();
+                param2 = &stream;
+                LOGV("STREAM_CONFIG_CHANGED stream %d", stream);
+            } else if (event != AudioSystem::OUTPUT_CLOSED && event != AudioSystem::INPUT_CLOSED) {
+                desc.samplingRate = data.readInt32();
+                desc.format = data.readInt32();
+                desc.channels = data.readInt32();
+                desc.frameCount = data.readInt32();
+                desc.latency = data.readInt32();
+                param2 = &desc;
+            }
+            ioConfigChanged(event, param1, param2);
             return NO_ERROR;
         } break;
         default:
diff --git a/media/libmedia/IAudioPolicyService.cpp b/media/libmedia/IAudioPolicyService.cpp
new file mode 100644
index 0000000..0d8a329
--- /dev/null
+++ b/media/libmedia/IAudioPolicyService.cpp
@@ -0,0 +1,423 @@
+/*
+**
+** Copyright 2009, 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.
+*/
+
+#define LOG_TAG "IAudioPolicyService"
+#include <utils/Log.h>
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <binder/Parcel.h>
+
+#include <media/IAudioPolicyService.h>
+
+namespace android {
+
+enum {
+    SET_DEVICE_CONNECTION_STATE = IBinder::FIRST_CALL_TRANSACTION,
+    GET_DEVICE_CONNECTION_STATE,
+    SET_PHONE_STATE,
+    SET_RINGER_MODE,
+    SET_FORCE_USE,
+    GET_FORCE_USE,
+    GET_OUTPUT,
+    START_OUTPUT,
+    STOP_OUTPUT,
+    RELEASE_OUTPUT,
+    GET_INPUT,
+    START_INPUT,
+    STOP_INPUT,
+    RELEASE_INPUT,
+    INIT_STREAM_VOLUME,
+    SET_STREAM_VOLUME,
+    GET_STREAM_VOLUME
+};
+
+class BpAudioPolicyService : public BpInterface<IAudioPolicyService>
+{
+public:
+    BpAudioPolicyService(const sp<IBinder>& impl)
+        : BpInterface<IAudioPolicyService>(impl)
+    {
+    }
+
+    virtual status_t setDeviceConnectionState(
+                                    AudioSystem::audio_devices device,
+                                    AudioSystem::device_connection_state state,
+                                    const char *device_address)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+        data.writeInt32(static_cast <uint32_t>(device));
+        data.writeInt32(static_cast <uint32_t>(state));
+        data.writeCString(device_address);
+        remote()->transact(SET_DEVICE_CONNECTION_STATE, data, &reply);
+        return static_cast <status_t> (reply.readInt32());
+    }
+
+    virtual AudioSystem::device_connection_state getDeviceConnectionState(
+                                    AudioSystem::audio_devices device,
+                                    const char *device_address)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+        data.writeInt32(static_cast <uint32_t>(device));
+        data.writeCString(device_address);
+        remote()->transact(GET_DEVICE_CONNECTION_STATE, data, &reply);
+        return static_cast <AudioSystem::device_connection_state>(reply.readInt32());
+    }
+
+    virtual status_t setPhoneState(int state)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+        data.writeInt32(state);
+        remote()->transact(SET_PHONE_STATE, data, &reply);
+        return static_cast <status_t> (reply.readInt32());
+    }
+
+    virtual status_t setRingerMode(uint32_t mode, uint32_t mask)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+        data.writeInt32(mode);
+        data.writeInt32(mask);
+        remote()->transact(SET_RINGER_MODE, data, &reply);
+        return static_cast <status_t> (reply.readInt32());
+    }
+
+    virtual status_t setForceUse(AudioSystem::force_use usage, AudioSystem::forced_config config)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+        data.writeInt32(static_cast <uint32_t>(usage));
+        data.writeInt32(static_cast <uint32_t>(config));
+        remote()->transact(SET_FORCE_USE, data, &reply);
+        return static_cast <status_t> (reply.readInt32());
+    }
+
+    virtual AudioSystem::forced_config getForceUse(AudioSystem::force_use usage)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+        data.writeInt32(static_cast <uint32_t>(usage));
+        remote()->transact(GET_FORCE_USE, data, &reply);
+        return static_cast <AudioSystem::forced_config> (reply.readInt32());
+    }
+
+    virtual audio_io_handle_t getOutput(
+                                        AudioSystem::stream_type stream,
+                                        uint32_t samplingRate,
+                                        uint32_t format,
+                                        uint32_t channels,
+                                        AudioSystem::output_flags flags)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+        data.writeInt32(static_cast <uint32_t>(stream));
+        data.writeInt32(samplingRate);
+        data.writeInt32(static_cast <uint32_t>(format));
+        data.writeInt32(channels);
+        data.writeInt32(static_cast <uint32_t>(flags));
+        remote()->transact(GET_OUTPUT, data, &reply);
+        audio_io_handle_t output;
+        reply.read(&output, sizeof(audio_io_handle_t));
+        return output;
+    }
+
+    virtual status_t startOutput(audio_io_handle_t output, AudioSystem::stream_type stream)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+        data.write(&output, sizeof(audio_io_handle_t));
+        data.writeInt32(stream);
+        remote()->transact(START_OUTPUT, data, &reply);
+        return static_cast <status_t> (reply.readInt32());
+    }
+
+    virtual status_t stopOutput(audio_io_handle_t output, AudioSystem::stream_type stream)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+        data.write(&output, sizeof(audio_io_handle_t));
+        data.writeInt32(stream);
+        remote()->transact(STOP_OUTPUT, data, &reply);
+        return static_cast <status_t> (reply.readInt32());
+    }
+
+    virtual void releaseOutput(audio_io_handle_t output)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+        data.write(&output, sizeof(audio_io_handle_t));
+        remote()->transact(RELEASE_OUTPUT, data, &reply);
+    }
+
+    virtual audio_io_handle_t getInput(
+                                    int inputSource,
+                                    uint32_t samplingRate,
+                                    uint32_t format,
+                                    uint32_t channels,
+                                    AudioSystem::audio_in_acoustics acoustics)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+        data.writeInt32(inputSource);
+        data.writeInt32(samplingRate);
+        data.writeInt32(static_cast <uint32_t>(format));
+        data.writeInt32(channels);
+        data.writeInt32(static_cast <uint32_t>(acoustics));
+        remote()->transact(GET_INPUT, data, &reply);
+        audio_io_handle_t input;
+        reply.read(&input, sizeof(audio_io_handle_t));
+        return input;
+    }
+
+    virtual status_t startInput(audio_io_handle_t input)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+        data.write(&input, sizeof(audio_io_handle_t));
+        remote()->transact(START_INPUT, data, &reply);
+        return static_cast <status_t> (reply.readInt32());
+    }
+
+    virtual status_t stopInput(audio_io_handle_t input)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+        data.write(&input, sizeof(audio_io_handle_t));
+        remote()->transact(STOP_INPUT, data, &reply);
+        return static_cast <status_t> (reply.readInt32());
+    }
+
+    virtual void releaseInput(audio_io_handle_t input)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+        data.write(&input, sizeof(audio_io_handle_t));
+        remote()->transact(RELEASE_INPUT, data, &reply);
+    }
+
+    virtual status_t initStreamVolume(AudioSystem::stream_type stream,
+                                    int indexMin,
+                                    int indexMax)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+        data.writeInt32(static_cast <uint32_t>(stream));
+        data.writeInt32(indexMin);
+        data.writeInt32(indexMax);
+        remote()->transact(INIT_STREAM_VOLUME, data, &reply);
+        return static_cast <status_t> (reply.readInt32());
+    }
+
+    virtual status_t setStreamVolumeIndex(AudioSystem::stream_type stream, int index)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+        data.writeInt32(static_cast <uint32_t>(stream));
+        data.writeInt32(index);
+        remote()->transact(SET_STREAM_VOLUME, data, &reply);
+        return static_cast <status_t> (reply.readInt32());
+    }
+
+    virtual status_t getStreamVolumeIndex(AudioSystem::stream_type stream, int *index)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+        data.writeInt32(static_cast <uint32_t>(stream));
+        remote()->transact(GET_STREAM_VOLUME, data, &reply);
+        int lIndex = reply.readInt32();
+        if (index) *index = lIndex;
+        return static_cast <status_t> (reply.readInt32());
+    }
+};
+
+IMPLEMENT_META_INTERFACE(AudioPolicyService, "android.media.IAudioPolicyService");
+
+// ----------------------------------------------------------------------
+
+
+status_t BnAudioPolicyService::onTransact(
+    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+    switch(code) {
+        case SET_DEVICE_CONNECTION_STATE: {
+            CHECK_INTERFACE(IAudioPolicyService, data, reply);
+            AudioSystem::audio_devices device = static_cast <AudioSystem::audio_devices>(data.readInt32());
+            AudioSystem::device_connection_state state = static_cast <AudioSystem::device_connection_state>(data.readInt32());
+            const char *device_address = data.readCString();
+            reply->writeInt32(static_cast <uint32_t>(setDeviceConnectionState(device, state, device_address)));
+            return NO_ERROR;
+        } break;
+
+        case GET_DEVICE_CONNECTION_STATE: {
+            CHECK_INTERFACE(IAudioPolicyService, data, reply);
+            AudioSystem::audio_devices device = static_cast <AudioSystem::audio_devices>(data.readInt32());
+            const char *device_address = data.readCString();
+            reply->writeInt32(static_cast <uint32_t>(getDeviceConnectionState(device, device_address)));
+            return NO_ERROR;
+        } break;
+
+        case SET_PHONE_STATE: {
+            CHECK_INTERFACE(IAudioPolicyService, data, reply);
+            reply->writeInt32(static_cast <uint32_t>(setPhoneState(data.readInt32())));
+            return NO_ERROR;
+        } break;
+
+        case SET_RINGER_MODE: {
+            CHECK_INTERFACE(IAudioPolicyService, data, reply);
+            uint32_t mode = data.readInt32();
+            uint32_t mask = data.readInt32();
+            reply->writeInt32(static_cast <uint32_t>(setRingerMode(mode, mask)));
+            return NO_ERROR;
+        } break;
+
+        case SET_FORCE_USE: {
+            CHECK_INTERFACE(IAudioPolicyService, data, reply);
+            AudioSystem::force_use usage = static_cast <AudioSystem::force_use>(data.readInt32());
+            AudioSystem::forced_config config = static_cast <AudioSystem::forced_config>(data.readInt32());
+            reply->writeInt32(static_cast <uint32_t>(setForceUse(usage, config)));
+            return NO_ERROR;
+        } break;
+
+        case GET_FORCE_USE: {
+            CHECK_INTERFACE(IAudioPolicyService, data, reply);
+            AudioSystem::force_use usage = static_cast <AudioSystem::force_use>(data.readInt32());
+            reply->writeInt32(static_cast <uint32_t>(getForceUse(usage)));
+            return NO_ERROR;
+        } break;
+
+        case GET_OUTPUT: {
+            CHECK_INTERFACE(IAudioPolicyService, data, reply);
+            AudioSystem::stream_type stream = static_cast <AudioSystem::stream_type>(data.readInt32());
+            uint32_t samplingRate = data.readInt32();
+            uint32_t format = data.readInt32();
+            uint32_t channels = data.readInt32();
+            AudioSystem::output_flags flags = static_cast <AudioSystem::output_flags>(data.readInt32());
+
+            audio_io_handle_t output = getOutput(stream,
+                                                 samplingRate,
+                                                 format,
+                                                 channels,
+                                                 flags);
+            reply->write(&output, sizeof(audio_io_handle_t));
+            return NO_ERROR;
+        } break;
+
+        case START_OUTPUT: {
+            CHECK_INTERFACE(IAudioPolicyService, data, reply);
+            audio_io_handle_t output;
+            data.read(&output, sizeof(audio_io_handle_t));
+            uint32_t stream = data.readInt32();
+            reply->writeInt32(static_cast <uint32_t>(startOutput(output, (AudioSystem::stream_type)stream)));
+            return NO_ERROR;
+        } break;
+
+        case STOP_OUTPUT: {
+            CHECK_INTERFACE(IAudioPolicyService, data, reply);
+            audio_io_handle_t output;
+            data.read(&output, sizeof(audio_io_handle_t));
+            uint32_t stream = data.readInt32();
+            reply->writeInt32(static_cast <uint32_t>(stopOutput(output, (AudioSystem::stream_type)stream)));
+            return NO_ERROR;
+        } break;
+
+        case RELEASE_OUTPUT: {
+            CHECK_INTERFACE(IAudioPolicyService, data, reply);
+            audio_io_handle_t output;
+            data.read(&output, sizeof(audio_io_handle_t));
+            releaseOutput(output);
+            return NO_ERROR;
+        } break;
+
+        case GET_INPUT: {
+            CHECK_INTERFACE(IAudioPolicyService, data, reply);
+            int inputSource = data.readInt32();
+            uint32_t samplingRate = data.readInt32();
+            uint32_t format = data.readInt32();
+            uint32_t channels = data.readInt32();
+            AudioSystem::audio_in_acoustics acoustics = static_cast <AudioSystem::audio_in_acoustics>(data.readInt32());
+            audio_io_handle_t input = getInput(inputSource,
+                                               samplingRate,
+                                               format,
+                                               channels,
+                                               acoustics);
+            reply->write(&input, sizeof(audio_io_handle_t));
+            return NO_ERROR;
+        } break;
+
+        case START_INPUT: {
+            CHECK_INTERFACE(IAudioPolicyService, data, reply);
+            audio_io_handle_t input;
+            data.read(&input, sizeof(audio_io_handle_t));
+            reply->writeInt32(static_cast <uint32_t>(startInput(input)));
+            return NO_ERROR;
+        } break;
+
+        case STOP_INPUT: {
+            CHECK_INTERFACE(IAudioPolicyService, data, reply);
+            audio_io_handle_t input;
+            data.read(&input, sizeof(audio_io_handle_t));
+            reply->writeInt32(static_cast <uint32_t>(stopInput(input)));
+            return NO_ERROR;
+        } break;
+
+        case RELEASE_INPUT: {
+            CHECK_INTERFACE(IAudioPolicyService, data, reply);
+            audio_io_handle_t input;
+            data.read(&input, sizeof(audio_io_handle_t));
+            releaseInput(input);
+            return NO_ERROR;
+        } break;
+
+        case INIT_STREAM_VOLUME: {
+            CHECK_INTERFACE(IAudioPolicyService, data, reply);
+            AudioSystem::stream_type stream = static_cast <AudioSystem::stream_type>(data.readInt32());
+            int indexMin = data.readInt32();
+            int indexMax = data.readInt32();
+            reply->writeInt32(static_cast <uint32_t>(initStreamVolume(stream, indexMin,indexMax)));
+            return NO_ERROR;
+        } break;
+
+        case SET_STREAM_VOLUME: {
+            CHECK_INTERFACE(IAudioPolicyService, data, reply);
+            AudioSystem::stream_type stream = static_cast <AudioSystem::stream_type>(data.readInt32());
+            int index = data.readInt32();
+            reply->writeInt32(static_cast <uint32_t>(setStreamVolumeIndex(stream, index)));
+            return NO_ERROR;
+        } break;
+
+        case GET_STREAM_VOLUME: {
+            CHECK_INTERFACE(IAudioPolicyService, data, reply);
+            AudioSystem::stream_type stream = static_cast <AudioSystem::stream_type>(data.readInt32());
+            int index;
+            status_t status = getStreamVolumeIndex(stream, &index);
+            reply->writeInt32(index);
+            reply->writeInt32(static_cast <uint32_t>(status));
+            return NO_ERROR;
+        } break;
+
+        default:
+            return BBinder::onTransact(code, data, reply, flags);
+    }
+}
+
+// ----------------------------------------------------------------------------
+
+}; // namespace android
diff --git a/media/libmedia/JetPlayer.cpp b/media/libmedia/JetPlayer.cpp
index 586aacb..ee9e1d8 100644
--- a/media/libmedia/JetPlayer.cpp
+++ b/media/libmedia/JetPlayer.cpp
@@ -99,7 +99,7 @@
     mAudioTrack->set(AudioSystem::MUSIC,  //TODO parametrize this
             pLibConfig->sampleRate,
             1, // format = PCM 16bits per sample,
-            pLibConfig->numChannels,
+            (pLibConfig->numChannels == 2) ? AudioSystem::CHANNEL_OUT_STEREO : AudioSystem::CHANNEL_OUT_MONO,
             mTrackBufferSize,
             0);
 
diff --git a/media/libmedia/ToneGenerator.cpp b/media/libmedia/ToneGenerator.cpp
index 5435da7..3ea64ae 100644
--- a/media/libmedia/ToneGenerator.cpp
+++ b/media/libmedia/ToneGenerator.cpp
@@ -1001,7 +1001,7 @@
 
    // Open audio track in mono, PCM 16bit, default sampling rate, default buffer size
     mpAudioTrack
-            = new AudioTrack(mStreamType, 0, AudioSystem::PCM_16_BIT, 1, 0, 0, audioCallback, this, 0);
+            = new AudioTrack(mStreamType, 0, AudioSystem::PCM_16_BIT, AudioSystem::CHANNEL_OUT_MONO, 0, 0, audioCallback, this, 0);
 
     if (mpAudioTrack == 0) {
         LOGE("AudioTrack allocation failed");