Squashed commit of audio changes from CodeAurora

libstagefright: Add QC specific media format

- Add QC specific media extensions
- Add QC specific media definitions

Change-Id: I7dca90be3b977701d9537f5e017117790a030f1f

audio: Compile AudioParameter as shared library

- AudioParameter as shared lib is needed by BT
  support in WFD source.

Change-Id: I464b428ace0cbb57ce6bf7bf3b57d51a7d56f032

libstagefright: Send flush on both i/p and o/p ports together

- ANR occurs in music due to race condition in OMX component if
  flush is issued separately for i/p and o/p ports as DSP only
  handles simultaneous flush on i/p and o/p ports.

Change-Id: I5b16cd5a9b57c857dc8bed489d2663b8f54769e3

libstagefright: Enable extended A\V format

- Add new files to support extended A\V format

Change-Id: I1e61d78d35b868d55fd8e99f95de8cab9c465db4

libstagefright: Framework to plug-in propritory parser

- Extend the current framework to plug-in propritory
  parser

Change-Id: Ia586a3048420ddf1515261f20035589447263b7b

audio: add support for QCOM audio formats

- Add support for EVRC, QCELP, and WMA formats.

Change-Id: Iaf80f982fc8b08617132dbd7d524a1748866745c

frameworks/av: Support Tunnel Playback

- Implement DirectTrack and DirectTrackClient
- DirectTrack exposes API to client so it can create a direct
  output.
- DirectTrackClient allows notifications to be sent to the
  client from DirectTrack
- DirectTrack is being used for Tunnel Audio

Change-Id: I2fbb18a781d8e44b8d65da9a357f6e39375f063a

frameworks/av: Support LPA Playback

Add support to enable Playback in LPA mode

Change-Id: I1b8ac4904f4735017d62f3757ede7bbb56e62fd3

audio: Send correct channel mask in voice call recording.

-Using popCount function to get channel count gives incorrect value on
voice call recording.
-Only STEREO and MONO bits to be considered to count
channels on input

Change-Id: I04c2c802422e868bdba0538ff8623dbf9eb659fe

libstagefright: Thumbnail mode initial commit

- use sync frame decoding mode when kClientNeedsFrameBuffer
  is set for hardware decoders
- hardware decoder will only expect I frames, OMXCodec will
  set EOS on first ETB to stop more frames from being pulled
- skip EOS check on FTB so that the first frame will be
  handled

Change-Id: I0e8974e088fdcc468e27764861c128cfe291499f

audio: Add support for QCOM's VOIP solution

Change-Id: I1150f536fa204b535ca4019fdaa84f33f4695d93

audio: define QCOM audio parameters

- Define QCOM audio paramters for FM, VOIP,
  fluence, SSR, and A2DP

Change-Id: I29d02e37685846f6d4f00dee02e2726b015eaae7

Add ifdefs for QCOM enhanced features

Change-Id: Ic8e5fe6ecc058466ced71030883b1af6c2bc055c
diff --git a/media/libmedia/Android.mk b/media/libmedia/Android.mk
index 54666fb..69361fa 100644
--- a/media/libmedia/Android.mk
+++ b/media/libmedia/Android.mk
@@ -11,6 +11,17 @@
 
 include $(CLEAR_VARS)
 
+ifeq ($(BOARD_USES_QCOM_HARDWARE),true)
+LOCAL_SRC_FILES:= AudioParameter.cpp
+LOCAL_MODULE:= libaudioparameter
+LOCAL_MODULE_TAGS := optional
+LOCAL_SHARED_LIBRARIES := libutils
+
+include $(BUILD_SHARED_LIBRARY)
+
+include $(CLEAR_VARS)
+endif
+
 LOCAL_SRC_FILES:= \
     AudioTrack.cpp \
     IAudioFlinger.cpp \
@@ -51,6 +62,16 @@
     SoundPool.cpp \
     SoundPoolThread.cpp
 
+ifeq ($(BOARD_USES_QCOM_HARDWARE),true)
+LOCAL_SRC_FILES += \
+    IDirectTrack.cpp \
+    IDirectTrackClient.cpp
+
+ifeq ($(TARGET_QCOM_AUDIO_VARIANT),caf)
+LOCAL_CFLAGS += -DQCOM_ENHANCED_AUDIO
+endif
+endif
+
 LOCAL_SHARED_LIBRARIES := \
 	libui libcutils libutils libbinder libsonivox libicuuc libexpat \
         libcamera_client libstagefright_foundation \
diff --git a/media/libmedia/AudioParameter.cpp b/media/libmedia/AudioParameter.cpp
index e3fea77..fbb34f4 100644
--- a/media/libmedia/AudioParameter.cpp
+++ b/media/libmedia/AudioParameter.cpp
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 2006-2011 The Android Open Source Project
+ * Copyright (c) 2012, The Linux Foundation. All rights reserved.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -32,6 +33,13 @@
 const char * const AudioParameter::keyFrameCount = AUDIO_PARAMETER_STREAM_FRAME_COUNT;
 const char * const AudioParameter::keyInputSource = AUDIO_PARAMETER_STREAM_INPUT_SOURCE;
 const char * const AudioParameter::keyScreenState = AUDIO_PARAMETER_KEY_SCREEN_STATE;
+#ifdef QCOM_HARDWARE
+const char * const AudioParameter::keyHandleFm = AUDIO_PARAMETER_KEY_HANDLE_FM;
+const char * const AudioParameter::keyVoipCheck = AUDIO_PARAMETER_KEY_VOIP_CHECK;
+const char * const AudioParameter::keyFluenceType = AUDIO_PARAMETER_KEY_FLUENCE_TYPE;
+const char * const AudioParameter::keySSR = AUDIO_PARAMETER_KEY_SSR;
+const char * const AudioParameter::keyHandleA2dpDevice = AUDIO_PARAMETER_KEY_HANDLE_A2DP_DEVICE;
+#endif
 
 AudioParameter::AudioParameter(const String8& keyValuePairs)
 {
diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp
index 8ea6306..ce03754 100644
--- a/media/libmedia/AudioRecord.cpp
+++ b/media/libmedia/AudioRecord.cpp
@@ -1,6 +1,7 @@
 /*
 **
 ** Copyright 2008, The Android Open Source Project
+** Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
 **
 ** Licensed under the Apache License, Version 2.0 (the "License");
 ** you may not use this file except in compliance with the License.
@@ -156,7 +157,11 @@
         return BAD_VALUE;
     }
 
+#ifdef QCOM_HARDWARE
+    int channelCount = popcount((channelMask) & (AUDIO_CHANNEL_IN_STEREO | AUDIO_CHANNEL_IN_MONO | AUDIO_CHANNEL_IN_5POINT1));
+#else
     int channelCount = popcount(channelMask);
+#endif
 
     if (sessionId == 0 ) {
         mSessionId = AudioSystem::newAudioSessionId();
diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp
index fa52fa9..a2172c9 100644
--- a/media/libmedia/AudioTrack.cpp
+++ b/media/libmedia/AudioTrack.cpp
@@ -2,6 +2,10 @@
 **
 ** Copyright 2007, The Android Open Source Project
 **
+** Copyright (c) 2012, The Linux Foundation. All rights reserved.
+** Not a Contribution, Apache license notifications and license are retained
+** for attribution purposes only.
+
 ** 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
@@ -96,6 +100,10 @@
       mIsTimed(false),
       mPreviousPriority(ANDROID_PRIORITY_NORMAL),
       mPreviousSchedulingGroup(SP_DEFAULT)
+#ifdef QCOM_HARDWARE
+      ,mAudioFlinger(NULL),
+      mObserver(NULL)
+#endif
 {
 }
 
@@ -114,6 +122,10 @@
       mIsTimed(false),
       mPreviousPriority(ANDROID_PRIORITY_NORMAL),
       mPreviousSchedulingGroup(SP_DEFAULT)
+#ifdef QCOM_HARDWARE
+      ,mAudioFlinger(NULL),
+      mObserver(NULL)
+#endif
 {
     mStatus = set(streamType, sampleRate, format, channelMask,
             frameCount, flags, cbf, user, notificationFrames,
@@ -135,6 +147,10 @@
     : mStatus(NO_INIT),
       mIsTimed(false),
       mPreviousPriority(ANDROID_PRIORITY_NORMAL), mPreviousSchedulingGroup(SP_DEFAULT)
+#ifdef QCOM_HARDWARE
+      ,mAudioFlinger(NULL),
+      mObserver(NULL)
+#endif
 {
     mStatus = set((audio_stream_type_t)streamType, sampleRate, (audio_format_t)format,
             (audio_channel_mask_t) channelMask,
@@ -157,6 +173,10 @@
       mIsTimed(false),
       mPreviousPriority(ANDROID_PRIORITY_NORMAL),
       mPreviousSchedulingGroup(SP_DEFAULT)
+#ifdef QCOM_HARDWARE
+      ,mAudioFlinger(NULL),
+      mObserver(NULL)
+#endif
 {
     mStatus = set(streamType, sampleRate, format, channelMask,
             0 /*frameCount*/, flags, cbf, user, notificationFrames,
@@ -177,9 +197,22 @@
             mAudioTrackThread->requestExitAndWait();
             mAudioTrackThread.clear();
         }
+#ifdef QCOM_HARDWARE
+        if (mAudioTrack != 0) {
+            mAudioTrack.clear();
+            AudioSystem::releaseAudioSessionId(mSessionId);
+        }
+
+        if (mDirectTrack != 0) {
+            mDirectTrack.clear();
+        }
+#else
         mAudioTrack.clear();
+#endif
         IPCThreadState::self()->flushCommands();
+#ifndef QCOM_HARDWARE
         AudioSystem::releaseAudioSessionId(mSessionId);
+#endif
     }
 }
 
@@ -252,12 +285,24 @@
         flags = (audio_output_flags_t)(flags &~AUDIO_OUTPUT_FLAG_DEEP_BUFFER);
     }
 
+#ifdef QCOM_ENHANCED_AUDIO
+    if ((streamType == AUDIO_STREAM_VOICE_CALL)
+         && (channelMask == AUDIO_CHANNEL_OUT_MONO)
+         && ((sampleRate == 8000 || sampleRate == 16000)))
+    {
+        ALOGD("Turn on Direct Output for VOIP RX");
+        flags = (audio_output_flags_t)(flags | AUDIO_OUTPUT_FLAG_VOIP_RX|AUDIO_OUTPUT_FLAG_DIRECT);
+    }
+#endif
+
     if (!audio_is_output_channel(channelMask)) {
         ALOGE("Invalid channel mask %#x", channelMask);
         return BAD_VALUE;
     }
     uint32_t channelCount = popcount(channelMask);
 
+    ALOGV("AudioTrack getOutput streamType %d, sampleRate %d, format %d, channelMask %d, flags %x",
+           streamType, sampleRate, format, channelMask, flags);
     audio_io_handle_t output = AudioSystem::getOutput(
                                     streamType,
                                     sampleRate, format, channelMask,
@@ -278,46 +323,86 @@
     mFlags = flags;
     mCbf = cbf;
 
-    if (cbf != NULL) {
-        mAudioTrackThread = new AudioTrackThread(*this, threadCanCallJava);
-        mAudioTrackThread->run("AudioTrack", ANDROID_PRIORITY_AUDIO, 0 /*stack*/);
-    }
-
-    // create the IAudioTrack
-    status_t status = createTrack_l(streamType,
-                                  sampleRate,
-                                  format,
-                                  channelMask,
-                                  frameCount,
-                                  flags,
-                                  sharedBuffer,
-                                  output);
-
-    if (status != NO_ERROR) {
-        if (mAudioTrackThread != 0) {
-            mAudioTrackThread->requestExit();
-            mAudioTrackThread.clear();
+#ifdef QCOM_HARDWARE
+    if (flags & AUDIO_OUTPUT_FLAG_LPA || flags & AUDIO_OUTPUT_FLAG_TUNNEL) {
+        ALOGV("Creating Direct Track");
+        const sp<IAudioFlinger>& audioFlinger = AudioSystem::get_audio_flinger();
+        if (audioFlinger == 0) {
+            ALOGE("Could not get audioflinger");
+            return NO_INIT;
         }
-        return status;
+        mAudioFlinger = audioFlinger;
+        status_t status = NO_ERROR;
+        mAudioDirectOutput = output;
+        mDirectTrack = audioFlinger->createDirectTrack( getpid(),
+                                                        sampleRate,
+                                                        channelMask,
+                                                        mAudioDirectOutput,
+                                                        &mSessionId,
+                                                        this,
+                                                        streamType,
+                                                        &status);
+        if(status != NO_ERROR) {
+            ALOGE("createDirectTrack returned with status %d", status);
+            return status;
+        }
+        mAudioTrack = NULL;
+        mSharedBuffer = NULL;
     }
+    else {
+#endif
+        if (cbf != NULL) {
+            mAudioTrackThread = new AudioTrackThread(*this, threadCanCallJava);
+            mAudioTrackThread->run("AudioTrack", ANDROID_PRIORITY_AUDIO, 0 /*stack*/);
+        }
+        // create the IAudioTrack
+        status_t status = createTrack_l(streamType,
+                                      sampleRate,
+                                      format,
+                                      channelMask,
+                                      frameCount,
+                                      flags,
+                                      sharedBuffer,
+                                      output);
 
+        if (status != NO_ERROR) {
+            if (mAudioTrackThread != 0) {
+                mAudioTrackThread->requestExit();
+                mAudioTrackThread.clear();
+            }
+            return status;
+        }
+#ifdef QCOM_HARDWARE
+        AudioSystem::acquireAudioSessionId(mSessionId);
+        mAudioDirectOutput = -1;
+        mDirectTrack = NULL;
+        mSharedBuffer = sharedBuffer;
+    }
+    mUserData = user;
+#endif
     mStatus = NO_ERROR;
 
     mStreamType = streamType;
     mFormat = format;
     mChannelMask = channelMask;
     mChannelCount = channelCount;
-    mSharedBuffer = sharedBuffer;
+
     mMuted = false;
     mActive = false;
-    mUserData = user;
+
     mLoopCount = 0;
     mMarkerPosition = 0;
     mMarkerReached = false;
     mNewPosition = 0;
     mUpdatePeriod = 0;
     mFlushed = false;
+
+#ifndef QCOM_HARDWARE
+    mSharedBuffer = sharedBuffer;
+    mUserData = user;
     AudioSystem::acquireAudioSessionId(mSessionId);
+#endif
+
     mRestoreStatus = NO_ERROR;
     return NO_ERROR;
 }
@@ -331,6 +416,11 @@
 
 uint32_t AudioTrack::latency() const
 {
+#ifdef QCOM_HARDWARE
+    if(mAudioDirectOutput != -1) {
+        return mAudioFlinger->latency(mAudioDirectOutput);
+    }
+#endif
     return mLatency;
 }
 
@@ -351,6 +441,11 @@
 
 uint32_t AudioTrack::frameCount() const
 {
+#ifdef QCOM_HARDWARE
+    if(mAudioDirectOutput != -1) {
+        return mAudioFlinger->frameCount(mAudioDirectOutput);
+    }
+#endif
     return mCblk->frameCount;
 }
 
@@ -372,6 +467,16 @@
 
 void AudioTrack::start()
 {
+#ifdef QCOM_HARDWARE
+    if (mDirectTrack != NULL) {
+        if(mActive == 0) {
+            mActive = 1;
+            mDirectTrack->start();
+        }
+        return;
+    }
+#endif
+
     sp<AudioTrackThread> t = mAudioTrackThread;
 
     ALOGV("start %p", this);
@@ -436,26 +541,35 @@
 
     AutoMutex lock(mLock);
     if (mActive) {
-        mActive = false;
-        mCblk->cv.signal();
-        mAudioTrack->stop();
-        // Cancel loops (If we are in the middle of a loop, playback
-        // would not stop until loopCount reaches 0).
-        setLoop_l(0, 0, 0);
-        // the playback head position will reset to 0, so if a marker is set, we need
-        // to activate it again
-        mMarkerReached = false;
-        // Force flush if a shared buffer is used otherwise audioflinger
-        // will not stop before end of buffer is reached.
-        if (mSharedBuffer != 0) {
-            flush_l();
+#ifdef QCOM_HARDWARE
+        if(mDirectTrack != NULL) {
+            mActive = false;
+            mDirectTrack->stop();
+        } else if (mAudioTrack != NULL) {
+#endif
+            mActive = false;
+            mCblk->cv.signal();
+            mAudioTrack->stop();
+            // Cancel loops (If we are in the middle of a loop, playback
+            // would not stop until loopCount reaches 0).
+            setLoop_l(0, 0, 0);
+            // the playback head position will reset to 0, so if a marker is set, we need
+            // to activate it again
+            mMarkerReached = false;
+            // Force flush if a shared buffer is used otherwise audioflinger
+            // will not stop before end of buffer is reached.
+            if (mSharedBuffer != 0) {
+                flush_l();
+            }
+            if (t != 0) {
+                t->pause();
+            } else {
+                setpriority(PRIO_PROCESS, 0, mPreviousPriority);
+                set_sched_policy(0, mPreviousSchedulingGroup);
+            }
+#ifdef QCOM_HARDWARE
         }
-        if (t != 0) {
-            t->pause();
-        } else {
-            setpriority(PRIO_PROCESS, 0, mPreviousPriority);
-            set_sched_policy(0, mPreviousSchedulingGroup);
-        }
+#endif
     }
 
 }
@@ -469,7 +583,12 @@
 void AudioTrack::flush()
 {
     AutoMutex lock(mLock);
-    flush_l();
+#ifdef QCOM_HARDWARE
+    if(mDirectTrack != NULL) {
+        mDirectTrack->flush();
+    } else
+#endif
+        flush_l();
 }
 
 // must be called with mLock held
@@ -497,14 +616,28 @@
     AutoMutex lock(mLock);
     if (mActive) {
         mActive = false;
-        mCblk->cv.signal();
-        mAudioTrack->pause();
+#ifdef QCOM_HARDWARE
+        if(mDirectTrack != NULL) {
+            ALOGV("mDirectTrack pause");
+            mDirectTrack->pause();
+        } else {
+#endif
+            mCblk->cv.signal();
+            mAudioTrack->pause();
+#ifdef QCOM_HARDWARE
+        }
+#endif
     }
 }
 
 void AudioTrack::mute(bool e)
 {
-    mAudioTrack->mute(e);
+#ifdef QCOM_HARDWARE
+    if(mDirectTrack != NULL) {
+        mDirectTrack->mute(e);
+    } else
+#endif
+        mAudioTrack->mute(e);
     mMuted = e;
 }
 
@@ -522,8 +655,13 @@
     AutoMutex lock(mLock);
     mVolume[LEFT] = left;
     mVolume[RIGHT] = right;
-
-    mCblk->setVolumeLR((uint32_t(uint16_t(right * 0x1000)) << 16) | uint16_t(left * 0x1000));
+#ifdef QCOM_HARDWARE
+    if(mDirectTrack != NULL) {
+        ALOGV("mDirectTrack->setVolume(left = %f , right = %f)", left,right);
+        mDirectTrack->setVolume(left, right);
+    } else
+#endif
+        mCblk->setVolumeLR((uint32_t(uint16_t(right * 0x1000)) << 16) | uint16_t(left * 0x1000));
 
     return NO_ERROR;
 }
@@ -540,6 +678,11 @@
 
 status_t AudioTrack::setAuxEffectSendLevel(float level)
 {
+#ifdef QCOM_HARDWARE
+    if (mDirectTrack != NULL) {
+        return NO_ERROR;
+    }
+#endif
     ALOGV("setAuxEffectSendLevel(%f)", level);
     if (level < 0.0f || level > 1.0f) {
         return BAD_VALUE;
@@ -586,6 +729,11 @@
     }
 
     AutoMutex lock(mLock);
+#ifdef QCOM_HARDWARE
+    if(mAudioDirectOutput != -1) {
+        return mAudioFlinger->sampleRate(mAudioDirectOutput);
+    }
+#endif
     return mCblk->sampleRate;
 }
 
@@ -1076,7 +1224,12 @@
 
 ssize_t AudioTrack::write(const void* buffer, size_t userSize)
 {
-
+#ifdef QCOM_HARDWARE
+    if (mDirectTrack != NULL) {
+        mDirectTrack->write(buffer,userSize);
+        return userSize;
+    }
+#endif
     if (mSharedBuffer != 0) return INVALID_OPERATION;
     if (mIsTimed) return INVALID_OPERATION;
 
@@ -1456,6 +1609,23 @@
     return NO_ERROR;
 }
 
+#ifdef QCOM_HARDWARE
+void AudioTrack::notify(int msg) {
+    if (msg == EVENT_UNDERRUN) {
+        ALOGV("Posting event underrun to Audio Sink.");
+        mCbf(EVENT_UNDERRUN, mUserData, 0);
+    }
+}
+
+status_t AudioTrack::getTimeStamp(uint64_t *tstamp) {
+    if (mDirectTrack != NULL) {
+        *tstamp = mDirectTrack->getTimeStamp();
+        ALOGV("Timestamp %lld ", *tstamp);
+    }
+    return NO_ERROR;
+}
+#endif
+
 // =========================================================================
 
 AudioTrack::AudioTrackThread::AudioTrackThread(AudioTrack& receiver, bool bCanCallJava)
diff --git a/media/libmedia/IAudioFlinger.cpp b/media/libmedia/IAudioFlinger.cpp
index ce8ffc4..cc6a75c 100644
--- a/media/libmedia/IAudioFlinger.cpp
+++ b/media/libmedia/IAudioFlinger.cpp
@@ -1,6 +1,9 @@
 /*
 **
 ** Copyright 2007, The Android Open Source Project
+** Copyright (c) 2012, The Linux Foundation. All rights reserved.
+** Not a Contribution, Apache license notifications and license are retained
+** for attribution purposes only.
 **
 ** Licensed under the Apache License, Version 2.0 (the "License");
 ** you may not use this file except in compliance with the License.
@@ -73,6 +76,9 @@
     LOAD_HW_MODULE,
     GET_PRIMARY_OUTPUT_SAMPLING_RATE,
     GET_PRIMARY_OUTPUT_FRAME_COUNT,
+#ifdef QCOM_HARDWARE
+    CREATE_DIRECT_TRACK
+#endif
 };
 
 class BpAudioFlinger : public BpInterface<IAudioFlinger>
@@ -132,6 +138,49 @@
         return track;
     }
 
+#ifdef QCOM_HARDWARE
+    virtual sp<IDirectTrack> createDirectTrack(
+                                pid_t pid,
+                                uint32_t sampleRate,
+                                audio_channel_mask_t channelMask,
+                                audio_io_handle_t output,
+                                int *sessionId,
+                                IDirectTrackClient* client,
+                                audio_stream_type_t streamType,
+                                status_t *status)
+    {
+        Parcel data, reply;
+        sp<IDirectTrack> track;
+        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+        data.writeInt32(pid);
+        data.writeInt32(sampleRate);
+        data.writeInt32(channelMask);
+        data.writeInt32((int32_t)output);
+        int lSessionId = 0;
+        if (sessionId != NULL) {
+            lSessionId = *sessionId;
+        }
+        data.writeInt32(lSessionId);
+        data.write(client, sizeof(IDirectTrackClient));
+        data.writeInt32((int32_t) streamType);
+        status_t lStatus = remote()->transact(CREATE_DIRECT_TRACK, data, &reply);
+        if (lStatus != NO_ERROR) {
+            ALOGE("createDirectTrack error: %s", strerror(-lStatus));
+        } else {
+            lSessionId = reply.readInt32();
+            if (sessionId != NULL) {
+                *sessionId = lSessionId;
+            }
+            lStatus = reply.readInt32();
+            track = interface_cast<IDirectTrack>(reply.readStrongBinder());
+        }
+        if (status) {
+            *status = lStatus;
+        }
+        return track;
+    }
+#endif
+
     virtual sp<IAudioRecord> openRecord(
                                 pid_t pid,
                                 audio_io_handle_t input,
@@ -738,6 +787,26 @@
             reply->writeStrongBinder(track->asBinder());
             return NO_ERROR;
         } break;
+#ifdef QCOM_HARDWARE
+        case CREATE_DIRECT_TRACK: {
+            CHECK_INTERFACE(IAudioFlinger, data, reply);
+            pid_t pid = data.readInt32();
+            uint32_t sampleRate = data.readInt32();
+            audio_channel_mask_t channelMask = data.readInt32();
+            audio_io_handle_t output = (audio_io_handle_t) data.readInt32();
+            int sessionId = data.readInt32();
+            IDirectTrackClient* client;
+            data.read(client,sizeof(IDirectTrackClient));
+            int streamType = data.readInt32();
+            status_t status;
+            sp<IDirectTrack> track = createDirectTrack(pid,
+                    sampleRate, channelMask, output, &sessionId, client,(audio_stream_type_t) streamType, &status);
+            reply->writeInt32(sessionId);
+            reply->writeInt32(status);
+            reply->writeStrongBinder(track->asBinder());
+            return NO_ERROR;
+        } break;
+#endif
         case OPEN_RECORD: {
             CHECK_INTERFACE(IAudioFlinger, data, reply);
             pid_t pid = data.readInt32();
diff --git a/media/libmedia/IAudioFlingerClient.cpp b/media/libmedia/IAudioFlingerClient.cpp
index 4178b29..e289703 100644
--- a/media/libmedia/IAudioFlingerClient.cpp
+++ b/media/libmedia/IAudioFlingerClient.cpp
@@ -1,4 +1,8 @@
 /*
+ * Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ * Not a Contribution, Apache license notifications and license are retained
+ * for attribution purposes only.
+ *
  * Copyright (C) 2009 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -49,7 +53,11 @@
             uint32_t stream = *(const uint32_t *)param2;
             ALOGV("ioConfigChanged stream %d", stream);
             data.writeInt32(stream);
-        } else if (event != AudioSystem::OUTPUT_CLOSED && event != AudioSystem::INPUT_CLOSED) {
+        } else if (event != AudioSystem::OUTPUT_CLOSED &&
+#ifdef QCOM_HARDWARE
+                        event != AudioSystem::EFFECT_CONFIG_CHANGED &&
+#endif
+                        event != AudioSystem::INPUT_CLOSED) {
             const AudioSystem::OutputDescriptor *desc = (const AudioSystem::OutputDescriptor *)param2;
             data.writeInt32(desc->samplingRate);
             data.writeInt32(desc->format);
diff --git a/media/libmedia/IDirectTrack.cpp b/media/libmedia/IDirectTrack.cpp
new file mode 100644
index 0000000..480761f
--- /dev/null
+++ b/media/libmedia/IDirectTrack.cpp
@@ -0,0 +1,178 @@
+/*
+** Copyright (c) 2012, The Linux Foundation. All rights reserved.
+** Not a Contribution, Apache license notifications and license are retained
+** for attribution purposes only.
+**
+** Copyright 2007, 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 "IDirectTrack"
+//#define LOG_NDEBUG 0
+#include <utils/Log.h>
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <binder/Parcel.h>
+
+#include <media/IDirectTrack.h>
+
+namespace android {
+
+enum {
+    START = IBinder::FIRST_CALL_TRANSACTION,
+    STOP,
+    FLUSH,
+    MUTE,
+    PAUSE,
+    SET_VOLUME,
+    WRITE,
+    GET_TIMESTAMP
+};
+
+class BpDirectTrack : public BpInterface<IDirectTrack>
+{
+public:
+    BpDirectTrack(const sp<IBinder>& impl)
+        : BpInterface<IDirectTrack>(impl)
+    {
+    }
+
+    virtual status_t start()
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IDirectTrack::getInterfaceDescriptor());
+        status_t status = remote()->transact(START, data, &reply);
+        if (status == NO_ERROR) {
+            status = reply.readInt32();
+        } else {
+            ALOGW("start() error: %s", strerror(-status));
+        }
+        return status;
+    }
+
+    virtual void stop()
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IDirectTrack::getInterfaceDescriptor());
+        remote()->transact(STOP, data, &reply);
+    }
+
+    virtual void flush()
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IDirectTrack::getInterfaceDescriptor());
+        remote()->transact(FLUSH, data, &reply);
+    }
+
+    virtual void mute(bool e)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IDirectTrack::getInterfaceDescriptor());
+        data.writeInt32(e);
+        remote()->transact(MUTE, data, &reply);
+    }
+
+    virtual void pause()
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IDirectTrack::getInterfaceDescriptor());
+        remote()->transact(PAUSE, data, &reply);
+    }
+
+    virtual void setVolume(float left, float right)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IDirectTrack::getInterfaceDescriptor());
+        remote()->transact(SET_VOLUME, data, &reply);
+    }
+
+    virtual ssize_t write(const void* buffer, size_t bytes)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IDirectTrack::getInterfaceDescriptor());
+        ssize_t bytesWritten = remote()->transact(WRITE, data, &reply);
+        return bytesWritten;
+    }
+
+    virtual int64_t getTimeStamp() {
+        Parcel data, reply;
+        data.writeInterfaceToken(IDirectTrack::getInterfaceDescriptor());
+        int64_t tstamp = remote()->transact(GET_TIMESTAMP, data, &reply);
+        return tstamp;
+    }
+};
+
+IMPLEMENT_META_INTERFACE(DirectTrack, "android.media.IDirectTrack");
+
+// ----------------------------------------------------------------------
+
+status_t BnDirectTrack::onTransact(
+    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+    switch(code) {
+        case START: {
+            CHECK_INTERFACE(IDirectTrack, data, reply);
+            reply->writeInt32(start());
+            return NO_ERROR;
+        } break;
+        case STOP: {
+            CHECK_INTERFACE(IDirectTrack, data, reply);
+            stop();
+            return NO_ERROR;
+        } break;
+        case FLUSH: {
+            CHECK_INTERFACE(IDirectTrack, data, reply);
+            flush();
+            return NO_ERROR;
+        } break;
+        case MUTE: {
+            CHECK_INTERFACE(IDirectTrack, data, reply);
+            mute( data.readInt32() );
+            return NO_ERROR;
+        } break;
+        case PAUSE: {
+            CHECK_INTERFACE(IDirectTrack, data, reply);
+            pause();
+            return NO_ERROR;
+        }
+        case SET_VOLUME: {
+            CHECK_INTERFACE(IDirectTrack, data, reply);
+            float left = 1.0;
+            float right = 1.0;
+            setVolume(left, right);
+            return NO_ERROR;
+        }
+        case WRITE: {
+            CHECK_INTERFACE(IDirectTrack, data, reply);
+            const void *buffer = (void *)data.readInt32();
+            size_t bytes = data.readInt32();
+            ssize_t bytesWritten = write(buffer, bytes);
+            reply->writeInt32(bytesWritten);
+            return NO_ERROR;
+        }
+        case GET_TIMESTAMP: {
+            CHECK_INTERFACE(IDirectTrack, data, reply);
+            int64_t time = getTimeStamp();
+            reply->writeInt32(time);
+            return NO_ERROR;
+        }
+        default:
+            return BBinder::onTransact(code, data, reply, flags);
+    }
+}
+
+}; // namespace android
+
diff --git a/media/libmedia/IDirectTrackClient.cpp b/media/libmedia/IDirectTrackClient.cpp
new file mode 100644
index 0000000..86a47ec
--- /dev/null
+++ b/media/libmedia/IDirectTrackClient.cpp
@@ -0,0 +1,69 @@
+/*
+** Copyright (c) 2012, The Linux Foundation. All rights reserved.
+** Not a Contribution, Apache license notifications and license are retained
+** for attribution purposes only.
+**
+** Copyright 2007, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+#include <utils/RefBase.h>
+#include <binder/IInterface.h>
+#include <binder/Parcel.h>
+
+#include <media/IDirectTrackClient.h>
+
+namespace android {
+
+enum {
+    NOTIFY = IBinder::FIRST_CALL_TRANSACTION,
+};
+
+class BpDirectTrackClient: public BpInterface<IDirectTrackClient>
+{
+public:
+    BpDirectTrackClient(const sp<IBinder>& impl)
+        : BpInterface<IDirectTrackClient>(impl)
+    {
+    }
+
+    virtual void notify(int msg)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IDirectTrackClient::getInterfaceDescriptor());
+        data.writeInt32(msg);
+        remote()->transact(NOTIFY, data, &reply, IBinder::FLAG_ONEWAY);
+    }
+};
+
+IMPLEMENT_META_INTERFACE(DirectTrackClient, "android.media.IDirectTrackClient");
+
+// ----------------------------------------------------------------------
+
+status_t BnDirectTrackClient::onTransact(
+    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+    switch (code) {
+        case NOTIFY: {
+            CHECK_INTERFACE(IDirectTrackClient, data, reply);
+            int msg = data.readInt32();
+            notify(msg);
+            return NO_ERROR;
+        } break;
+        default:
+            return BBinder::onTransact(code, data, reply, flags);
+    }
+}
+
+}; // namespace android
diff --git a/media/libmedia/MediaProfiles.cpp b/media/libmedia/MediaProfiles.cpp
index f69dbea..fa536a6 100644
--- a/media/libmedia/MediaProfiles.cpp
+++ b/media/libmedia/MediaProfiles.cpp
@@ -1,6 +1,7 @@
 /*
 **
 ** Copyright 2010, The Android Open Source Project
+** Copyright (c) 2010 - 2012, The Linux Foundation. All rights reserved.
 **
 ** Licensed under the Apache License, Version 2.0 (the "License");
 ** you may not use this file except in compliance with the License.
@@ -45,7 +46,10 @@
     {"amrwb",  AUDIO_ENCODER_AMR_WB},
     {"aac",    AUDIO_ENCODER_AAC},
     {"heaac",  AUDIO_ENCODER_HE_AAC},
-    {"aaceld", AUDIO_ENCODER_AAC_ELD}
+    {"aaceld", AUDIO_ENCODER_AAC_ELD},
+#ifdef QCOM_HARDWARE
+    {"lpcm",  AUDIO_ENCODER_LPCM},
+#endif
 };
 
 const MediaProfiles::NameToTagMap MediaProfiles::sFileFormatMap[] = {
@@ -804,6 +808,10 @@
 MediaProfiles::createDefaultAudioEncoders(MediaProfiles *profiles)
 {
     profiles->mAudioEncoders.add(createDefaultAmrNBEncoderCap());
+#ifdef QCOM_HARDWARE
+    profiles->mAudioEncoders.add(createDefaultAacEncoderCap());
+    profiles->mAudioEncoders.add(createDefaultLpcmEncoderCap());
+#endif
 }
 
 /*static*/ void
@@ -838,6 +846,22 @@
         AUDIO_ENCODER_AMR_NB, 5525, 12200, 8000, 8000, 1, 1);
 }
 
+#ifdef QCOM_HARDWARE
+/*static*/ MediaProfiles::AudioEncoderCap*
+MediaProfiles::createDefaultAacEncoderCap()
+{
+    return new MediaProfiles::AudioEncoderCap(
+        AUDIO_ENCODER_AAC, 64000, 156000, 8000, 48000, 1, 2);
+}
+
+/*static*/ MediaProfiles::AudioEncoderCap*
+MediaProfiles::createDefaultLpcmEncoderCap()
+{
+    return new MediaProfiles::AudioEncoderCap(
+        AUDIO_ENCODER_LPCM, 768000, 4608000, 48000, 48000, 1, 6);
+}
+#endif
+
 /*static*/ void
 MediaProfiles::createDefaultImageEncodingQualityLevels(MediaProfiles *profiles)
 {