Merge tag 'android-4.4.3_r1.1' into HEAD

Android 4.4.3 release 1.1

Change-Id: Ic939fc64cbacba0f0aba987d9d834c7798020dd1
diff --git a/NOTICE b/NOTICE
index 152be20..6f652a2 100644
--- a/NOTICE
+++ b/NOTICE
@@ -322,3 +322,32 @@
 shall not be used in advertising or otherwise to promote the sale, use
 or other dealings in these Data Files or Software without prior written
 authorization of the copyright holder.
+
+
+Copyright (c) 2013, The Linux Foundation. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+    * Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+     with the distribution.
+  * Neither the name of The Linux Foundation nor the names of its
+     contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
diff --git a/camera/Android.mk b/camera/Android.mk
index 5cedab0..3d5afab 100644
--- a/camera/Android.mk
+++ b/camera/Android.mk
@@ -36,6 +36,17 @@
 LOCAL_C_INCLUDES += \
 	system/media/camera/include \
 
+ifeq ($(BOARD_CAMERA_HAVE_ISO),true)
+	LOCAL_CFLAGS += -DHAVE_ISO
+endif
+
+ifeq ($(BOARD_USES_QCOM_HARDWARE),true)
+	LOCAL_CFLAGS += -DQCOM_HARDWARE
+endif
+ifeq ($(BOARD_USES_QCOM_LEGACY_CAM_PARAMS),true)
+	LOCAL_CFLAGS += -DQCOM_LEGACY_CAM_PARAMS
+endif
+
 LOCAL_MODULE:= libcamera_client
 
 include $(BUILD_SHARED_LIBRARY)
diff --git a/camera/CameraParameters.cpp b/camera/CameraParameters.cpp
index c51f265..75ec676 100644
--- a/camera/CameraParameters.cpp
+++ b/camera/CameraParameters.cpp
@@ -26,15 +26,51 @@
 // Parameter keys to communicate between camera application and driver.
 const char CameraParameters::KEY_PREVIEW_SIZE[] = "preview-size";
 const char CameraParameters::KEY_SUPPORTED_PREVIEW_SIZES[] = "preview-size-values";
+#ifdef QCOM_HARDWARE
+const char CameraParameters::KEY_SUPPORTED_HFR_SIZES[] = "hfr-size-values";
+#endif
 const char CameraParameters::KEY_PREVIEW_FORMAT[] = "preview-format";
 const char CameraParameters::KEY_SUPPORTED_PREVIEW_FORMATS[] = "preview-format-values";
 const char CameraParameters::KEY_PREVIEW_FRAME_RATE[] = "preview-frame-rate";
 const char CameraParameters::KEY_SUPPORTED_PREVIEW_FRAME_RATES[] = "preview-frame-rate-values";
 const char CameraParameters::KEY_PREVIEW_FPS_RANGE[] = "preview-fps-range";
 const char CameraParameters::KEY_SUPPORTED_PREVIEW_FPS_RANGE[] = "preview-fps-range-values";
+#ifdef QCOM_HARDWARE
+const char CameraParameters::KEY_PREVIEW_FRAME_RATE_MODE[] = "preview-frame-rate-mode";
+const char CameraParameters::KEY_SUPPORTED_PREVIEW_FRAME_RATE_MODES[] = "preview-frame-rate-modes";
+const char CameraParameters::KEY_PREVIEW_FRAME_RATE_AUTO_MODE[] = "frame-rate-auto";
+const char CameraParameters::KEY_PREVIEW_FRAME_RATE_FIXED_MODE[] = "frame-rate-fixed";
+#ifdef QCOM_LEGACY_CAM_PARAMS
+//Values for Continuous AF
+const char CameraParameters::CAF_OFF[] = "caf-off";
+const char CameraParameters::CAF_ON[] = "caf-on";
+//Same, for CodeAurora-based blobs
+const char CameraParameters::CAPTURE_MODE_NORMAL[] = "normal";
+const char CameraParameters::CAPTURE_MODE_BURST[] = "burst";
+const char CameraParameters::CAPTURE_MODE_CONTI_BURST[] = "contiburst";
+const char CameraParameters::CAPTURE_MODE_HDR[] = "hdr";
+const char CameraParameters::CAPTURE_MODE_HJR[] = "hjr";
+const char CameraParameters::CAPTURE_MODE_PANORAMA[] = "panorama";
+const char CameraParameters::CONTINUOUS_AF_OFF[] = "caf-off";
+const char CameraParameters::CONTINUOUS_AF_ON[] = "caf-on";
+const char CameraParameters::KEY_CONTINUOUS_AF[] = "continuous-af";
+const char CameraParameters::KEY_CAF[] = "continuous-af";
+const char CameraParameters::KEY_CAPTURE_MODE[] = "capture-mode";
+const char CameraParameters::KEY_PICTURE_COUNT[] = "picture-count";
+const char CameraParameters::KEY_MAX_BURST_PICTURE_COUNT[] = "max-burst-picture-count";
+const char CameraParameters::KEY_SUPPORTED_CONTINUOUS_AF[] = "continuous-af-mode";
+const char CameraParameters::KEY_SUPPORTED_CAF[] = "continuous-af-values";
+const char CameraParameters::KEY_SUPPORTED_CAPTURE_MODES[] = "capture-mode-values";
+const char CameraParameters::KEY_TAKING_PICTURE_ZOOM[] = "taking-picture-zoom";
+const char CameraParameters::KEY_PANORAMA_MODE[] = "panorama-mode";
+const char CameraParameters::PANORAMA_MODE_NOT_INPROGRESS[] = "not-in-progress";
+const char CameraParameters::PANORAMA_MODE_INPROGRESS[] = "in-progress";
+#endif
+#endif
 const char CameraParameters::KEY_PICTURE_SIZE[] = "picture-size";
 const char CameraParameters::KEY_SUPPORTED_PICTURE_SIZES[] = "picture-size-values";
 const char CameraParameters::KEY_PICTURE_FORMAT[] = "picture-format";
+const char CameraParameters::KEY_SUPPORTED_3D_FILE_FORMAT[] = "3d-file-format";
 const char CameraParameters::KEY_SUPPORTED_PICTURE_FORMATS[] = "picture-format-values";
 const char CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH[] = "jpeg-thumbnail-width";
 const char CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT[] = "jpeg-thumbnail-height";
@@ -51,10 +87,20 @@
 const char CameraParameters::KEY_SUPPORTED_WHITE_BALANCE[] = "whitebalance-values";
 const char CameraParameters::KEY_EFFECT[] = "effect";
 const char CameraParameters::KEY_SUPPORTED_EFFECTS[] = "effect-values";
+#ifdef QCOM_HARDWARE
+const char CameraParameters::KEY_TOUCH_AF_AEC[] = "touch-af-aec";
+const char CameraParameters::KEY_SUPPORTED_TOUCH_AF_AEC[] = "touch-af-aec-values";
+const char CameraParameters::KEY_TOUCH_INDEX_AEC[] = "touch-index-aec";
+const char CameraParameters::KEY_TOUCH_INDEX_AF[] = "touch-index-af";
+#endif
 const char CameraParameters::KEY_ANTIBANDING[] = "antibanding";
 const char CameraParameters::KEY_SUPPORTED_ANTIBANDING[] = "antibanding-values";
 const char CameraParameters::KEY_SCENE_MODE[] = "scene-mode";
 const char CameraParameters::KEY_SUPPORTED_SCENE_MODES[] = "scene-mode-values";
+#ifdef QCOM_HARDWARE
+const char CameraParameters::KEY_SCENE_DETECT[] = "scene-detect";
+const char CameraParameters::KEY_SUPPORTED_SCENE_DETECT[] = "scene-detect-values";
+#endif QCOM_HARDWARE
 const char CameraParameters::KEY_FLASH_MODE[] = "flash-mode";
 const char CameraParameters::KEY_SUPPORTED_FLASH_MODES[] = "flash-mode-values";
 const char CameraParameters::KEY_FOCUS_MODE[] = "focus-mode";
@@ -81,6 +127,32 @@
 const char CameraParameters::KEY_SMOOTH_ZOOM_SUPPORTED[] = "smooth-zoom-supported";
 const char CameraParameters::KEY_FOCUS_DISTANCES[] = "focus-distances";
 const char CameraParameters::KEY_VIDEO_FRAME_FORMAT[] = "video-frame-format";
+#ifdef QCOM_HARDWARE
+const char CameraParameters::KEY_ISO_MODE[] = "iso";
+const char CameraParameters::KEY_SUPPORTED_ISO_MODES[] = "iso-values";
+const char CameraParameters::KEY_LENSSHADE[] = "lensshade";
+const char CameraParameters::KEY_SUPPORTED_LENSSHADE_MODES[] = "lensshade-values";
+#ifdef SAMSUNG_CAMERA_LEGACY
+const char CameraParameters::KEY_AUTO_EXPOSURE[] = "metering";
+#else
+const char CameraParameters::KEY_AUTO_EXPOSURE[] = "auto-exposure";
+#endif
+const char CameraParameters::KEY_SUPPORTED_AUTO_EXPOSURE[] = "auto-exposure-values";
+const char CameraParameters::KEY_DENOISE[] = "denoise";
+const char CameraParameters::KEY_SUPPORTED_DENOISE[] = "denoise-values";
+const char CameraParameters::KEY_SELECTABLE_ZONE_AF[] = "selectable-zone-af";
+const char CameraParameters::KEY_SUPPORTED_SELECTABLE_ZONE_AF[] = "selectable-zone-af-values";
+const char CameraParameters::KEY_FACE_DETECTION[] = "face-detection";
+const char CameraParameters::KEY_SUPPORTED_FACE_DETECTION[] = "face-detection-values";
+const char CameraParameters::KEY_MEMORY_COLOR_ENHANCEMENT[] = "mce";
+const char CameraParameters::KEY_SUPPORTED_MEM_COLOR_ENHANCE_MODES[] = "mce-values";
+const char CameraParameters::KEY_VIDEO_HIGH_FRAME_RATE[] = "video-hfr";
+const char CameraParameters::KEY_SUPPORTED_VIDEO_HIGH_FRAME_RATE_MODES[] = "video-hfr-values";
+const char CameraParameters::KEY_REDEYE_REDUCTION[] = "redeye-reduction";
+const char CameraParameters::KEY_SUPPORTED_REDEYE_REDUCTION[] = "redeye-reduction-values";
+const char CameraParameters::KEY_HIGH_DYNAMIC_RANGE_IMAGING[] = "hdr";
+const char CameraParameters::KEY_SUPPORTED_HDR_IMAGING_MODES[] = "hdr-values";
+#endif
 const char CameraParameters::KEY_VIDEO_SIZE[] = "video-size";
 const char CameraParameters::KEY_SUPPORTED_VIDEO_SIZES[] = "video-size-values";
 const char CameraParameters::KEY_PREFERRED_PREVIEW_SIZE_FOR_VIDEO[] = "preferred-preview-size-for-video";
@@ -88,9 +160,101 @@
 const char CameraParameters::KEY_MAX_NUM_DETECTED_FACES_SW[] = "max-num-detected-faces-sw";
 const char CameraParameters::KEY_RECORDING_HINT[] = "recording-hint";
 const char CameraParameters::KEY_VIDEO_SNAPSHOT_SUPPORTED[] = "video-snapshot-supported";
+const char CameraParameters::KEY_FULL_VIDEO_SNAP_SUPPORTED[] = "full-video-snap-supported";
 const char CameraParameters::KEY_VIDEO_STABILIZATION[] = "video-stabilization";
 const char CameraParameters::KEY_VIDEO_STABILIZATION_SUPPORTED[] = "video-stabilization-supported";
 const char CameraParameters::KEY_LIGHTFX[] = "light-fx";
+#ifdef QCOM_HARDWARE
+const char CameraParameters::KEY_ZSL[] = "zsl";
+const char CameraParameters::KEY_SUPPORTED_ZSL_MODES[] = "zsl-values";
+const char CameraParameters::KEY_CAMERA_MODE[] = "camera-mode";
+const char CameraParameters::KEY_POWER_MODE[] = "power-mode";
+const char CameraParameters::KEY_POWER_MODE_SUPPORTED[] = "power-mode-supported";
+#endif
+const char CameraParameters::KEY_AE_BRACKET_HDR[] = "ae-bracket-hdr";
+
+/*only effective when KEY_AE_BRACKET_HDR set to ae_bracketing*/
+//const char CameraParameters::KEY_AE_BRACKET_SETTING_KEY[] = "ae-bracket-setting";
+
+#ifdef HAVE_ISO
+const char CameraParameters::KEY_SUPPORTED_ISO_MODES[] = "iso-values";
+const char CameraParameters::KEY_ISO_MODE[] = "iso";
+#endif
+
+#ifdef SAMSUNG_CAMERA_HARDWARE
+const char CameraParameters::KEY_ANTI_SHAKE_MODE[] = "anti-shake";
+const char CameraParameters::KEY_METERING[] = "metering";
+const char CameraParameters::KEY_WDR[] = "wdr";
+const char CameraParameters::KEY_WEATHER[] = "weather";
+const char CameraParameters::KEY_CITYID[] = "contextualtag-cityid";
+#endif
+
+#ifdef HTC_CAMERA_HARDWARE
+const char CameraParameters::KEY_TIME_CONS_POST_PROCESSING[] = "time-cons-post-processing";
+const char CameraParameters::KEY_OIS_MODE[] = "ois_mode";
+const char CameraParameters::KEY_APP_OIS_SETTING[] = "ois-setting";
+const char CameraParameters::KEY_OIS_SUPPORT[] = "ois_support";
+const char CameraParameters::KEY_CONTIBURST_TYPE[] = "contiburst-type";
+const char CameraParameters::KEY_CAPTURE_MODE[] = "capture-mode";
+const char CameraParameters::CAPTURE_MODE_NORMAL[] = "normal";
+const char CameraParameters::CAPTURE_MODE_CONTI_ZOE[] = "contizoe";
+const char CameraParameters::CAPTURE_MODE_CONTI_BURST[] = "contiburst";
+const char CameraParameters::CAPTURE_MODE_CONTI_BURST_ONE_SHOT[] = "contiburst-one-shot";
+const char CameraParameters::CAPTURE_MODE_HDR[] = "hdr";
+const char CameraParameters::CAPTURE_MODE_PANORAMA[] = "panorama";
+const char CameraParameters::CAPTURE_MODE_ZOE[] = "zoe";
+const char CameraParameters::KEY_CONTI_BURST_STATE[] = "contiburst-state";
+const char CameraParameters::KEY_SUPPORTED_CAPTURE_MODES[] = "capture-mode-values";
+const char CameraParameters::KEY_MIN_CONTRAST[] = "contrast-min";
+const char CameraParameters::KEY_DEF_CONTRAST[] = "contrast-def";
+const char CameraParameters::KEY_MIN_SHARPNESS[] = "sharpness-min";
+const char CameraParameters::KEY_DEF_SHARPNESS[] = "sharpness-def";
+const char CameraParameters::KEY_MIN_SATURATION[] = "saturation-min";
+const char CameraParameters::KEY_DEF_SATURATION[] = "saturation-def";
+const char CameraParameters::KEY_SINGLE_ISP_OUTPUT_ENABLED[] = "single-isp-output-enabled";
+const char CameraParameters::POST_PROCESSING_ENABLE[] = "enable";
+const char CameraParameters::POST_PROCESSING_BYPASS[] = "bypass";
+const char CameraParameters::POST_PROCESSING_DELAY[] = "delay";
+const char CameraParameters::SCENE_MODE_OFF[] = "off";
+const char CameraParameters::SCENE_MODE_TEXT[] = "text";
+const char CameraParameters::BURST_MODE_LIMIT20[] = "limit-20";
+const char CameraParameters::BURST_MODE_UNLIMITED[] = "unlimited";
+const char CameraParameters::OIS_MODE_OFF[] = "off";
+const char CameraParameters::OIS_MODE_ON[] = "on";
+const char CameraParameters::CONTI_BURST_CAPTURING[] = "contiburst-capturing";
+const char CameraParameters::CONTI_BURST_CAPTURE_DONE[] = "contiburst-done";
+const char CameraParameters::APP_OIS_SETTING_FALSE[] = "false";
+const char CameraParameters::APP_OIS_SETTING_TRUE[] = "true";
+const char CameraParameters::KEY_GPU_EFFECT[] = "GPU-effect";
+const char CameraParameters::KEY_GPU_EFFECT_PARAM_0[] = "GE-param0";
+const char CameraParameters::KEY_GPU_EFFECT_PARAM_1[] = "GE-param1";
+const char CameraParameters::KEY_GPU_EFFECT_PARAM_2[] = "GE-param2";
+const char CameraParameters::KEY_GPU_EFFECT_PARAM_3[] = "GE-param3";
+const char CameraParameters::KEY_FORCE_USE_AUDIO_ENABLED[] = "forceuseaudio";
+#endif
+
+#ifdef LG_CAMERA_HARDWARE
+const char CameraParameters::AUDIO_ZOOM_OFF[] = "audio-zoom";
+const char CameraParameters::AUDIO_ZOOM_ON[] = "audio-zoom";
+const char CameraParameters::BEAUTY_SHOT_OFF[] = "beauty-shot";
+const char CameraParameters::BEAUTY_SHOT_ON[] = "beauty-shot";
+const char CameraParameters::BURST_SHOT_OFF[] = "burst-shot";
+const char CameraParameters::BURST_SHOT_ON[] = "burst-shot";
+const char CameraParameters::KEY_AUDIO_ZOOM[] = "audio-zoom";
+const char CameraParameters::KEY_AUDIO_ZOOM_SUPPORTED[] = "audio-zoom-supported";
+const char CameraParameters::KEY_BEAUTY_SHOT[] = "beauty-shot";
+const char CameraParameters::KEY_BEAUTY_SHOT_SUPPORTED[] = "beauty-shot-supported";
+const char CameraParameters::KEY_BURST_SHOT[] = "burst-shot";
+const char CameraParameters::KEY_BURST_SHOT_SUPPORTED[] = "burst-shot-supported";
+const char CameraParameters::KEY_FOCUS_MODE_OBJECT_TRACKING[] = "object-tracking";
+const char CameraParameters::KEY_FOCUS_MODE_OBJECT_TRACKING_SUPPORTED[] = "object-tracking-supported";
+const char CameraParameters::KEY_VIDEO_WDR[] = "video-wdr";
+const char CameraParameters::KEY_VIDEO_WDR_SUPPORTED[] = "video-wdr-supported";
+const char CameraParameters::VIDEO_WDR_OFF[] = "video-wdr";
+const char CameraParameters::VIDEO_WDR_ON[] = "video-wdr";
+const char CameraParameters::OBJECT_TRACKING_ON[] = "object-tracking";
+const char CameraParameters::OBJECT_TRACKING_OFF[] = "object-tracking";
+#endif
 
 const char CameraParameters::TRUE[] = "true";
 const char CameraParameters::FALSE[] = "false";
@@ -116,6 +280,24 @@
 const char CameraParameters::EFFECT_WHITEBOARD[] = "whiteboard";
 const char CameraParameters::EFFECT_BLACKBOARD[] = "blackboard";
 const char CameraParameters::EFFECT_AQUA[] = "aqua";
+#ifdef SAMSUNG_CAMERA_HARDWARE
+const char CameraParameters::EFFECT_CARTOONIZE[] = "cartoonize";
+const char CameraParameters::EFFECT_POINT_RED_YELLOW[] = "point-red-yellow";
+const char CameraParameters::EFFECT_POINT_GREEN[] = "point-green";
+const char CameraParameters::EFFECT_POINT_BLUE[] = "point-blue";
+const char CameraParameters::EFFECT_VINTAGE_COLD[] = "vintage-cold";
+const char CameraParameters::EFFECT_VINTAGE_WARM[] = "vintage-warm";
+const char CameraParameters::EFFECT_WASHED[] = "washed";
+#endif
+#ifdef QCOM_HARDWARE
+const char CameraParameters::EFFECT_EMBOSS[] = "emboss";
+const char CameraParameters::EFFECT_SKETCH[] = "sketch";
+const char CameraParameters::EFFECT_NEON[] = "neon";
+
+// Values for auto exposure settings.
+const char CameraParameters::TOUCH_AF_AEC_OFF[] = "touch-off";
+const char CameraParameters::TOUCH_AF_AEC_ON[] = "touch-on";
+#endif
 
 // Values for antibanding settings.
 const char CameraParameters::ANTIBANDING_AUTO[] = "auto";
@@ -131,7 +313,8 @@
 const char CameraParameters::FLASH_MODE_TORCH[] = "torch";
 
 // Values for scene mode settings.
-const char CameraParameters::SCENE_MODE_AUTO[] = "auto";
+const char CameraParameters::SCENE_MODE_AUTO[] = "auto"; // corresponds to CAMERA_BESTSHOT_OFF in HAL
+const char CameraParameters::SCENE_MODE_ASD[] = "asd";   // corresponds to CAMERA_BESTSHOT_AUTO in HAL
 const char CameraParameters::SCENE_MODE_ACTION[] = "action";
 const char CameraParameters::SCENE_MODE_PORTRAIT[] = "portrait";
 const char CameraParameters::SCENE_MODE_LANDSCAPE[] = "landscape";
@@ -146,11 +329,32 @@
 const char CameraParameters::SCENE_MODE_SPORTS[] = "sports";
 const char CameraParameters::SCENE_MODE_PARTY[] = "party";
 const char CameraParameters::SCENE_MODE_CANDLELIGHT[] = "candlelight";
+#ifdef QCOM_HARDWARE
+#ifdef SAMSUNG_CAMERA_LEGACY
+const char CameraParameters::SCENE_MODE_BACKLIGHT[] = "back-light";
+#else
+const char CameraParameters::SCENE_MODE_BACKLIGHT[] = "backlight";
+#endif
+const char CameraParameters::SCENE_MODE_FLOWERS[] = "flowers";
+#endif
 const char CameraParameters::SCENE_MODE_BARCODE[] = "barcode";
-const char CameraParameters::SCENE_MODE_HDR[] = "hdr";
 
+const char CameraParameters::SCENE_MODE_HDR[] = "hdr";
+#ifdef QCOM_HARDWARE
+const char CameraParameters::SCENE_MODE_AR[] = "AR";
+
+// Values for auto scene detection settings.
+const char CameraParameters::SCENE_DETECT_OFF[] = "off";
+const char CameraParameters::SCENE_DETECT_ON[] = "on";
+#endif
+
+
+// Formats for setPreviewFormat and setPictureFormat.
 const char CameraParameters::PIXEL_FORMAT_YUV422SP[] = "yuv422sp";
 const char CameraParameters::PIXEL_FORMAT_YUV420SP[] = "yuv420sp";
+#ifdef QCOM_HARDWARE
+const char CameraParameters::PIXEL_FORMAT_YUV420SP_ADRENO[] = "yuv420sp-adreno";
+#endif
 const char CameraParameters::PIXEL_FORMAT_YUV422I[] = "yuv422i-yuyv";
 const char CameraParameters::PIXEL_FORMAT_YUV420P[]  = "yuv420p";
 const char CameraParameters::PIXEL_FORMAT_RGB565[] = "rgb565";
@@ -159,6 +363,12 @@
 const char CameraParameters::PIXEL_FORMAT_BAYER_RGGB[] = "bayer-rggb";
 const char CameraParameters::PIXEL_FORMAT_ANDROID_OPAQUE[] = "android-opaque";
 
+#ifdef QCOM_HARDWARE
+const char CameraParameters::PIXEL_FORMAT_RAW[] = "raw";
+const char CameraParameters::PIXEL_FORMAT_YV12[] = "yuv420p";
+const char CameraParameters::PIXEL_FORMAT_NV12[] = "nv12";
+#endif
+
 // Values for focus mode settings.
 const char CameraParameters::FOCUS_MODE_AUTO[] = "auto";
 const char CameraParameters::FOCUS_MODE_INFINITY[] = "infinity";
@@ -167,6 +377,161 @@
 const char CameraParameters::FOCUS_MODE_EDOF[] = "edof";
 const char CameraParameters::FOCUS_MODE_CONTINUOUS_VIDEO[] = "continuous-video";
 const char CameraParameters::FOCUS_MODE_CONTINUOUS_PICTURE[] = "continuous-picture";
+#if defined(QCOM_HARDWARE)
+#ifdef QCOM_LEGACY_CAM_PARAMS
+const char CameraParameters::FOCUS_MODE_CONTINUOUS_CAMERA[] = "continuous-camera";
+#endif
+const char CameraParameters::FOCUS_MODE_NORMAL[] = "normal";
+
+
+const char CameraParameters::KEY_SKIN_TONE_ENHANCEMENT[] = "skinToneEnhancement";
+const char CameraParameters::KEY_SUPPORTED_SKIN_TONE_ENHANCEMENT_MODES[] = "skinToneEnhancement-values";
+
+// Values for ISO Settings
+const char CameraParameters::ISO_AUTO[] = "auto";
+const char CameraParameters::ISO_HJR[] = "ISO_HJR";
+const char CameraParameters::ISO_100[] = "ISO100";
+const char CameraParameters::ISO_200[] = "ISO200";
+const char CameraParameters::ISO_400[] = "ISO400";
+const char CameraParameters::ISO_800[] = "ISO800";
+const char CameraParameters::ISO_1600[] = "ISO1600";
+const char CameraParameters::ISO_3200[] = "ISO3200";
+const char CameraParameters::ISO_6400[] = "ISO6400";
+
+ //Values for Lens Shading
+const char CameraParameters::LENSSHADE_ENABLE[] = "enable";
+const char CameraParameters::LENSSHADE_DISABLE[] = "disable";
+
+// Values for auto exposure settings.
+const char CameraParameters::AUTO_EXPOSURE_FRAME_AVG[] = "frame-average";
+const char CameraParameters::AUTO_EXPOSURE_CENTER_WEIGHTED[] = "center-weighted";
+const char CameraParameters::AUTO_EXPOSURE_SPOT_METERING[] = "spot-metering";
+
+const char CameraParameters::KEY_GPS_LATITUDE_REF[] = "gps-latitude-ref";
+const char CameraParameters::KEY_GPS_LONGITUDE_REF[] = "gps-longitude-ref";
+const char CameraParameters::KEY_GPS_ALTITUDE_REF[] = "gps-altitude-ref";
+const char CameraParameters::KEY_GPS_STATUS[] = "gps-status";
+const char CameraParameters::KEY_EXIF_DATETIME[] = "exif-datetime";
+
+const char CameraParameters::KEY_HISTOGRAM[] = "histogram";
+const char CameraParameters::KEY_SUPPORTED_HISTOGRAM_MODES[] = "histogram-values";
+//Values for Histogram Shading
+const char CameraParameters::HISTOGRAM_ENABLE[] = "enable";
+const char CameraParameters::HISTOGRAM_DISABLE[] = "disable";
+
+//Values for Skin Tone Enhancement Modes
+const char CameraParameters::SKIN_TONE_ENHANCEMENT_ENABLE[] = "enable";
+const char CameraParameters::SKIN_TONE_ENHANCEMENT_DISABLE[] = "disable";
+
+const char CameraParameters::KEY_SHARPNESS[] = "sharpness";
+#ifdef QCOM_LEGACY_CAM_PARAMS
+const char CameraParameters::KEY_MAX_SHARPNESS[] = "sharpness-max";
+const char CameraParameters::KEY_MIN_SHARPNESS[] = "sharpness-min";
+#else
+const char CameraParameters::KEY_MAX_SHARPNESS[] = "max-sharpness";
+#endif
+const char CameraParameters::KEY_CONTRAST[] = "contrast";
+#ifdef QCOM_LEGACY_CAM_PARAMS
+const char CameraParameters::KEY_MAX_CONTRAST[] = "contrast-max";
+const char CameraParameters::KEY_MIN_CONTRAST[] = "contrast-min";
+#else
+const char CameraParameters::KEY_MAX_CONTRAST[] = "max-contrast";
+#endif
+const char CameraParameters::KEY_SATURATION[] = "saturation";
+#ifdef QCOM_LEGACY_CAM_PARAMS
+const char CameraParameters::KEY_MAX_SATURATION[] = "saturation-max";
+const char CameraParameters::KEY_MIN_SATURATION[] = "saturation-min";
+#else
+const char CameraParameters::KEY_MAX_SATURATION[] = "max-saturation";
+#endif
+
+//Values for DENOISE
+const char CameraParameters::DENOISE_OFF[] = "denoise-off";
+const char CameraParameters::DENOISE_ON[] = "denoise-on";
+// Values for selectable zone af Settings
+const char CameraParameters::SELECTABLE_ZONE_AF_AUTO[] = "auto";
+const char CameraParameters::SELECTABLE_ZONE_AF_SPOT_METERING[] = "spot-metering";
+const char CameraParameters::SELECTABLE_ZONE_AF_CENTER_WEIGHTED[] = "center-weighted";
+const char CameraParameters::SELECTABLE_ZONE_AF_FRAME_AVERAGE[] = "frame-average";
+
+// Values for Face Detection settings.
+const char CameraParameters::FACE_DETECTION_OFF[] = "off";
+const char CameraParameters::FACE_DETECTION_ON[] = "on";
+
+const char CameraParameters::FILE_FORMAT_MPO[] = "mpo";
+const char CameraParameters::FILE_FORMAT_JPS[] = "jps";
+
+// Values for MCE settings.
+const char CameraParameters::MCE_ENABLE[] = "enable";
+const char CameraParameters::MCE_DISABLE[] = "disable";
+
+// Values for HFR settings.
+const char CameraParameters::VIDEO_HFR_OFF[] = "off";
+const char CameraParameters::VIDEO_HFR_2X[] = "60";
+const char CameraParameters::VIDEO_HFR_3X[] = "90";
+const char CameraParameters::VIDEO_HFR_4X[] = "120";
+
+// Values for Redeye Reduction settings.
+const char CameraParameters::REDEYE_REDUCTION_ENABLE[] = "enable";
+const char CameraParameters::REDEYE_REDUCTION_DISABLE[] = "disable";
+// Values for HDR settings.
+const char CameraParameters::HDR_ENABLE[] = "enable";
+const char CameraParameters::HDR_DISABLE[] = "disable";
+
+// Values for ZSL settings.
+const char CameraParameters::ZSL_OFF[] = "off";
+const char CameraParameters::ZSL_ON[] = "on";
+
+// Values for HDR Bracketing settings.
+const char CameraParameters::AE_BRACKET_HDR_OFF[] = "Off";
+const char CameraParameters::AE_BRACKET_HDR[] = "HDR";
+const char CameraParameters::AE_BRACKET[] = "AE-Bracket";
+
+const char CameraParameters::LOW_POWER[] = "Low_Power";
+const char CameraParameters::NORMAL_POWER[] = "Normal_Power";
+
+#if defined(QCOM_HARDWARE) && defined(SAMSUNG_CAMERA_LEGACY)
+const char CameraParameters::FOCUS_MODE_FACEDETECT[] = "facedetect";
+const char CameraParameters::FOCUS_MODE_TOUCHAF[] = "touchaf";
+const char CameraParameters::ISO_50[] = "ISO50";
+const char CameraParameters::KEY_ANTI_SHAKE_MODE[] = "antishake";
+const char CameraParameters::KEY_AUTO_CONTRAST[] = "auto-contrast";
+const char CameraParameters::KEY_BEAUTY_MODE[] = "beauty";
+const char CameraParameters::KEY_BLUR_MODE[] = "blur";
+const char CameraParameters::KEY_VINTAGE_MODE[] = "vintagemode";
+const char CameraParameters::KEY_WDR_MODE[] = "wdr";
+const char CameraParameters::VINTAGE_MODE_BNW[] = "bnw";
+const char CameraParameters::VINTAGE_MODE_COOL[] = "cool";
+const char CameraParameters::VINTAGE_MODE_NORMAL[] = "normal";
+const char CameraParameters::VINTAGE_MODE_OFF[] = "off";
+const char CameraParameters::VINTAGE_MODE_WARM[] = "warm";
+const char CameraParameters::SCENE_MODE_DAWN[] = "dusk-dawn";
+const char CameraParameters::SCENE_MODE_DUSKDAWN[] = "dusk-dawn";
+const char CameraParameters::SCENE_MODE_FALL[] = "fall-color";
+const char CameraParameters::SCENE_MODE_FALL_COLOR[] = "fall-color";
+const char CameraParameters::SCENE_MODE_TEXT[] = "text";
+#endif
+
+static const char* portrait = "portrait";
+static const char* landscape = "landscape";
+
+int CameraParameters::getOrientation() const
+{
+    const char* orientation = get("orientation");
+    if (orientation && !strcmp(orientation, portrait))
+        return CAMERA_ORIENTATION_PORTRAIT;
+    return CAMERA_ORIENTATION_LANDSCAPE;
+}
+void CameraParameters::setOrientation(int orientation)
+{
+    if (orientation == CAMERA_ORIENTATION_PORTRAIT) {
+        set("orientation", portrait);
+    } else {
+         set("orientation", landscape);
+    }
+}
+#endif
+
 
 // Values for light fx settings
 const char CameraParameters::LIGHTFX_LOWLIGHT[] = "low-light";
@@ -236,6 +601,9 @@
 
 void CameraParameters::set(const char *key, const char *value)
 {
+    if (key == NULL || value == NULL)
+        return;
+
     // XXX i think i can do this with strspn()
     if (strchr(key, '=') || strchr(key, ';')) {
         //XXX ALOGE("Key \"%s\"contains invalid character (= or ;)", key);
@@ -253,7 +621,7 @@
 void CameraParameters::set(const char *key, int value)
 {
     char str[16];
-    sprintf(str, "%d", value);
+    snprintf(str, sizeof(str), "%d", value);
     set(key, str);
 }
 
@@ -280,6 +648,13 @@
     return strtol(v, 0, 0);
 }
 
+#ifdef SAMSUNG_CAMERA_HARDWARE
+int CameraParameters::getInt64(const char *key) const
+{
+    return -1;
+}
+#endif
+
 float CameraParameters::getFloat(const char *key) const
 {
     const char *v = get(key);
@@ -318,6 +693,32 @@
     return 0;
 }
 
+// Parse string like "(1, 2, 3, 4, ..., N)"
+// num is pointer to an allocated array of size N
+static int parseNDimVector(const char *str, int *num, int N, char delim = ',')
+{
+    char *start, *end;
+    if(num == NULL) {
+        ALOGE("Invalid output array (num == NULL)");
+        return -1;
+    }
+    //check if string starts and ends with parantheses
+    if(str[0] != '(' || str[strlen(str)-1] != ')') {
+        ALOGE("Invalid format of string %s, valid format is (n1, n2, n3, n4 ...)", str);
+        return -1;
+    }
+    start = (char*) str;
+    start++;
+    for(int i=0; i<N; i++) {
+        *(num+i) = (int) strtol(start, &end, 10);
+        if(*end != delim && i < N-1) {
+            ALOGE("Cannot find delimeter '%c' in string \"%s\". end = %c", delim, str, *end);
+            return -1;
+        }
+        start = end+1;
+    }
+    return 0;
+}
 static void parseSizesList(const char *sizesStr, Vector<Size> &sizes)
 {
     if (sizesStr == 0) {
@@ -346,7 +747,7 @@
 void CameraParameters::setPreviewSize(int width, int height)
 {
     char str[32];
-    sprintf(str, "%dx%d", width, height);
+    snprintf(str, sizeof(str), "%dx%d", width, height);
     set(KEY_PREVIEW_SIZE, str);
 }
 
@@ -373,6 +774,28 @@
     parseSizesList(previewSizesStr, sizes);
 }
 
+#ifdef QCOM_HARDWARE
+#ifdef QCOM_LEGACY_CAM_PARAMS
+void CameraParameters::setPostviewSize(int width, int height)
+{
+    // dummy
+}
+#endif
+
+void CameraParameters::getSupportedHfrSizes(Vector<Size> &sizes) const
+{
+    const char *hfrSizesStr = get(KEY_SUPPORTED_HFR_SIZES);
+    parseSizesList(hfrSizesStr, sizes);
+}
+
+void CameraParameters::setPreviewFpsRange(int minFPS, int maxFPS)
+{
+    char str[32];
+    snprintf(str, sizeof(str), "%d,%d",minFPS,maxFPS);
+    set(KEY_PREVIEW_FPS_RANGE,str);
+}
+#endif
+
 void CameraParameters::setVideoSize(int width, int height)
 {
     char str[32];
@@ -412,6 +835,18 @@
     parse_pair(p, min_fps, max_fps, ',');
 }
 
+#ifdef QCOM_HARDWARE
+void CameraParameters::setPreviewFrameRateMode(const char *mode)
+{
+    set(KEY_PREVIEW_FRAME_RATE_MODE, mode);
+}
+
+const char *CameraParameters::getPreviewFrameRateMode() const
+{
+    return get(KEY_PREVIEW_FRAME_RATE_MODE);
+}
+#endif
+
 void CameraParameters::setPreviewFormat(const char *format)
 {
     set(KEY_PREVIEW_FORMAT, format);
@@ -444,6 +879,11 @@
     parseSizesList(pictureSizesStr, sizes);
 }
 
+void CameraParameters::set3DFileFormat(const char *format)
+{
+    set(KEY_SUPPORTED_3D_FILE_FORMAT, format);
+}
+
 void CameraParameters::setPictureFormat(const char *format)
 {
     set(KEY_PICTURE_FORMAT, format);
@@ -465,6 +905,71 @@
     }
 }
 
+#ifdef QCOM_HARDWARE
+void CameraParameters::setTouchIndexAec(int x, int y)
+{
+    char str[32];
+    snprintf(str, sizeof(str), "%dx%d", x, y);
+    set(KEY_TOUCH_INDEX_AEC, str);
+}
+
+void CameraParameters::getTouchIndexAec(int *x, int *y) const
+{
+    *x = -1;
+    *y = -1;
+
+    // Get the current string, if it doesn't exist, leave the -1x-1
+    const char *p = get(KEY_TOUCH_INDEX_AEC);
+    if (p == 0)
+        return;
+
+    int tempX, tempY;
+    if (parse_pair(p, &tempX, &tempY, 'x') == 0) {
+        *x = tempX;
+        *y = tempY;
+    }
+}
+
+void CameraParameters::setTouchIndexAf(int x, int y)
+{
+    char str[32];
+    snprintf(str, sizeof(str), "%dx%d", x, y);
+    set(KEY_TOUCH_INDEX_AF, str);
+}
+
+void CameraParameters::getMeteringAreaCenter(int *x, int *y) const
+{
+    //Default invalid values
+    *x = -2000;
+    *y = -2000;
+
+    const char *p = get(KEY_METERING_AREAS);
+    if(p != NULL) {
+        int arr[5] = {-2000, -2000, -2000, -2000, 0};
+        parseNDimVector(p, arr, 5); //p = "(x1, y1, x2, y2, weight)"
+        *x = (arr[0] + arr[2])/2; //center_x = (x1+x2)/2
+        *y = (arr[1] + arr[3])/2; //center_y = (y1+y2)/2
+    }
+}
+
+void CameraParameters::getTouchIndexAf(int *x, int *y) const
+{
+    *x = -1;
+    *y = -1;
+
+    // Get the current string, if it doesn't exist, leave the -1x-1
+    const char *p = get(KEY_TOUCH_INDEX_AF);
+    if (p == 0)
+        return;
+
+    int tempX, tempY;
+    if (parse_pair(p, &tempX, &tempY, 'x') == 0) {
+        *x = tempX;
+        *y = tempY;
+    }
+}
+#endif
+
 status_t CameraParameters::dump(int fd, const Vector<String16>& args) const
 {
     const size_t SIZE = 256;
diff --git a/cmds/screenrecord/screenrecord.cpp b/cmds/screenrecord/screenrecord.cpp
index 49999b5..83b6a03 100644
--- a/cmds/screenrecord/screenrecord.cpp
+++ b/cmds/screenrecord/screenrecord.cpp
@@ -49,7 +49,7 @@
 
 static const uint32_t kMinBitRate = 100000;         // 0.1Mbps
 static const uint32_t kMaxBitRate = 100 * 1000000;  // 100Mbps
-static const uint32_t kMaxTimeLimitSec = 180;       // 3 minutes
+static const uint32_t kMaxTimeLimitSec = 3600;       // 1 Hour
 static const uint32_t kFallbackWidth = 1280;        // 720p
 static const uint32_t kFallbackHeight = 720;
 
diff --git a/include/camera/CameraParameters.h b/include/camera/CameraParameters.h
index d521543..2758989 100644
--- a/include/camera/CameraParameters.h
+++ b/include/camera/CameraParameters.h
@@ -36,7 +36,21 @@
         height = h;
     }
 };
+#ifdef QCOM_HARDWARE
+struct FPSRange{
+    int minFPS;
+    int maxFPS;
 
+    FPSRange(){
+        minFPS=0;
+        maxFPS=0;
+    };
+    FPSRange(int min,int max){
+        minFPS=min;
+        maxFPS=max;
+   };
+};
+#endif
 class CameraParameters
 {
 public:
@@ -52,6 +66,9 @@
     void setFloat(const char *key, float value);
     const char *get(const char *key) const;
     int getInt(const char *key) const;
+#ifdef SAMSUNG_CAMERA_HARDWARE
+    int getInt64(const char *key) const;
+#endif
     float getFloat(const char *key) const;
 
     void remove(const char *key);
@@ -91,13 +108,26 @@
     void setPreviewFrameRate(int fps);
     int getPreviewFrameRate() const;
     void getPreviewFpsRange(int *min_fps, int *max_fps) const;
+#ifdef QCOM_HARDWARE
+    void setPreviewFrameRateMode(const char *mode);
+    const char *getPreviewFrameRateMode() const;
+#endif
     void setPreviewFormat(const char *format);
     const char *getPreviewFormat() const;
     void setPictureSize(int width, int height);
     void getPictureSize(int *width, int *height) const;
     void getSupportedPictureSizes(Vector<Size> &sizes) const;
+    void set3DFileFormat(const char* buffer);
     void setPictureFormat(const char *format);
     const char *getPictureFormat() const;
+#ifdef QCOM_HARDWARE
+    void setTouchIndexAec(int x, int y);
+    void getTouchIndexAec(int *x, int *y) const;
+    void setTouchIndexAf(int x, int y);
+    void getTouchIndexAf(int *x, int *y) const;
+#endif
+
+    void getMeteringAreaCenter(int * x, int *y) const;
 
     void dump() const;
     status_t dump(int fd, const Vector<String16>& args) const;
@@ -112,6 +142,11 @@
     // Supported preview frame sizes in pixels.
     // Example value: "800x600,480x320". Read only.
     static const char KEY_SUPPORTED_PREVIEW_SIZES[];
+#ifdef QCOM_HARDWARE
+    // Supported PREVIEW/RECORDING SIZES IN HIGH FRAME RATE recording, sizes in pixels.
+    // Example value: "800x480,432x320". Read only.
+    static const char KEY_SUPPORTED_HFR_SIZES[];
+#endif
     // The current minimum and maximum preview fps. This controls the rate of
     // preview frames received (CAMERA_MSG_PREVIEW_FRAME). The minimum and
     // maximum fps must be one of the elements from
@@ -141,12 +176,36 @@
     // Supported number of preview frames per second.
     // Example value: "24,15,10". Read.
     static const char KEY_SUPPORTED_PREVIEW_FRAME_RATES[];
+#ifdef QCOM_HARDWARE
+    // The mode of preview frame rate.
+    // Example value: "frame-rate-auto, frame-rate-fixed".
+    static const char KEY_PREVIEW_FRAME_RATE_MODE[];
+    static const char KEY_SUPPORTED_PREVIEW_FRAME_RATE_MODES[];
+    static const char KEY_PREVIEW_FRAME_RATE_AUTO_MODE[];
+    static const char KEY_PREVIEW_FRAME_RATE_FIXED_MODE[];
+#ifdef QCOM_LEGACY_CAM_PARAMS
+    static const char KEY_CAPTURE_MODE[];
+    static const char KEY_SUPPORTED_CAPTURE_MODES[];
+    static const char KEY_PICTURE_COUNT[];
+    static const char KEY_MAX_BURST_PICTURE_COUNT[];
+    static const char KEY_SUPPORTED_CONTINUOUS_AF[];
+    static const char KEY_SUPPORTED_CAF[];
+    static const char CAPTURE_MODE_NORMAL[];
+    static const char CAPTURE_MODE_BURST[];
+    static const char CAPTURE_MODE_CONTI_BURST[];
+    static const char CAPTURE_MODE_HDR[];
+    static const char CAPTURE_MODE_HJR[];
+    static const char CAPTURE_MODE_PANORAMA[];
+#endif
+#endif
     // The dimensions for captured pictures in pixels (width x height).
     // Example value: "1024x768". Read/write.
     static const char KEY_PICTURE_SIZE[];
     // Supported dimensions for captured pictures in pixels.
     // Example value: "2048x1536,1024x768". Read only.
     static const char KEY_SUPPORTED_PICTURE_SIZES[];
+    //HTC 3D color format
+    static const char KEY_SUPPORTED_3D_FILE_FORMAT[];
     // The image format for captured pictures. See CAMERA_MSG_COMPRESSED_IMAGE
     // in frameworks/base/include/camera/Camera.h.
     // Example value: "jpeg" or PIXEL_FORMAT_XXX constants. Read/write.
@@ -203,6 +262,12 @@
     // header.
     // Example value: "21.0" or "-5". Write only.
     static const char KEY_GPS_ALTITUDE[];
+
+#ifdef QCOM_HARDWARE
+    static const char KEY_SKIN_TONE_ENHANCEMENT[] ;
+    static const char KEY_SUPPORTED_SKIN_TONE_ENHANCEMENT_MODES[] ;
+#endif
+
     // GPS timestamp (UTC in seconds since January 1, 1970). This should be
     // stored in JPEG EXIF header.
     // Example value: "1251192757". Write only.
@@ -222,6 +287,15 @@
     // Supported color effect settings.
     // Example value: "none,mono,sepia". Read only.
     static const char KEY_SUPPORTED_EFFECTS[];
+#ifdef QCOM_HARDWARE
+    //Touch Af/AEC settings.
+    static const char KEY_TOUCH_AF_AEC[];
+    static const char KEY_SUPPORTED_TOUCH_AF_AEC[];
+    //Touch Index for AEC.
+    static const char KEY_TOUCH_INDEX_AEC[];
+    //Touch Index for AF.
+    static const char KEY_TOUCH_INDEX_AF[];
+#endif
     // Current antibanding setting.
     // Example value: "auto" or ANTIBANDING_XXX constants. Read/write.
     static const char KEY_ANTIBANDING[];
@@ -234,6 +308,14 @@
     // Supported scene mode settings.
     // Example value: "auto,night,fireworks". Read only.
     static const char KEY_SUPPORTED_SCENE_MODES[];
+#ifdef QCOM_HARDWARE
+    // Current auto scene detection mode.
+    // Example value: "off" or SCENE_DETECT_XXX constants. Read/write.
+    static const char KEY_SCENE_DETECT[];
+    // Supported auto scene detection settings.
+    // Example value: "off,backlight,snow/cloudy". Read only.
+    static const char KEY_SUPPORTED_SCENE_DETECT[];
+#endif
     // Current flash mode.
     // Example value: "auto" or FLASH_MODE_XXX constants. Read/write.
     static const char KEY_FLASH_MODE[];
@@ -505,6 +587,23 @@
     // captured pictures.
     // Example value: "true" or "false". Read only.
     static const char KEY_VIDEO_SNAPSHOT_SUPPORTED[];
+    static const char KEY_FULL_VIDEO_SNAP_SUPPORTED[];
+
+#ifdef QCOM_HARDWARE
+    static const char KEY_ISO_MODE[];
+    static const char KEY_SUPPORTED_ISO_MODES[];
+    static const char KEY_LENSSHADE[] ;
+    static const char KEY_SUPPORTED_LENSSHADE_MODES[] ;
+
+    static const char KEY_AUTO_EXPOSURE[];
+    static const char KEY_SUPPORTED_AUTO_EXPOSURE[];
+
+    static const char KEY_GPS_LATITUDE_REF[];
+    static const char KEY_GPS_LONGITUDE_REF[];
+    static const char KEY_GPS_ALTITUDE_REF[];
+    static const char KEY_GPS_STATUS[];
+    static const char KEY_EXIF_DATETIME[];
+#endif
 
     // The state of the video stabilization. If set to true, both the
     // preview stream and the recorded video stream are stabilized by
@@ -520,6 +619,23 @@
     // has no effect on still image capture.
     static const char KEY_VIDEO_STABILIZATION[];
 
+#ifdef QCOM_HARDWARE
+    static const char KEY_MEMORY_COLOR_ENHANCEMENT[];
+    static const char KEY_SUPPORTED_MEM_COLOR_ENHANCE_MODES[];
+
+    static const char KEY_POWER_MODE_SUPPORTED[];
+    static const char KEY_POWER_MODE[];
+
+    static const char KEY_ZSL[];
+    static const char KEY_SUPPORTED_ZSL_MODES[];
+
+    static const char KEY_CAMERA_MODE[];
+
+    static const char KEY_VIDEO_HIGH_FRAME_RATE[];
+    static const char KEY_SUPPORTED_VIDEO_HIGH_FRAME_RATE_MODES[];
+    static const char KEY_HIGH_DYNAMIC_RANGE_IMAGING[];
+    static const char KEY_SUPPORTED_HDR_IMAGING_MODES[];
+#endif
     // Returns true if video stabilization is supported. That is, applications
     // can set KEY_VIDEO_STABILIZATION to true and have a stabilized preview
     // stream and record stabilized videos.
@@ -529,6 +645,88 @@
     // Example values: "lowlight,hdr".
     static const char KEY_LIGHTFX[];
 
+#ifdef HAVE_ISO
+    static const char KEY_SUPPORTED_ISO_MODES[];
+    static const char KEY_ISO_MODE[];
+#endif
+
+#ifdef SAMSUNG_CAMERA_HARDWARE
+    static const char KEY_ANTI_SHAKE_MODE[];
+    static const char KEY_METERING[];
+    static const char KEY_WDR[];
+    static const char KEY_WEATHER[];
+    static const char KEY_CITYID[];
+#endif
+
+#ifdef HTC_CAMERA_HARDWARE
+    static const char KEY_TIME_CONS_POST_PROCESSING[];
+    static const char KEY_OIS_MODE[];
+    static const char KEY_APP_OIS_SETTING[];
+    static const char KEY_OIS_SUPPORT[];
+    static const char KEY_CONTIBURST_TYPE[];
+    static const char KEY_CAPTURE_MODE[];
+    static const char CAPTURE_MODE_NORMAL[];
+    static const char CAPTURE_MODE_CONTI_ZOE[];
+    static const char CAPTURE_MODE_CONTI_BURST[];
+    static const char CAPTURE_MODE_CONTI_BURST_ONE_SHOT[];
+    static const char CAPTURE_MODE_HDR[];
+    static const char CAPTURE_MODE_PANORAMA[];
+    static const char CAPTURE_MODE_ZOE[];
+    static const char KEY_CONTI_BURST_STATE[];
+    static const char KEY_SUPPORTED_CAPTURE_MODES[];
+    static const char KEY_MIN_CONTRAST[];
+    static const char KEY_DEF_CONTRAST[];
+    static const char KEY_MIN_SHARPNESS[];
+    static const char KEY_DEF_SHARPNESS[];
+    static const char KEY_MIN_SATURATION[];
+    static const char KEY_DEF_SATURATION[];
+    static const char KEY_SINGLE_ISP_OUTPUT_ENABLED[];
+    static const char POST_PROCESSING_ENABLE[];
+    static const char POST_PROCESSING_BYPASS[];
+    static const char POST_PROCESSING_DELAY[];
+    static const char SCENE_MODE_OFF[];
+    static const char SCENE_MODE_TEXT[];
+    static const char BURST_MODE_LIMIT20[];
+    static const char BURST_MODE_UNLIMITED[];
+    static const char OIS_MODE_OFF[];
+    static const char OIS_MODE_ON[];
+    static const char CONTI_BURST_CAPTURING[];
+    static const char CONTI_BURST_CAPTURE_DONE[];
+    static const char APP_OIS_SETTING_FALSE[];
+    static const char APP_OIS_SETTING_TRUE[];
+    static const char KEY_GPU_EFFECT[];
+    static const char KEY_GPU_EFFECT_PARAM_0[];
+    static const char KEY_GPU_EFFECT_PARAM_1[];
+    static const char KEY_GPU_EFFECT_PARAM_2[];
+    static const char KEY_GPU_EFFECT_PARAM_3[];
+    static const char KEY_FORCE_USE_AUDIO_ENABLED[];
+#endif
+
+#ifdef LG_CAMERA_HARDWARE
+    static const char AUDIO_ZOOM_OFF[];
+    static const char AUDIO_ZOOM_ON[];
+    static const char BEAUTY_SHOT_OFF[];
+    static const char BEAUTY_SHOT_ON[];
+    static const char BURST_SHOT_OFF[];
+    static const char BURST_SHOT_ON[];
+    static const char KEY_AUDIO_ZOOM[];
+    static const char KEY_AUDIO_ZOOM_SUPPORTED[];
+    static const char KEY_BEAUTY_SHOT[];
+    static const char KEY_BEAUTY_SHOT_SUPPORTED[];
+    static const char KEY_BURST_SHOT[];
+    static const char KEY_BURST_SHOT_SUPPORTED[];
+    static const char KEY_FOCUS_MODE_OBJECT_TRACKING[];
+    static const char KEY_FOCUS_MODE_OBJECT_TRACKING_SUPPORTED[];
+    static const char KEY_VIDEO_WDR[];
+    static const char KEY_VIDEO_WDR_SUPPORTED[];
+    static const char VIDEO_WDR_OFF[];
+    static const char VIDEO_WDR_ON[];
+    static const char OBJECT_TRACKING_ON[];
+    static const char OBJECT_TRACKING_OFF[];
+#endif
+
+    static const char KEY_AE_BRACKET_HDR[];
+
     // Value for KEY_ZOOM_SUPPORTED or KEY_SMOOTH_ZOOM_SUPPORTED.
     static const char TRUE[];
     static const char FALSE[];
@@ -536,6 +734,24 @@
     // Value for KEY_FOCUS_DISTANCES.
     static const char FOCUS_DISTANCE_INFINITY[];
 
+#ifdef QCOM_HARDWARE
+    // DENOISE
+    static const char KEY_DENOISE[];
+    static const char KEY_SUPPORTED_DENOISE[];
+
+    //Selectable zone AF.
+    static const char KEY_SELECTABLE_ZONE_AF[];
+    static const char KEY_SUPPORTED_SELECTABLE_ZONE_AF[];
+
+    //Face Detection
+    static const char KEY_FACE_DETECTION[];
+    static const char KEY_SUPPORTED_FACE_DETECTION[];
+
+    //Redeye Reduction
+    static const char KEY_REDEYE_REDUCTION[];
+    static const char KEY_SUPPORTED_REDEYE_REDUCTION[];
+#endif
+
     // Values for white balance settings.
     static const char WHITE_BALANCE_AUTO[];
     static const char WHITE_BALANCE_INCANDESCENT[];
@@ -556,6 +772,24 @@
     static const char EFFECT_WHITEBOARD[];
     static const char EFFECT_BLACKBOARD[];
     static const char EFFECT_AQUA[];
+#ifdef SAMSUNG_CAMERA_HARDWARE
+    static const char EFFECT_CARTOONIZE[];
+    static const char EFFECT_POINT_RED_YELLOW[];
+    static const char EFFECT_POINT_GREEN[];
+    static const char EFFECT_POINT_BLUE[];
+    static const char EFFECT_VINTAGE_COLD[];
+    static const char EFFECT_VINTAGE_WARM[];
+    static const char EFFECT_WASHED[];
+#endif
+#ifdef QCOM_HARDWARE
+    static const char EFFECT_EMBOSS[];
+    static const char EFFECT_SKETCH[];
+    static const char EFFECT_NEON[];
+
+    // Values for Touch AF/AEC
+    static const char TOUCH_AF_AEC_OFF[] ;
+    static const char TOUCH_AF_AEC_ON[] ;
+#endif
 
     // Values for antibanding settings.
     static const char ANTIBANDING_AUTO[];
@@ -580,6 +814,7 @@
 
     // Values for scene mode settings.
     static const char SCENE_MODE_AUTO[];
+    static const char SCENE_MODE_ASD[];
     static const char SCENE_MODE_ACTION[];
     static const char SCENE_MODE_PORTRAIT[];
     static const char SCENE_MODE_LANDSCAPE[];
@@ -594,6 +829,11 @@
     static const char SCENE_MODE_SPORTS[];
     static const char SCENE_MODE_PARTY[];
     static const char SCENE_MODE_CANDLELIGHT[];
+#ifdef QCOM_HARDWARE
+    static const char SCENE_MODE_BACKLIGHT[];
+    static const char SCENE_MODE_FLOWERS[];
+    static const char SCENE_MODE_AR[];
+#endif
     // Applications are looking for a barcode. Camera driver will be optimized
     // for barcode reading.
     static const char SCENE_MODE_BARCODE[];
@@ -604,8 +844,15 @@
 
     // Pixel color formats for KEY_PREVIEW_FORMAT, KEY_PICTURE_FORMAT,
     // and KEY_VIDEO_FRAME_FORMAT
+#ifdef QCOM_HARDWARE
+    static const char SCENE_DETECT_OFF[];
+    static const char SCENE_DETECT_ON[];
+#endif
     static const char PIXEL_FORMAT_YUV422SP[];
     static const char PIXEL_FORMAT_YUV420SP[]; // NV21
+#ifdef QCOM_HARDWARE
+    static const char PIXEL_FORMAT_YUV420SP_ADRENO[]; // ADRENO
+#endif
     static const char PIXEL_FORMAT_YUV422I[]; // YUY2
     static const char PIXEL_FORMAT_YUV420P[]; // YV12
     static const char PIXEL_FORMAT_RGB565[];
@@ -614,9 +861,16 @@
     // Raw bayer format used for images, which is 10 bit precision samples
     // stored in 16 bit words. The filter pattern is RGGB.
     static const char PIXEL_FORMAT_BAYER_RGGB[];
+
     // Pixel format is not known to the framework
     static const char PIXEL_FORMAT_ANDROID_OPAQUE[];
 
+#ifdef QCOM_HARDWARE
+    static const char PIXEL_FORMAT_RAW[];
+    static const char PIXEL_FORMAT_YV12[]; // NV21
+    static const char PIXEL_FORMAT_NV12[]; //NV12
+#endif
+
     // Values for focus mode settings.
     // Auto-focus mode. Applications should call
     // CameraHardwareInterface.autoFocus to start the focus in this mode.
@@ -674,6 +928,161 @@
     // High-dynamic range mode
     static const char LIGHTFX_HDR[];
 
+#ifdef QCOM_HARDWARE
+#ifdef QCOM_LEGACY_CAM_PARAMS
+    static const char FOCUS_MODE_CONTINUOUS_CAMERA[];
+
+    // Values for Continuous AF
+    static const char CAF_OFF[] ;
+    static const char CAF_ON[] ;
+    // Proprietaries from CodeAurora use these...
+    static const char CONTINUOUS_AF_OFF[] ;
+    static const char CONTINUOUS_AF_ON[] ;
+    static const char KEY_CONTINUOUS_AF[] ;
+    static const char KEY_CAF[] ;
+    static const char KEY_TAKING_PICTURE_ZOOM[];
+    static const char KEY_PANORAMA_MODE[];
+    static const char PANORAMA_MODE_NOT_INPROGRESS[];
+    static const char PANORAMA_MODE_INPROGRESS[];
+#endif
+    // Normal focus mode. Applications should call
+    // CameraHardwareInterface.autoFocus to start the focus in this mode.
+    static const char FOCUS_MODE_NORMAL[];
+    static const char ISO_AUTO[];
+    static const char ISO_HJR[] ;
+    static const char ISO_100[];
+    static const char ISO_200[] ;
+    static const char ISO_400[];
+    static const char ISO_800[];
+    static const char ISO_1600[];
+    static const char ISO_3200[];
+    static const char ISO_6400[];
+    // Values for Lens Shading
+    static const char LENSSHADE_ENABLE[] ;
+    static const char LENSSHADE_DISABLE[] ;
+
+    // Values for auto exposure settings.
+    static const char AUTO_EXPOSURE_FRAME_AVG[];
+    static const char AUTO_EXPOSURE_CENTER_WEIGHTED[];
+    static const char AUTO_EXPOSURE_SPOT_METERING[];
+
+    static const char KEY_SHARPNESS[];
+    static const char KEY_MAX_SHARPNESS[];
+#ifdef QCOM_LEGACY_CAM_PARAMS
+    static const char KEY_MIN_SHARPNESS[];
+#endif
+    static const char KEY_CONTRAST[];
+    static const char KEY_MAX_CONTRAST[];
+#ifdef QCOM_LEGACY_CAM_PARAMS
+    static const char KEY_MIN_CONTRAST[];
+#endif
+    static const char KEY_SATURATION[];
+    static const char KEY_MAX_SATURATION[];
+#ifdef QCOM_LEGACY_CAM_PARAMS
+    static const char KEY_MIN_SATURATION[];
+#endif
+
+    static const char KEY_HISTOGRAM[] ;
+    static const char KEY_SUPPORTED_HISTOGRAM_MODES[] ;
+    // Values for HISTOGRAM
+    static const char HISTOGRAM_ENABLE[] ;
+    static const char HISTOGRAM_DISABLE[] ;
+
+    // Values for SKIN TONE ENHANCEMENT
+    static const char SKIN_TONE_ENHANCEMENT_ENABLE[] ;
+    static const char SKIN_TONE_ENHANCEMENT_DISABLE[] ;
+
+    // Values for Denoise
+    static const char DENOISE_OFF[] ;
+    static const char DENOISE_ON[] ;
+
+    // Values for auto exposure settings.
+    static const char SELECTABLE_ZONE_AF_AUTO[];
+    static const char SELECTABLE_ZONE_AF_SPOT_METERING[];
+    static const char SELECTABLE_ZONE_AF_CENTER_WEIGHTED[];
+    static const char SELECTABLE_ZONE_AF_FRAME_AVERAGE[];
+
+    // Values for Face Detection settings.
+    static const char FACE_DETECTION_OFF[];
+    static const char FACE_DETECTION_ON[];
+
+    // Values for HTC 3D image settings.
+    static const char FILE_FORMAT_MPO[];
+    static const char FILE_FORMAT_JPS[];
+
+    // Values for MCE settings.
+    static const char MCE_ENABLE[];
+    static const char MCE_DISABLE[];
+
+    // Values for ZSL settings.
+    static const char ZSL_OFF[];
+    static const char ZSL_ON[];
+
+    // Values for HDR Bracketing settings.
+    static const char AE_BRACKET_HDR_OFF[];
+    static const char AE_BRACKET_HDR[];
+    static const char AE_BRACKET[];
+
+    //POWER MODE
+    static const char LOW_POWER[];
+    static const char NORMAL_POWER[];
+
+    // Values for HFR settings.
+    static const char VIDEO_HFR_OFF[];
+    static const char VIDEO_HFR_2X[];
+    static const char VIDEO_HFR_3X[];
+    static const char VIDEO_HFR_4X[];
+
+    // Values for Redeye Reduction settings.
+    static const char REDEYE_REDUCTION_ENABLE[];
+    static const char REDEYE_REDUCTION_DISABLE[];
+    // Values for HDR settings.
+    static const char HDR_ENABLE[];
+    static const char HDR_DISABLE[];
+
+#if defined(QCOM_HARDWARE) && defined(SAMSUNG_CAMERA_LEGACY)
+    static const char FOCUS_MODE_FACEDETECT[];
+    static const char FOCUS_MODE_TOUCHAF[];
+    static const char ISO_50[];
+    static const char KEY_ANTI_SHAKE_MODE[];
+    static const char KEY_AUTO_CONTRAST[];
+    static const char KEY_BEAUTY_MODE[];
+    static const char KEY_BLUR_MODE[];
+    static const char KEY_VINTAGE_MODE[];
+    static const char KEY_WDR_MODE[];
+    static const char VINTAGE_MODE_BNW[];
+    static const char VINTAGE_MODE_COOL[];
+    static const char VINTAGE_MODE_NORMAL[];
+    static const char VINTAGE_MODE_OFF[];
+    static const char VINTAGE_MODE_WARM[];
+    static const char SCENE_MODE_DAWN[];
+    static const char SCENE_MODE_DUSKDAWN[];
+    static const char SCENE_MODE_FALL[];
+    static const char SCENE_MODE_FALL_COLOR[];
+    static const char SCENE_MODE_TEXT[];
+#endif
+
+   // Values for Redeye Reduction settings.
+   // static const char REDEYE_REDUCTION_ENABLE[];
+   // static const char REDEYE_REDUCTION_DISABLE[];
+   // Values for HDR settings.
+   //    static const char HDR_ENABLE[];
+   //    static const char HDR_DISABLE[];
+
+    enum {
+        CAMERA_ORIENTATION_UNKNOWN = 0,
+        CAMERA_ORIENTATION_PORTRAIT = 1,
+        CAMERA_ORIENTATION_LANDSCAPE = 2,
+    };
+    int getOrientation() const;
+    void setOrientation(int orientation);
+    void setPreviewFpsRange(int minFPS,int maxFPS);
+#ifdef QCOM_LEGACY_CAM_PARAMS
+    void setPostviewSize(int x, int y);
+#endif
+    void getSupportedHfrSizes(Vector<Size> &sizes) const;
+#endif
+
 private:
     DefaultKeyedVector<String8,String8>    mMap;
 };
diff --git a/include/media/AudioParameter.h b/include/media/AudioParameter.h
index 891bc4b..bce7f21 100644
--- a/include/media/AudioParameter.h
+++ b/include/media/AudioParameter.h
@@ -1,4 +1,7 @@
 /*
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ * Not a Contribution.
+ *
  * Copyright (C) 2008-2011 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -48,6 +51,16 @@
     static const char * const keyFrameCount;
     static const char * const keyInputSource;
     static const char * const keyScreenState;
+#ifdef QCOM_HARDWARE
+    static const char * const keyHandleFm;
+    static const char * const keyVoipCheck;
+    static const char * const keyFluenceType;
+    static const char * const keySSR;
+    static const char * const keyHandleA2dpDevice;
+    static const char * const keyADSPStatus;
+    static const char * const keyCanOpenProxy;
+    static const char * const keyFmVolume;
+#endif
 
     String8 toString();
 
diff --git a/include/media/AudioRecord.h b/include/media/AudioRecord.h
index 052064d..e4cb560 100644
--- a/include/media/AudioRecord.h
+++ b/include/media/AudioRecord.h
@@ -210,8 +210,13 @@
             audio_format_t format() const   { return mFormat; }
             uint32_t    channelCount() const    { return mChannelCount; }
             size_t      frameCount() const  { return mFrameCount; }
+#ifdef QCOM_HARDWARE
+            size_t      frameSize() const;
+            audio_source_t inputSource() const;
+#else
             size_t      frameSize() const   { return mFrameSize; }
             audio_source_t inputSource() const  { return mInputSource; }
+#endif
 
     /* After it's created the track is not active. Call start() to
      * make it active. If set, the callback will start being called.
diff --git a/include/media/AudioSystem.h b/include/media/AudioSystem.h
index 225ef76..cad455d 100644
--- a/include/media/AudioSystem.h
+++ b/include/media/AudioSystem.h
@@ -1,4 +1,6 @@
 /*
+ * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+ * Not a Contribution.
  * Copyright (C) 2008 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -23,6 +25,9 @@
 #include <system/audio_policy.h>
 #include <utils/Errors.h>
 #include <utils/Mutex.h>
+#ifdef QCOM_HARDWARE
+#include <media/AudioParameter.h>
+#endif
 
 namespace android {
 
@@ -147,6 +152,9 @@
         INPUT_CLOSED,
         INPUT_CONFIG_CHANGED,
         STREAM_CONFIG_CHANGED,
+#ifdef QCOM_HARDWARE
+        EFFECT_CONFIG_CHANGED,
+#endif
         NUM_CONFIG_EVENTS
     };
 
diff --git a/include/media/AudioTrack.h b/include/media/AudioTrack.h
index 4736369..40a9f1f 100644
--- a/include/media/AudioTrack.h
+++ b/include/media/AudioTrack.h
@@ -1,4 +1,6 @@
 /*
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ * Not a Contribution.
  * Copyright (C) 2007 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -22,7 +24,10 @@
 #include <media/AudioTimestamp.h>
 #include <media/IAudioTrack.h>
 #include <utils/threads.h>
-
+#ifdef QCOM_HARDWARE
+#include <media/IDirectTrack.h>
+#include <media/IDirectTrackClient.h>
+#endif
 namespace android {
 
 // ----------------------------------------------------------------------------
@@ -33,7 +38,12 @@
 
 // ----------------------------------------------------------------------------
 
+#ifdef QCOM_HARDWARE
+class AudioTrack : public BnDirectTrackClient,
+                   virtual public RefBase
+#else
 class AudioTrack : public RefBase
+#endif
 {
 public:
     enum channel_index {
@@ -66,6 +76,9 @@
         EVENT_NEW_TIMESTAMP = 8,    // Delivered periodically and when there's a significant change
                                     // in the mapping from frame position to presentation time.
                                     // See AudioTimestamp for the information included with event.
+#ifdef QCOM_HARDWARE
+        EVENT_HW_FAIL = 9,          // ADSP failure.
+#endif
     };
 
     /* Client should declare Buffer on the stack and pass address to obtainBuffer()
@@ -218,9 +231,8 @@
     /* Terminates the AudioTrack and unregisters it from AudioFlinger.
      * Also destroys all resources associated with the AudioTrack.
      */
-protected:
+
                         virtual ~AudioTrack();
-public:
 
     /* Initialize an AudioTrack that was created using the AudioTrack() constructor.
      * Don't call set() more than once, or after the AudioTrack() constructors that take parameters.
@@ -264,7 +276,11 @@
      * This includes the latency due to AudioTrack buffer size, AudioMixer (if any)
      * and audio hardware driver.
      */
+#ifdef QCOM_HARDWARE
+            uint32_t    latency() const;
+#else
             uint32_t    latency() const     { return mLatency; }
+#endif
 
     /* getters, see constructors and set() */
 
@@ -582,7 +598,11 @@
      * consider implementing that at application level, based on the low resolution timestamps.
      * Returns NO_ERROR if timestamp is valid.
      */
-            status_t    getTimestamp(AudioTimestamp& timestamp);
+      virtual status_t    getTimestamp(AudioTimestamp& timestamp);
+#ifdef QCOM_HARDWARE
+      virtual void notify(int msg);
+      virtual status_t    getTimeStamp(uint64_t *tstamp);
+#endif
 
 protected:
     /* copying audio tracks is not allowed */
@@ -653,6 +673,9 @@
             bool     isOffloaded() const
                 { return (mFlags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) != 0; }
 
+#ifdef QCOM_HARDWARE
+    sp<IDirectTrack>        mDirectTrack;
+#endif
     // Next 3 fields may be changed if IAudioTrack is re-created, but always != 0
     sp<IAudioTrack>         mAudioTrack;
     sp<IMemory>             mCblkMemory;
@@ -720,11 +743,18 @@
     uint32_t                mUpdatePeriod;          // in frames, zero means no EVENT_NEW_POS
 
     audio_output_flags_t    mFlags;
+#ifdef QCOM_HARDWARE
+    sp<IAudioFlinger>       mAudioFlinger;
+    audio_io_handle_t       mAudioDirectOutput;
+#endif
     int                     mSessionId;
     int                     mAuxEffectId;
 
     mutable Mutex           mLock;
 
+#ifdef QCOM_HARDWARE
+    void*                   mObserver;
+#endif
     bool                    mIsTimed;
     int                     mPreviousPriority;          // before start()
     SchedPolicy             mPreviousSchedulingGroup;
diff --git a/include/media/IAudioFlinger.h b/include/media/IAudioFlinger.h
index 899d79f..698b584 100644
--- a/include/media/IAudioFlinger.h
+++ b/include/media/IAudioFlinger.h
@@ -1,5 +1,7 @@
 /*
- * Copyright (C) 2007 The Android Open Source Project
+ * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+ * Not a contribution.
+ * Copyright (C) 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.
@@ -24,6 +26,10 @@
 #include <utils/RefBase.h>
 #include <utils/Errors.h>
 #include <binder/IInterface.h>
+#ifdef QCOM_HARDWARE
+#include <media/IDirectTrack.h>
+#include <media/IDirectTrackClient.h>
+#endif
 #include <media/IAudioTrack.h>
 #include <media/IAudioRecord.h>
 #include <media/IAudioFlingerClient.h>
@@ -50,6 +56,9 @@
         TRACK_TIMED   = 1,  // client requests a TimedAudioTrack
         TRACK_FAST    = 2,  // client requests a fast AudioTrack or AudioRecord
         TRACK_OFFLOAD = 4,  // client requests offload to hw codec
+#ifdef QCOM_HARDWARE
+        TRACK_VOICE_COMMUNICATION = 8, //client uses voice communication
+#endif
     };
     typedef uint32_t track_flags_t;
 
@@ -77,6 +86,21 @@
                                 int clientUid,
                                 status_t *status) = 0;
 
+#ifdef QCOM_HARDWARE
+    /* create a direct audio track and registers it with AudioFlinger.
+     * return null if the track cannot be created.
+     */
+    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) = 0;
+#endif
+
     virtual sp<IAudioRecord> openRecord(
                                 audio_io_handle_t input,
                                 uint32_t sampleRate,
diff --git a/include/media/IDirectTrack.h b/include/media/IDirectTrack.h
new file mode 100644
index 0000000..bfb29ec
--- /dev/null
+++ b/include/media/IDirectTrack.h
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ * Not a Contribution.
+ *
+ * Copyright (C) 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.
+ */
+
+#ifndef ANDROID_IDIRECTTRACK_H
+#define ANDROID_IDIRECTTRACK_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <utils/RefBase.h>
+#include <utils/Errors.h>
+#include <binder/IInterface.h>
+#include <binder/IMemory.h>
+
+
+namespace android {
+
+// ----------------------------------------------------------------------------
+
+class IDirectTrack : public IInterface
+{
+public:
+    DECLARE_META_INTERFACE(DirectTrack);
+
+    /* After it's created the track is not active. Call start() to
+     * make it active. If set, the callback will start being called.
+     */
+    virtual status_t    start() = 0;
+
+    /* Stop a track. If set, the callback will cease being called and
+     * obtainBuffer will return an error. Buffers that are already released
+     * will be processed, unless flush() is called.
+     */
+    virtual void        stop() = 0;
+
+    /* flush a stopped track. All pending buffers are discarded.
+     * This function has no effect if the track is not stoped.
+     */
+    virtual void        flush() = 0;
+
+    /* mute or unmutes this track.
+     * While mutted, the callback, if set, is still called.
+     */
+    virtual void        mute(bool) = 0;
+
+    /* Pause a track. If set, the callback will cease being called and
+     * obtainBuffer will return an error. Buffers that are already released
+     * will be processed, unless flush() is called.
+     */
+    virtual void        pause() = 0;
+
+    /* set volume for both left and right channels.
+     */
+    virtual void        setVolume(float l, float r) = 0;
+
+    virtual ssize_t     write(const void*, size_t) =  0;
+
+    virtual int64_t     getTimeStamp() =  0;
+};
+
+// ----------------------------------------------------------------------------
+
+class BnDirectTrack : public BnInterface<IDirectTrack>
+{
+public:
+    virtual status_t    onTransact( uint32_t code,
+                                    const Parcel& data,
+                                    Parcel* reply,
+                                    uint32_t flags = 0);
+};
+
+// ----------------------------------------------------------------------------
+
+}; // namespace android
+
+#endif // ANDROID_IAUDIOTRACK_H
diff --git a/include/media/IDirectTrackClient.h b/include/media/IDirectTrackClient.h
new file mode 100644
index 0000000..703df35
--- /dev/null
+++ b/include/media/IDirectTrackClient.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ * Not a Contribution.
+ *
+ * Copyright (C) 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.
+ */
+
+#ifndef ANDROID_IDIRECTTRACKCLIENT_H
+#define ANDROID_IDIRECTTRACKCLIENT_H
+
+#include <utils/RefBase.h>
+#include <binder/IInterface.h>
+#include <binder/Parcel.h>
+
+namespace android {
+
+class IDirectTrackClient: public IInterface
+{
+public:
+    DECLARE_META_INTERFACE(DirectTrackClient);
+
+    virtual void notify(int msg) = 0;
+};
+
+// ----------------------------------------------------------------------------
+
+class BnDirectTrackClient: public BnInterface<IDirectTrackClient>
+{
+public:
+    virtual status_t    onTransact( uint32_t code,
+                                    const Parcel& data,
+                                    Parcel* reply,
+                                    uint32_t flags = 0);
+};
+
+}; // namespace android
+
+#endif // ANDROID_IDIRECTTRACKCLIENT_H
diff --git a/include/media/MediaPlayerInterface.h b/include/media/MediaPlayerInterface.h
index 26d8729..a1cbe07 100644
--- a/include/media/MediaPlayerInterface.h
+++ b/include/media/MediaPlayerInterface.h
@@ -1,4 +1,6 @@
 /*
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ * Not a Contribution.
  * Copyright (C) 2007 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -50,6 +52,7 @@
     // The shared library with the test player is passed passed as an
     // argument to the 'test:' url in the setDataSource call.
     TEST_PLAYER = 5,
+    DASH_PLAYER = 6,
 };
 
 
@@ -78,8 +81,12 @@
             CB_EVENT_FILL_BUFFER,   // Request to write more data to buffer.
             CB_EVENT_STREAM_END,    // Sent after all the buffers queued in AF and HW are played
                                     // back (after stop is called)
-            CB_EVENT_TEAR_DOWN      // The AudioTrack was invalidated due to use case change:
+            CB_EVENT_TEAR_DOWN,      // The AudioTrack was invalidated due to use case change:
                                     // Need to re-evaluate offloading options
+#ifdef QCOM_HARDWARE
+            CB_EVENT_UNDERRUN,
+            CB_EVENT_HW_FAIL
+#endif
         };
 
         // Callback returns the number of bytes actually written to the buffer.
@@ -95,6 +102,9 @@
         virtual ssize_t     channelCount() const = 0;
         virtual ssize_t     frameSize() const = 0;
         virtual uint32_t    latency() const = 0;
+#ifdef QCOM_HARDWARE
+        virtual audio_stream_type_t    streamType() const {return AUDIO_STREAM_DEFAULT;}
+#endif
         virtual float       msecsPerFrame() const = 0;
         virtual status_t    getPosition(uint32_t *position) const = 0;
         virtual status_t    getFramesWritten(uint32_t *frameswritten) const = 0;
@@ -122,9 +132,13 @@
 
         virtual status_t    setPlaybackRatePermille(int32_t rate) { return INVALID_OPERATION; }
         virtual bool        needsTrailingPadding() { return true; }
-
         virtual status_t    setParameters(const String8& keyValuePairs) { return NO_ERROR; };
         virtual String8     getParameters(const String8& keys) { return String8::empty(); };
+
+#ifdef QCOM_HARDWARE
+        virtual ssize_t     sampleRate() const {return 0;};
+        virtual status_t    getTimeStamp(uint64_t *tstamp) {return 0;};
+#endif
     };
 
                         MediaPlayerBase() : mCookie(0), mNotify(0) {}
diff --git a/include/media/MediaProfiles.h b/include/media/MediaProfiles.h
index 9fc962c..ec3eb9b 100644
--- a/include/media/MediaProfiles.h
+++ b/include/media/MediaProfiles.h
@@ -32,8 +32,23 @@
     CAMCORDER_QUALITY_480P = 4,
     CAMCORDER_QUALITY_720P = 5,
     CAMCORDER_QUALITY_1080P = 6,
+#ifdef QCOM_HARDWARE
     CAMCORDER_QUALITY_QVGA = 7,
-    CAMCORDER_QUALITY_LIST_END = 7,
+    CAMCORDER_QUALITY_FWVGA = 8,
+    CAMCORDER_QUALITY_WVGA = 9,
+    CAMCORDER_QUALITY_VGA = 10,
+    CAMCORDER_QUALITY_WQVGA = 11,
+    CAMCORDER_QUALITY_4kUHD = 12,
+    CAMCORDER_QUALITY_4kDCI = 13,
+    CAMCORDER_QUALITY_LIST_END = 13,
+#else
+    CAMCORDER_QUALITY_QVGA = 11,
+    CAMCORDER_QUALITY_FWVGA = 7,
+    CAMCORDER_QUALITY_WVGA = 8,
+    CAMCORDER_QUALITY_VGA = 9,
+    CAMCORDER_QUALITY_WQVGA = 10,
+    CAMCORDER_QUALITY_LIST_END = 11,
+#endif
 
     CAMCORDER_QUALITY_TIME_LAPSE_LIST_START = 1000,
     CAMCORDER_QUALITY_TIME_LAPSE_LOW  = 1000,
@@ -44,7 +59,15 @@
     CAMCORDER_QUALITY_TIME_LAPSE_720P = 1005,
     CAMCORDER_QUALITY_TIME_LAPSE_1080P = 1006,
     CAMCORDER_QUALITY_TIME_LAPSE_QVGA = 1007,
+#ifdef QCOM_HARDWARE
+    CAMCORDER_QUALITY_TIME_LAPSE_FWVGA = 1008,
+    CAMCORDER_QUALITY_TIME_LAPSE_WVGA = 1009,
+    CAMCORDER_QUALITY_TIME_LAPSE_VGA = 1010,
+    CAMCORDER_QUALITY_TIME_LAPSE_WQVGA = 1011,
+    CAMCORDER_QUALITY_TIME_LAPSE_LIST_END = 1011,
+#else
     CAMCORDER_QUALITY_TIME_LAPSE_LIST_END = 1007,
+#endif
 };
 
 /**
@@ -456,6 +479,10 @@
     static VideoEncoderCap* createDefaultH263VideoEncoderCap();
     static VideoEncoderCap* createDefaultM4vVideoEncoderCap();
     static AudioEncoderCap* createDefaultAmrNBEncoderCap();
+#ifdef QCOM_HARDWARE
+    static AudioEncoderCap* createDefaultAacEncoderCap();
+    static AudioEncoderCap* createDefaultLpcmEncoderCap();
+#endif
 
     static int findTagForName(const NameToTagMap *map, size_t nMappings, const char *name);
 
diff --git a/include/media/mediaplayer.h b/include/media/mediaplayer.h
index 4c05fc3..24583ef 100644
--- a/include/media/mediaplayer.h
+++ b/include/media/mediaplayer.h
@@ -50,6 +50,9 @@
     MEDIA_ERROR             = 100,
     MEDIA_INFO              = 200,
     MEDIA_SUBTITLE_DATA     = 201,
+#ifdef QCOM_HARDWARE
+    MEDIA_QOE               = 300,
+#endif
 };
 
 // Generic error codes for the media player framework.  Errors are fatal, the
diff --git a/include/media/mediarecorder.h b/include/media/mediarecorder.h
index 88a42a0..24dfa0f 100644
--- a/include/media/mediarecorder.h
+++ b/include/media/mediarecorder.h
@@ -67,6 +67,11 @@
     /* H.264/AAC data encapsulated in MPEG2/TS */
     OUTPUT_FORMAT_MPEG2TS = 8,
 
+#ifdef QCOM_HARDWARE
+    OUTPUT_FORMAT_QCP = 9, // QCP file format
+    OUTPUT_FORMAT_THREE_GPP2 = 10, /*3GPP2*/
+    OUTPUT_FORMAT_WAVE = 11, /*WAVE*/
+#endif
     OUTPUT_FORMAT_LIST_END // must be last - used to validate format type
 };
 
@@ -77,7 +82,11 @@
     AUDIO_ENCODER_AAC = 3,
     AUDIO_ENCODER_HE_AAC = 4,
     AUDIO_ENCODER_AAC_ELD = 5,
-
+#ifdef QCOM_HARDWARE
+    AUDIO_ENCODER_EVRC = 6,
+    AUDIO_ENCODER_QCELP = 7,
+    AUDIO_ENCODER_LPCM = 8,
+#endif
     AUDIO_ENCODER_LIST_END // must be the last - used to validate the audio encoder type
 };
 
@@ -118,6 +127,9 @@
     MEDIA_RECORDER_EVENT_LIST_START               = 1,
     MEDIA_RECORDER_EVENT_ERROR                    = 1,
     MEDIA_RECORDER_EVENT_INFO                     = 2,
+#ifdef QCOM_HARDWARE
+    MEDIA_RECORDER_MSG_COMPRESSED_IMAGE           = 8, // mzhu: TODO, where to put this?
+#endif
     MEDIA_RECORDER_EVENT_LIST_END                 = 99,
 
     // Track related event types
diff --git a/include/media/stagefright/ACodec.h b/include/media/stagefright/ACodec.h
index bf3a998..18a3100 100644
--- a/include/media/stagefright/ACodec.h
+++ b/include/media/stagefright/ACodec.h
@@ -200,6 +200,9 @@
 
     bool mChannelMaskPresent;
     int32_t mChannelMask;
+#ifdef QCOM_HARDWARE
+    bool mInSmoothStreamingMode;
+#endif
     unsigned mDequeueCounter;
     bool mStoreMetaDataInOutputBuffers;
     int32_t mMetaDataBuffersToSubmit;
@@ -219,6 +222,9 @@
     status_t submitOutputMetaDataBuffer();
     void signalSubmitOutputMetaDataBufferIfEOS_workaround();
     status_t allocateOutputBuffersFromNativeWindow();
+#ifdef USE_SAMSUNG_COLORFORMAT
+    void setNativeWindowColorFormat(OMX_COLOR_FORMATTYPE &eNativeColorFormat);
+#endif
     status_t cancelBufferToNativeWindow(BufferInfo *info);
     status_t freeOutputBuffersNotOwnedByComponent();
     BufferInfo *dequeueBufferFromNativeWindow();
diff --git a/include/media/stagefright/AudioPlayer.h b/include/media/stagefright/AudioPlayer.h
index 14afb85..f1249bb 100644
--- a/include/media/stagefright/AudioPlayer.h
+++ b/include/media/stagefright/AudioPlayer.h
@@ -1,4 +1,6 @@
 /*
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ * Not a Contribution.
  * Copyright (C) 2009 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -51,27 +53,27 @@
     virtual ~AudioPlayer();
 
     // Caller retains ownership of "source".
-    void setSource(const sp<MediaSource> &source);
+    virtual void setSource(const sp<MediaSource> &source);
 
     // Return time in us.
     virtual int64_t getRealTimeUs();
 
-    status_t start(bool sourceAlreadyStarted = false);
+    virtual status_t start(bool sourceAlreadyStarted = false);
 
-    void pause(bool playPendingSamples = false);
-    status_t resume();
+    virtual void pause(bool playPendingSamples = false);
+    virtual status_t resume();
 
     // Returns the timestamp of the last buffer played (in us).
-    int64_t getMediaTimeUs();
+    virtual int64_t getMediaTimeUs();
 
     // Returns true iff a mapping is established, i.e. the AudioPlayer
     // has played at least one frame of audio.
-    bool getMediaTimeMapping(int64_t *realtime_us, int64_t *mediatime_us);
+    virtual bool getMediaTimeMapping(int64_t *realtime_us, int64_t *mediatime_us);
 
-    status_t seekTo(int64_t time_us);
+    virtual status_t seekTo(int64_t time_us);
 
-    bool isSeeking();
-    bool reachedEOS(status_t *finalStatus);
+    virtual bool isSeeking();
+    virtual bool reachedEOS(status_t *finalStatus);
 
     status_t setPlaybackRatePermille(int32_t ratePermille);
 
@@ -101,6 +103,9 @@
     int64_t mSeekTimeUs;
 
     bool mStarted;
+#ifdef QCOM_HARDWARE
+    bool mSourcePaused;
+#endif
 
     bool mIsFirstBuffer;
     status_t mFirstBufferResult;
diff --git a/include/media/stagefright/AudioSource.h b/include/media/stagefright/AudioSource.h
index 4c9aaad..3b79d0a 100644
--- a/include/media/stagefright/AudioSource.h
+++ b/include/media/stagefright/AudioSource.h
@@ -23,7 +23,7 @@
 #include <media/stagefright/MediaSource.h>
 #include <media/stagefright/MediaBuffer.h>
 #include <utils/List.h>
-
+#include <utils/String8.h>
 #include <system/audio.h>
 
 namespace android {
@@ -85,6 +85,7 @@
     int64_t mInitialReadTimeUs;
     int64_t mNumFramesReceived;
     int64_t mNumClientOwnedBuffers;
+    int64_t mAutoRampStartUs;
 
     List<MediaBuffer * > mBuffersReceived;
 
@@ -103,6 +104,16 @@
 
     AudioSource(const AudioSource &);
     AudioSource &operator=(const AudioSource &);
+#ifdef QCOM_HARDWARE
+public:
+    AudioSource(
+        audio_source_t inputSource, const sp<MetaData>& meta );
+private:
+    audio_format_t mFormat;
+    String8 mMime;
+    int32_t mMaxBufferSize;
+    int64_t bufferDurationUs( ssize_t n );
+#endif
 };
 
 }  // namespace android
diff --git a/include/media/stagefright/ExtendedCodec.h b/include/media/stagefright/ExtendedCodec.h
new file mode 100644
index 0000000..eeb31d6
--- /dev/null
+++ b/include/media/stagefright/ExtendedCodec.h
@@ -0,0 +1,177 @@
+/*
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials provided
+ *      with the distribution.
+ *     * Neither the name of The Linux Foundation nor the names of its
+ *      contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef EXTENDED_CODEC_H_
+#define EXTENDED_CODEC_H_
+
+#include <android/native_window.h>
+#include <media/IOMX.h>
+#include <media/stagefright/MediaBuffer.h>
+#include <media/stagefright/MediaSource.h>
+#include <media/stagefright/foundation/AMessage.h>
+#include <media/stagefright/foundation/AString.h>
+#include <utils/threads.h>
+
+#include <OMX_Audio.h>
+
+namespace android {
+
+struct MediaCodecList;
+struct OMXCodec;
+
+enum{
+    kRequiresWMAProComponent = 0x40000000,
+};
+
+
+struct ExtendedCodec {
+
+    enum {
+        kPortIndexInput  = 0,
+        kPortIndexOutput = 1
+    };
+    static status_t convertMetaDataToMessage(
+            const sp<MetaData> &meta, sp<AMessage> *format);
+
+    static uint32_t getComponentQuirks (
+            const MediaCodecList *list, size_t index);
+
+    static status_t setAudioFormat(
+            const sp<MetaData> &meta, const char* mime,
+            sp<IOMX> OMXhandle,IOMX::node_id nodeID,
+            bool isEncoder);
+
+    static status_t setAudioFormat(
+            const sp<AMessage> &msg, const char* mime,
+            sp<IOMX> OMXhandle,IOMX::node_id nodeID,
+            bool isEncoder);
+
+    static status_t setVideoInputFormat(
+            const char *mime,
+            OMX_VIDEO_CODINGTYPE *compressionFormat);
+
+    static status_t setVideoOutputFormat(
+            const char *mime,
+            OMX_VIDEO_CODINGTYPE *compressionFormat);
+
+    static status_t getSupportedAudioFormatInfo(
+            const AString* mime,
+            sp<IOMX> OMXhandle,
+            IOMX::node_id nodeID,
+            int portIndex,
+            int* channelCount);
+
+    static status_t handleSupportedAudioFormats(
+            int format, AString* mime);
+
+    static const char* overrideComponentName(
+            uint32_t quirks, const sp<MetaData> &meta);
+
+    static void overrideComponentName(
+            uint32_t quirks, const sp<AMessage> &msg,
+            AString* componentName);
+
+    static void getRawCodecSpecificData(
+            const sp<MetaData> &meta,
+            const void* &data,
+            size_t& size);
+
+    static sp<ABuffer> getRawCodecSpecificData(
+            const sp<AMessage> &msg);
+
+    static void getAacCodecSpecificData(
+            const sp<MetaData> &meta,
+            const void* &data,
+            size_t& size);
+
+    static sp<ABuffer> getAacCodecSpecificData(
+            const sp<AMessage> &msg);
+
+    static status_t setSupportedRole(
+            const sp<IOMX> &omx, IOMX::node_id node,
+            bool isEncoder, const char *mime);
+
+    static void configureFramePackingFormat(
+            const sp<AMessage> &msg, sp<IOMX> OMXhandle,
+            IOMX::node_id nodeID, const char* componentName);
+
+    static void configureFramePackingFormat(
+            const sp<MetaData> &meta, sp<IOMX> OMXhandle,
+            IOMX::node_id nodeID, const char* componentName);
+
+    static void configureVideoDecoder(
+            const sp<MetaData> &meta, const char* mime,
+            sp<IOMX> OMXhandle, const uint32_t flags,
+            IOMX::node_id nodeID, const char* componentName);
+
+    static void configureVideoDecoder(
+            const sp<AMessage> &msg, const char* mime,
+            sp<IOMX> OMXhandle, const uint32_t flags,
+            IOMX::node_id nodeID, const char* componentName);
+
+    static void enableSmoothStreaming(
+            const sp<IOMX> &omx, IOMX::node_id nodeID, bool* isEnabled,
+            const char* componentName);
+
+    static bool useHWAACDecoder(const char *mime);
+
+private:
+    static const char* getMsgKey(int key );
+
+    static status_t setWMAFormat(
+            const sp<MetaData> &meta, sp<IOMX> OMXhandle,
+            IOMX::node_id nodeID, bool isEncoder );
+
+    static status_t setWMAFormat(
+            const sp<AMessage> &msg, sp<IOMX> OMXhandle,
+            IOMX::node_id nodeID, bool isEncoder );
+
+    static void setEVRCFormat(
+            int32_t numChannels, int32_t sampleRate,
+            sp<IOMX> OMXhandle, IOMX::node_id nodeID,
+            bool isEncoder );
+
+    static void setQCELPFormat(
+            int32_t numChannels, int32_t sampleRate,
+            sp<IOMX> OMXhandle, IOMX::node_id nodeID,
+            bool isEncoder );
+
+    static void setAC3Format(
+            int32_t numChannels, int32_t sampleRate,
+            sp<IOMX> OMXhandle, IOMX::node_id nodeID);
+
+    static status_t setDIVXFormat(
+            const sp<AMessage> &msg, const char* mime,
+            sp<IOMX> OMXhandle,IOMX::node_id nodeID, int port_index);
+
+};
+
+}
+#endif /*EXTENDED_CODEC_H_ */
+
diff --git a/include/media/stagefright/ExtendedWriter.h b/include/media/stagefright/ExtendedWriter.h
new file mode 100644
index 0000000..c56239f
--- /dev/null
+++ b/include/media/stagefright/ExtendedWriter.h
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 2012 - 2013, The Linux Foundation. All rights reserved.
+ *
+ * Not a Contribution
+ *
+ * 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.
+ */
+
+#ifndef EXTENDED_WRITER_H_
+
+#define EXTENDED_WRITER_H_
+
+#include <stdio.h>
+
+#include <media/stagefright/MediaWriter.h>
+#include <utils/threads.h>
+#include <cutils/log.h>
+
+#define LITERAL_TO_STRING_INTERNAL(x)    #x
+#define LITERAL_TO_STRING(x) LITERAL_TO_STRING_INTERNAL(x)
+
+#define CHECK_EQ(x,y)                                                   \
+    LOG_ALWAYS_FATAL_IF(                                                \
+            (x) != (y),                                                 \
+            __FILE__ ":" LITERAL_TO_STRING(__LINE__) " " #x " != " #y)
+
+#define CHECK(x)                                                        \
+    LOG_ALWAYS_FATAL_IF(                                                \
+            !(x),                                                       \
+            __FILE__ ":" LITERAL_TO_STRING(__LINE__) " " #x)
+
+namespace android {
+
+struct MediaSource;
+struct MetaData;
+
+struct ExtendedWriter : public MediaWriter {
+    ExtendedWriter(const char *filename);
+    ExtendedWriter(int fd);
+
+    status_t initCheck() const;
+
+    virtual status_t addSource(const sp<MediaSource> &source);
+    virtual bool reachedEOS();
+    virtual status_t start(MetaData *params = NULL);
+    virtual status_t stop();
+    virtual status_t pause();
+
+protected:
+    virtual ~ExtendedWriter();
+
+private:
+    FILE *mFile;
+    status_t mInitCheck;
+    sp<MediaSource> mSource;
+    bool mStarted;
+    volatile bool mPaused;
+    volatile bool mResumed;
+    volatile bool mDone;
+    volatile bool mReachedEOS;
+    pthread_t mThread;
+    int64_t mEstimatedSizeBytes;
+    int64_t mEstimatedDurationUs;
+
+    int32_t mFormat;
+
+    //QCP/EVRC header
+    struct QCPEVRCHeader
+    {
+        /* RIFF Section */
+        char riff[4];
+        unsigned int s_riff;
+        char qlcm[4];
+
+        /* Format chunk */
+        char fmt[4];
+        unsigned int s_fmt;
+        char mjr;
+        char mnr;
+        unsigned int data1;
+
+        /* UNIQUE ID of the codec */
+        unsigned short data2;
+        unsigned short data3;
+        char data4[8];
+        unsigned short ver;
+
+        /* Codec Info */
+        char name[80];
+        unsigned short abps;
+
+        /* average bits per sec of the codec */
+        unsigned short bytes_per_pkt;
+        unsigned short samp_per_block;
+        unsigned short samp_per_sec;
+        unsigned short bits_per_samp;
+        unsigned char vr_num_of_rates;
+
+        /* Rate Header fmt info */
+        unsigned char rvd1[3];
+        unsigned short vr_bytes_per_pkt[8];
+        unsigned int rvd2[5];
+
+        /* Vrat chunk */
+        unsigned char vrat[4];
+        unsigned int s_vrat;
+        unsigned int v_rate;
+        unsigned int size_in_pkts;
+
+        /* Data chunk */
+        unsigned char data[4];
+        unsigned int s_data;
+    } __attribute__ ((packed));
+
+    struct QCPEVRCHeader mHeader;
+    off_t mOffset; //note off_t
+
+    static void *ThreadWrapper(void *);
+    status_t threadFunc();
+    bool exceedsFileSizeLimit();
+    bool exceedsFileDurationLimit();
+
+    ExtendedWriter(const ExtendedWriter &);
+    ExtendedWriter &operator=(const ExtendedWriter &);
+
+    status_t writeQCPHeader( );
+    status_t writeEVRCHeader( );
+};
+
+}  // namespace android
+
+#endif  // AMR_WRITER_H_
diff --git a/include/media/stagefright/LPAPlayer.h b/include/media/stagefright/LPAPlayer.h
new file mode 100644
index 0000000..a2ae966
--- /dev/null
+++ b/include/media/stagefright/LPAPlayer.h
@@ -0,0 +1,198 @@
+/*
+ * Copyright (c) 2009-2012, The Linux Foundation. All rights reserved.
+ * Not a Contribution.
+ * Copyright (C) 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.
+ */
+
+#ifndef LPA_PLAYER_H_
+
+#define LPA_PLAYER_H_
+
+#include "AudioPlayer.h"
+#include <utils/threads.h>
+#include <utils/List.h>
+#include <utils/Vector.h>
+#include <fcntl.h>
+#include <pthread.h>
+#include <include/TimedEventQueue.h>
+
+// Pause timeout = 3sec
+#define LPA_PAUSE_TIMEOUT_USEC 3000000
+
+namespace android {
+
+class LPAPlayer : public AudioPlayer  {
+public:
+    enum {
+        REACHED_EOS,
+        SEEK_COMPLETE
+    };
+
+    enum {
+        TRACK_DIRECT,
+        TRACK_REGULAR,
+        TRACK_NONE
+    };
+
+    LPAPlayer(const sp<MediaPlayerBase::AudioSink> &audioSink, bool &initCheck,
+                AwesomePlayer *audioObserver = NULL);
+
+    virtual ~LPAPlayer();
+
+    // Caller retains ownership of "source".
+    virtual void setSource(const sp<MediaSource> &source);
+
+    // Return time in us.
+    virtual int64_t getRealTimeUs();
+
+    virtual status_t start(bool sourceAlreadyStarted = false);
+
+    virtual void pause(bool playPendingSamples = false);
+    virtual status_t resume();
+
+    // Returns the timestamp of the last buffer played (in us).
+    virtual int64_t getMediaTimeUs();
+
+    // Returns true iff a mapping is established, i.e. the LPAPlayer
+    // has played at least one frame of audio.
+    virtual bool getMediaTimeMapping(int64_t *realtime_us, int64_t *mediatime_us);
+
+    virtual status_t seekTo(int64_t time_us);
+
+    virtual bool isSeeking();
+    virtual bool reachedEOS(status_t *finalStatus);
+
+    static int mObjectsAlive;
+private:
+    int64_t mPositionTimeMediaUs;
+    int64_t mPositionTimeRealUs;
+    bool mInternalSeeking;
+    bool mIsAudioRouted;
+    bool mStarted;
+    bool mPaused;
+    int32_t mChannelMask;
+    int32_t mNumOutputChannels;
+    int32_t mNumInputChannels;
+    int32_t mSampleRate;
+    int64_t mLatencyUs;
+    size_t mFrameSize;
+    int64_t mTimeStarted;
+    int64_t mTimePlayed;
+    int64_t mNumFramesPlayed;
+    int64_t mNumFramesPlayedSysTimeUs;
+
+    pthread_t mDecoderThread;
+
+    //Kill Thread boolean
+    bool mKillDecoderThread;
+
+    //Thread alive boolean
+    bool mDecoderThreadAlive;
+
+    //Declare the condition Variables and Mutex
+
+    Mutex mDecoderMutex;
+
+    Condition mDecoderCv;
+
+    // make sure Decoder thread has exited
+    void requestAndWaitForDecoderThreadExit_l();
+
+    static void *decoderThreadWrapper(void *me);
+    void decoderThreadEntry();
+
+    void createThreads();
+
+    void onPauseTimeOut();
+
+    sp<MediaSource> mSource;
+
+    MediaBuffer *mInputBuffer;
+
+    Mutex mLock;
+
+    bool mSeeking;
+    bool mReachedEOS;
+    bool mReachedOutputEOS;
+    status_t mFinalStatus;
+    int64_t mSeekTimeUs;
+    int64_t mPauseTime;
+
+
+    bool mIsFirstBuffer;
+    status_t mFirstBufferResult;
+    MediaBuffer *mFirstBuffer;
+    TimedEventQueue mQueue;
+    bool            mQueueStarted;
+    sp<TimedEventQueue::Event>  mPauseEvent;
+    bool                        mPauseEventPending;
+
+    sp<MediaPlayerBase::AudioSink> mAudioSink;
+    AwesomePlayer *mObserver;
+    int mTrackType;
+
+    static size_t AudioSinkCallback(
+        MediaPlayerBase::AudioSink *audioSink,
+        void *data, size_t size, void *me,
+        MediaPlayerBase::AudioSink::cb_event_t event);
+
+    int64_t getTimeStamp();
+
+    size_t fillBuffer(void *data, size_t size);
+
+    int64_t getRealTimeUsLocked();
+
+    void reset();
+
+    status_t setupAudioSink();
+    static size_t AudioCallback(
+        MediaPlayerBase::AudioSink *audioSink,
+        void *buffer, size_t size, void *cookie);
+    size_t AudioCallback(void *cookie, void *data, size_t size);
+    int64_t getMediaTimeUs_l();
+    bool seekTooClose(int64_t);
+
+    void convertMonoToStereo(int16_t *data, size_t size);
+
+    LPAPlayer(const LPAPlayer &);
+    LPAPlayer &operator=(const LPAPlayer &);
+};
+
+struct TimedEvent : public TimedEventQueue::Event {
+    TimedEvent(LPAPlayer *player,
+               void (LPAPlayer::*method)())
+        : mPlayer(player),
+          mMethod(method) {
+    }
+
+protected:
+    virtual ~TimedEvent() {}
+
+    virtual void fire(TimedEventQueue *queue, int64_t /* now_us */) {
+        (mPlayer->*mMethod)();
+    }
+
+private:
+    LPAPlayer *mPlayer;
+    void (LPAPlayer::*mMethod)();
+
+    TimedEvent(const TimedEvent &);
+    TimedEvent &operator=(const TimedEvent &);
+};
+
+}  // namespace android
+
+#endif  // LPA_PLAYER_H_
+
diff --git a/include/media/stagefright/LPAPlayerLegacy.h b/include/media/stagefright/LPAPlayerLegacy.h
new file mode 100755
index 0000000..cca3bd4
--- /dev/null
+++ b/include/media/stagefright/LPAPlayerLegacy.h
@@ -0,0 +1,299 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ * Copyright (c) 2009-2013, 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
+ *
+ *      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.
+ */
+
+#ifndef LPA_PLAYER_H_
+
+#define LPA_PLAYER_H_
+
+#include "AudioPlayer.h"
+#include <media/IAudioFlinger.h>
+#include <utils/threads.h>
+#include <utils/List.h>
+#include <utils/Vector.h>
+#include <fcntl.h>
+#include <pthread.h>
+#include <binder/IServiceManager.h>
+#include <linux/unistd.h>
+#include <include/TimedEventQueue.h>
+#include <binder/BinderService.h>
+#include <binder/MemoryDealer.h>
+#include <powermanager/IPowerManager.h>
+
+// Pause timeout = 3sec
+#define LPA_PAUSE_TIMEOUT_USEC 3000000
+
+namespace android {
+
+class LPAPlayer : public AudioPlayer  {
+public:
+    enum {
+        REACHED_EOS,
+        SEEK_COMPLETE
+    };
+
+    enum {
+        TRACK_DIRECT,
+        TRACK_REGULAR,
+        TRACK_NONE
+    };
+
+    LPAPlayer(const sp<MediaPlayerBase::AudioSink> &audioSink, bool &initCheck,
+                AwesomePlayer *audioObserver = NULL);
+
+    virtual ~LPAPlayer();
+
+    // Caller retains ownership of "source".
+    virtual void setSource(const sp<MediaSource> &source);
+
+    // Return time in us.
+    virtual int64_t getRealTimeUs();
+
+    virtual status_t start(bool sourceAlreadyStarted = false);
+
+    virtual void pause(bool playPendingSamples = false);
+    virtual status_t resume();
+
+    // Returns the timestamp of the last buffer played (in us).
+    virtual int64_t getMediaTimeUs();
+
+    // Returns true iff a mapping is established, i.e. the LPAPlayer
+    // has played at least one frame of audio.
+    virtual bool getMediaTimeMapping(int64_t *realtime_us, int64_t *mediatime_us);
+
+    virtual status_t seekTo(int64_t time_us);
+
+    virtual bool isSeeking();
+    virtual bool reachedEOS(status_t *finalStatus);
+
+    static int mObjectsAlive;
+    static bool mLpaInProgress;
+private:
+    int64_t mPositionTimeMediaUs;
+    int64_t mPositionTimeRealUs;
+    bool mInternalSeeking;
+    bool mIsAudioRouted;
+    bool mStarted;
+    bool mPaused;
+    bool mA2DPEnabled;
+    int32_t mChannelMask;
+    int32_t numChannels;
+    int32_t mNumOutputChannels;
+    int32_t mNumInputChannels;
+    int32_t mSampleRate;
+    int64_t mLatencyUs;
+    size_t mFrameSize;
+    int64_t mTimeStarted;
+    int64_t mTimePlayed;
+    int64_t mNumFramesPlayed;
+    int64_t mNumFramesPlayedSysTimeUs;
+    int64_t mNumA2DPBytesPlayed;
+
+    void clearPowerManager();
+
+    class PMDeathRecipient : public IBinder::DeathRecipient {
+        public:
+                        PMDeathRecipient(void *obj){parentClass = (LPAPlayer *)obj;}
+            virtual     ~PMDeathRecipient() {}
+
+            // IBinder::DeathRecipient
+            virtual     void        binderDied(const wp<IBinder>& who);
+
+        private:
+                        LPAPlayer *parentClass;
+                        PMDeathRecipient(const PMDeathRecipient&);
+                        PMDeathRecipient& operator = (const PMDeathRecipient&);
+
+        friend class LPAPlayer;
+    };
+
+    friend class PMDeathRecipient;
+
+    void        acquireWakeLock();
+    void        releaseWakeLock();
+
+    sp<IPowerManager>       mPowerManager;
+    sp<IBinder>             mWakeLockToken;
+    sp<PMDeathRecipient>    mDeathRecipient;
+
+    pthread_t decoderThread;
+
+    pthread_t A2DPNotificationThread;
+
+    //Kill Thread boolean
+    bool killDecoderThread;
+
+
+
+    bool killA2DPNotificationThread;
+
+    //Thread alive boolean
+    bool decoderThreadAlive;
+
+
+    bool a2dpNotificationThreadAlive;
+
+    //Declare the condition Variables and Mutex
+
+    pthread_mutex_t decoder_mutex;
+
+    pthread_mutex_t audio_sink_setup_mutex;
+
+    pthread_mutex_t a2dp_notification_mutex;
+
+
+
+    pthread_cond_t decoder_cv;
+
+
+    pthread_cond_t a2dp_notification_cv;
+
+
+    // make sure Decoder thread has exited
+    void requestAndWaitForDecoderThreadExit();
+
+
+    // make sure the Effects thread also exited
+    void requestAndWaitForA2DPNotificationThreadExit();
+
+    static void *decoderThreadWrapper(void *me);
+    void decoderThreadEntry();
+    static void *A2DPNotificationThreadWrapper(void *me);
+    void A2DPNotificationThreadEntry();
+
+    void createThreads();
+
+    volatile bool mIsA2DPEnabled;
+
+    //Structure to recieve the BT notification from the flinger.
+    class AudioFlingerLPAdecodeClient: public IBinder::DeathRecipient, public BnAudioFlingerClient {
+    public:
+        AudioFlingerLPAdecodeClient(void *obj);
+
+        LPAPlayer *pBaseClass;
+        // DeathRecipient
+        virtual void binderDied(const wp<IBinder>& who);
+
+        // IAudioFlingerClient
+
+        // indicate a change in the configuration of an output or input: keeps the cached
+        // values for output/input parameters upto date in client process
+        virtual void ioConfigChanged(int event, audio_io_handle_t ioHandle, const void *param2);
+
+        friend class LPAPlayer;
+    };
+
+    sp<IAudioFlinger> mAudioFlinger;
+
+    // helper function to obtain AudioFlinger service handle
+    void getAudioFlinger();
+
+    void handleA2DPSwitch();
+    void onPauseTimeOut();
+
+    int64_t getMediaTimeUs_l();
+    bool seekTooClose(int64_t);
+
+    sp<AudioFlingerLPAdecodeClient> AudioFlingerClient;
+    friend class AudioFlingerLPAdecodeClient;
+    Mutex AudioFlingerLock;
+    sp<MediaSource> mSource;
+
+    MediaBuffer *mInputBuffer;
+
+    Mutex mLock;
+    Mutex mResumeLock;
+
+    bool mSeeking;
+    bool mReachedEOS;
+    bool mReachedOutputEOS;
+    status_t mFinalStatus;
+    int64_t mSeekTimeUs;
+    int64_t mPauseTime;
+
+
+    bool mIsFirstBuffer;
+    status_t mFirstBufferResult;
+    MediaBuffer *mFirstBuffer;
+    TimedEventQueue mQueue;
+    bool            mQueueStarted;
+    sp<TimedEventQueue::Event>  mPauseEvent;
+    bool                        mPauseEventPending;
+
+    sp<MediaPlayerBase::AudioSink> mAudioSink;
+    AwesomePlayer *mObserver;
+    int mTrackType;
+
+    static size_t AudioSinkCallback(
+        MediaPlayerBase::AudioSink *audioSink,
+        void *data, size_t size, void *me,
+        MediaPlayerBase::AudioSink::cb_event_t event);
+
+    enum A2DPState {
+        A2DP_ENABLED,
+        A2DP_DISABLED,
+        A2DP_CONNECT,
+        A2DP_DISCONNECT
+    };
+
+    int64_t getTimeStamp(A2DPState state);
+
+    size_t fillBuffer(void *data, size_t size);
+
+    int64_t getRealTimeUsLocked();
+
+    void reset();
+
+    status_t setupAudioSink();
+    static size_t AudioCallback(
+        MediaPlayerBase::AudioSink *audioSink,
+        void *buffer, size_t size, void *cookie);
+    size_t AudioCallback(void *cookie, void *data, size_t size);
+
+    void convertMonoToStereo(int16_t *data, size_t size);
+
+    LPAPlayer(const LPAPlayer &);
+    LPAPlayer &operator=(const LPAPlayer &);
+};
+
+struct TimedEvent : public TimedEventQueue::Event {
+    TimedEvent(LPAPlayer *player,
+               void (LPAPlayer::*method)())
+        : mPlayer(player),
+          mMethod(method) {
+    }
+
+protected:
+    virtual ~TimedEvent() {}
+
+    virtual void fire(TimedEventQueue *queue, int64_t /* now_us */) {
+        (mPlayer->*mMethod)();
+    }
+
+private:
+    LPAPlayer *mPlayer;
+    void (LPAPlayer::*mMethod)();
+
+    TimedEvent(const TimedEvent &);
+    TimedEvent &operator=(const TimedEvent &);
+};
+
+}  // namespace android
+
+#endif  // LPA_PLAYER_H_
+
diff --git a/include/media/stagefright/MediaCodecList.h b/include/media/stagefright/MediaCodecList.h
index 590623b..947f123 100644
--- a/include/media/stagefright/MediaCodecList.h
+++ b/include/media/stagefright/MediaCodecList.h
@@ -100,6 +100,8 @@
     status_t addTypeFromAttributes(const char **attrs);
     void addType(const char *name);
 
+    friend class ExtendedUtils;
+
     DISALLOW_EVIL_CONSTRUCTORS(MediaCodecList);
 };
 
diff --git a/include/media/stagefright/MediaDefs.h b/include/media/stagefright/MediaDefs.h
index 85693d4..170e587 100644
--- a/include/media/stagefright/MediaDefs.h
+++ b/include/media/stagefright/MediaDefs.h
@@ -32,6 +32,9 @@
 
 extern const char *MEDIA_MIMETYPE_AUDIO_AMR_NB;
 extern const char *MEDIA_MIMETYPE_AUDIO_AMR_WB;
+#ifdef QCOM_HARDWARE
+extern const char *MEDIA_MIMETYPE_AUDIO_AMR_WB_PLUS;
+#endif
 extern const char *MEDIA_MIMETYPE_AUDIO_MPEG;           // layer III
 extern const char *MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_I;
 extern const char *MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_II;
diff --git a/include/media/stagefright/MediaExtractor.h b/include/media/stagefright/MediaExtractor.h
index 3076a96..ec3de50 100644
--- a/include/media/stagefright/MediaExtractor.h
+++ b/include/media/stagefright/MediaExtractor.h
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 2009 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.
@@ -49,6 +50,7 @@
         CAN_SEEK_FORWARD   = 2,  // the "seek 10secs forward button"
         CAN_PAUSE          = 4,
         CAN_SEEK           = 8,  // the "seek bar"
+        CAN_SEEK_TO_ZERO   = 16, // the "previous button"
     };
 
     // If subclasses do _not_ override this, the default is
diff --git a/include/media/stagefright/MetaData.h b/include/media/stagefright/MetaData.h
index 3a87474..c289439 100644
--- a/include/media/stagefright/MetaData.h
+++ b/include/media/stagefright/MetaData.h
@@ -1,6 +1,9 @@
 /*
  * Copyright (C) 2009 The Android Open Source Project
  *
+ * Copyright (c) 2009-2013, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ *
  * 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
@@ -162,6 +165,9 @@
     kKeyCryptoDefaultIVSize = 'cryS',  // int32_t
 
     kKeyPssh              = 'pssh',  // raw data
+#ifdef QCOM_HARDWARE
+    kKeyTunnelException   = 'Ntnl', // not tunnel
+#endif
 };
 
 enum {
diff --git a/include/media/stagefright/OMXCodec.h b/include/media/stagefright/OMXCodec.h
index daaf20f..1247356 100644
--- a/include/media/stagefright/OMXCodec.h
+++ b/include/media/stagefright/OMXCodec.h
@@ -100,6 +100,13 @@
         kSupportsMultipleFramesPerInputBuffer = 1024,
         kRequiresLargerEncoderOutputBuffer    = 2048,
         kOutputBuffersAreUnreadable           = 4096,
+#if defined(OMAP_ENHANCEMENT)
+        kAvoidMemcopyInputRecordingFrames     = 0x20000000,
+#endif
+#ifdef QCOM_HARDWARE
+        kRequiresGlobalFlush                  = 0x20000000, // 2^29
+        kRequiresWMAProComponent              = 0x40000000, //2^30
+#endif
     };
 
     struct CodecNameAndQuirks {
@@ -139,10 +146,18 @@
         EXECUTING_TO_IDLE,
         IDLE_TO_LOADED,
         RECONFIGURING,
+#ifdef QCOM_HARDWARE
+        PAUSING,
+        FLUSHING,
+        PAUSED,
+#endif
         ERROR
     };
 
     enum {
+#ifdef QCOM_HARDWARE
+        kPortIndexBoth   = -1,
+#endif
         kPortIndexInput  = 0,
         kPortIndexOutput = 1
     };
@@ -255,7 +270,7 @@
             OMX_VIDEO_CODINGTYPE compressionFormat,
             OMX_COLOR_FORMATTYPE colorFormat);
 
-    void setVideoInputFormat(
+    status_t setVideoInputFormat(
             const char *mime, const sp<MetaData>& meta);
 
     status_t setupBitRate(int32_t bitRate);
@@ -291,6 +306,9 @@
 
     status_t allocateBuffers();
     status_t allocateBuffersOnPort(OMX_U32 portIndex);
+#ifdef USE_SAMSUNG_COLORFORMAT
+    void setNativeWindowColorFormat(OMX_COLOR_FORMATTYPE &eNativeColorFormat);
+#endif
     status_t allocateOutputBuffersFromNativeWindow();
 
     status_t queueBufferToNativeWindow(BufferInfo *info);
@@ -344,6 +362,9 @@
     void dumpPortStatus(OMX_U32 portIndex);
 
     status_t configureCodec(const sp<MetaData> &meta);
+#if defined(OMAP_ENHANCEMENT)
+    void restorePatchedDataPointer(BufferInfo *info);
+#endif
 
     status_t applyRotation();
     status_t waitForBufferFilled_l();
@@ -358,6 +379,11 @@
 
     OMXCodec(const OMXCodec &);
     OMXCodec &operator=(const OMXCodec &);
+
+#ifdef QCOM_HARDWARE
+    int32_t mNumBFrames;
+    bool mInSmoothStreamingMode;
+#endif
 };
 
 struct CodecCapabilities {
diff --git a/include/media/stagefright/TunnelPlayer.h b/include/media/stagefright/TunnelPlayer.h
new file mode 100644
index 0000000..bec2485
--- /dev/null
+++ b/include/media/stagefright/TunnelPlayer.h
@@ -0,0 +1,180 @@
+/*
+ * Copyright (c) 2009-2012, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ * Copyright (C) 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.
+ */
+
+#ifndef TUNNEL_PLAYER_H_
+
+#define TUNNEL_PLAYER_H_
+
+#include "AudioPlayer.h"
+#include <utils/threads.h>
+#include <utils/List.h>
+#include <utils/Vector.h>
+#include <fcntl.h>
+#include <pthread.h>
+#include <include/TimedEventQueue.h>
+
+// Pause timeout = 3sec
+#define TUNNEL_PAUSE_TIMEOUT_USEC 3000000
+namespace android {
+
+class TunnelPlayer : public AudioPlayer  {
+public:
+    enum {
+        REACHED_EOS,
+        SEEK_COMPLETE
+    };
+
+    TunnelPlayer(const sp<MediaPlayerBase::AudioSink> &audioSink, bool &initCheck,
+                AwesomePlayer *audioObserver = NULL, bool hasVideo = false);
+
+    virtual ~TunnelPlayer();
+
+    // Caller retains ownership of "source".
+    virtual void setSource(const sp<MediaSource> &source);
+
+    // Return time in us.
+    virtual int64_t getRealTimeUs();
+
+    virtual status_t start(bool sourceAlreadyStarted = false);
+
+    virtual void pause(bool playPendingSamples = false);
+    virtual status_t resume();
+
+    // Returns the timestamp of the last buffer played (in us).
+    virtual int64_t getMediaTimeUs();
+
+    // Returns true iff a mapping is established, i.e. the TunnelPlayer
+    // has played at least one frame of audio.
+    virtual bool getMediaTimeMapping(int64_t *realtime_us, int64_t *mediatime_us);
+
+    virtual status_t seekTo(int64_t time_us);
+
+    virtual bool isSeeking();
+    virtual bool reachedEOS(status_t *finalStatus);
+
+
+    static int mTunnelObjectsAlive;
+    static const int getTunnelObjectsAliveMax();
+private:
+    int64_t mPositionTimeMediaUs;
+    int64_t mPositionTimeRealUs;
+    bool mInternalSeeking;
+    bool mIsAudioRouted;
+    bool mStarted;
+    bool mPaused;
+    int32_t mChannelMask;
+    int32_t numChannels;
+    int32_t mSampleRate;
+    int64_t mLatencyUs;
+    size_t mFrameSize;
+    int64_t mNumFramesPlayed;
+    int64_t mNumFramesPlayedSysTimeUs;
+    audio_format_t mFormat;
+    bool mHasVideo;
+
+    pthread_t mExtractorThread;
+
+    //Kill Thread boolean
+    bool mKillExtractorThread;
+
+    //Thread alive boolean
+    bool mExtractorThreadAlive;
+
+    //Declare the condition Variables and Mutex
+    Mutex mExtractorMutex;
+    Condition mExtractorCv;
+
+
+    // make sure Decoder thread has exited
+    void requestAndWaitForExtractorThreadExit_l();
+
+
+    static void *extractorThreadWrapper(void *me);
+    void extractorThreadEntry();
+
+    void createThreads();
+
+    void onPauseTimeOut();
+
+    sp<MediaSource> mSource;
+
+    MediaBuffer *mInputBuffer;
+
+    Mutex mLock;
+
+    bool mSeeking;
+    bool mReachedEOS;
+    bool mReachedOutputEOS;
+    status_t mFinalStatus;
+    int64_t mSeekTimeUs;
+    int64_t mPauseTime;
+
+
+    bool mIsFirstBuffer;
+    status_t mFirstBufferResult;
+    MediaBuffer *mFirstBuffer;
+    TimedEventQueue mQueue;
+    bool            mQueueStarted;
+    sp<TimedEventQueue::Event>  mPauseEvent;
+    bool                        mPauseEventPending;
+
+    sp<MediaPlayerBase::AudioSink> mAudioSink;
+    AwesomePlayer *mObserver;
+
+    static size_t AudioSinkCallback(
+        MediaPlayerBase::AudioSink *audioSink,
+        void *data, size_t size, void *me,
+        MediaPlayerBase::AudioSink::cb_event_t event);
+
+    void getPlayedTimeFromDSP_l(int64_t *timeStamp);
+    void getOffsetRealTime_l(int64_t *offsetTime);
+
+    size_t fillBuffer(void *data, size_t size);
+
+    void reset();
+    bool seekTooClose(int64_t time_us);
+
+    TunnelPlayer(const TunnelPlayer &);
+    TunnelPlayer &operator=(const TunnelPlayer &);
+};
+
+struct TunnelEvent : public TimedEventQueue::Event {
+    TunnelEvent(TunnelPlayer *player,
+               void (TunnelPlayer::*method)())
+        : mPlayer(player),
+          mMethod(method) {
+    }
+
+protected:
+    virtual ~TunnelEvent() {}
+
+    virtual void fire(TimedEventQueue *queue, int64_t /* now_us */) {
+        (mPlayer->*mMethod)();
+    }
+
+private:
+    TunnelPlayer *mPlayer;
+    void (TunnelPlayer::*mMethod)();
+
+    TunnelEvent(const TunnelEvent &);
+    TunnelEvent &operator=(const TunnelEvent &);
+};
+
+}  // namespace android
+
+#endif  // LPA_PLAYER_H_
diff --git a/include/media/stagefright/WAVEWriter.h b/include/media/stagefright/WAVEWriter.h
new file mode 100644
index 0000000..a314008
--- /dev/null
+++ b/include/media/stagefright/WAVEWriter.h
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2012 - 2013, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials provided
+ *       with the distribution.
+ *     * Neither the name of The Linux Foundation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef WAVE_WRITER_H_
+
+#define WAVE_WRITER_H_
+
+#include <stdio.h>
+
+#include <media/stagefright/MediaWriter.h>
+#include <utils/threads.h>
+
+namespace android {
+
+
+#define ID_RIFF 0x46464952
+#define ID_WAVE 0x45564157
+#define ID_FMT  0x20746d66
+#define ID_DATA 0x61746164
+#define FORMAT_PCM 1
+
+
+struct MediaSource;
+struct MetaData;
+
+struct wav_header {
+    uint32_t riff_id;
+    uint32_t riff_sz;
+    uint32_t riff_fmt;
+    uint32_t fmt_id;
+    uint32_t fmt_sz;
+    uint16_t audio_format;
+    uint16_t num_channels;
+    uint32_t sample_rate;
+    uint32_t byte_rate;       /* sample_rate * num_channels * bps / 8 */
+    uint16_t block_align;     /* num_channels * bps / 8 */
+    uint16_t bits_per_sample;
+    uint32_t data_id;
+    uint32_t data_sz;
+};
+
+
+struct WAVEWriter : public MediaWriter {
+    WAVEWriter(const char *filename);
+    WAVEWriter(int fd);
+
+    status_t initCheck() const;
+
+    virtual status_t addSource(const sp<MediaSource> &source);
+    virtual bool reachedEOS();
+    virtual status_t start(MetaData *params = NULL);
+    virtual status_t stop();
+    virtual status_t pause();
+
+protected:
+    virtual ~WAVEWriter();
+
+private:
+    int   mFd;
+    status_t mInitCheck;
+    sp<MediaSource> mSource;
+    bool mStarted;
+    volatile bool mPaused;
+    volatile bool mResumed;
+    volatile bool mDone;
+    volatile bool mReachedEOS;
+    pthread_t mThread;
+    int64_t mEstimatedSizeBytes;
+    int64_t mEstimatedDurationUs;
+
+    static void *ThreadWrapper(void *);
+    status_t threadFunc();
+    bool exceedsFileSizeLimit();
+    bool exceedsFileDurationLimit();
+
+    WAVEWriter(const WAVEWriter &);
+    WAVEWriter &operator=(const WAVEWriter &);
+};
+
+}  // namespace android
+
+#endif  // WAVE_WRITER_H_
diff --git a/libvideoeditor/lvpp/Android.mk b/libvideoeditor/lvpp/Android.mk
index 2286827..4400c03 100755
--- a/libvideoeditor/lvpp/Android.mk
+++ b/libvideoeditor/lvpp/Android.mk
@@ -80,9 +80,13 @@
     $(TOP)/frameworks/av/libvideoeditor/lvpp \
     $(TOP)/frameworks/av/services/audioflinger \
     $(TOP)/frameworks/native/include/media/editor \
-    $(TOP)/frameworks/native/include/media/openmax \
     $(TOP)/frameworks/native/services/audioflinger
 
+ifneq ($(TI_CUSTOM_DOMX_PATH),)
+LOCAL_C_INCLUDES += $(TI_CUSTOM_DOMX_PATH)/omx_core/inc
+else
+LOCAL_C_INCLUDES += $(TOP)/frameworks/native/include/media/openmax
+endif
 
 LOCAL_SHARED_LIBRARIES += libdl
 
diff --git a/libvideoeditor/vss/stagefrightshells/src/VideoEditorVideoDecoder.cpp b/libvideoeditor/vss/stagefrightshells/src/VideoEditorVideoDecoder.cpp
index de91731..5386cdd 100755
--- a/libvideoeditor/vss/stagefrightshells/src/VideoEditorVideoDecoder.cpp
+++ b/libvideoeditor/vss/stagefrightshells/src/VideoEditorVideoDecoder.cpp
@@ -830,8 +830,13 @@
     pDecShellContext->mCropRect.top = cropTop;
     pDecShellContext->mCropRect.bottom = cropBottom;
 
+#ifdef QCOM_HARDWARE
+    width = vWidth;
+    height = vHeight;
+#else
     width = cropRight - cropLeft + 1;
     height = cropBottom - cropTop + 1;
+#endif
 
     ALOGV("VideoDecoder_configureFromMetadata : W=%d H=%d", width, height);
     VIDEOEDITOR_CHECK((0 != width) && (0 != height), M4ERR_PARAMETER);
diff --git a/media/libmedia/Android.mk b/media/libmedia/Android.mk
index 56e7787..331e4dc 100644
--- a/media/libmedia/Android.mk
+++ b/media/libmedia/Android.mk
@@ -9,6 +9,17 @@
 
 include $(BUILD_STATIC_LIBRARY)
 
+ifeq ($(BOARD_USES_QCOM_HARDWARE),true)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= AudioParameter.cpp
+LOCAL_MODULE:= libaudioparameter
+LOCAL_MODULE_TAGS := optional
+LOCAL_SHARED_LIBRARIES := libutils libcutils
+
+include $(BUILD_SHARED_LIBRARY)
+endif
+
 include $(CLEAR_VARS)
 
 LOCAL_SRC_FILES:= \
@@ -58,6 +69,21 @@
 
 LOCAL_SRC_FILES += ../libnbaio/roundup.c
 
+ifeq ($(BOARD_USES_LIBMEDIA_WITH_AUDIOPARAMETER),true)
+LOCAL_SRC_FILES+= \
+    AudioParameter.cpp
+endif
+
+ifeq ($(BOARD_USE_SAMSUNG_SEPARATEDSTREAM),true)
+LOCAL_CFLAGS += -DUSE_SAMSUNG_SEPARATEDSTREAM
+endif
+
+ifeq ($(BOARD_USES_QCOM_HARDWARE),true)
+LOCAL_SRC_FILES += \
+    IDirectTrack.cpp \
+    IDirectTrackClient.cpp
+endif
+
 # for <cutils/atomic-inline.h>
 LOCAL_CFLAGS += -DANDROID_SMP=$(if $(findstring true,$(TARGET_CPU_SMP)),1,0)
 LOCAL_SRC_FILES += SingleStateQueue.cpp
diff --git a/media/libmedia/AudioParameter.cpp b/media/libmedia/AudioParameter.cpp
index e3fea77..4240a9a 100644
--- a/media/libmedia/AudioParameter.cpp
+++ b/media/libmedia/AudioParameter.cpp
@@ -1,4 +1,7 @@
 /*
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ * Not a Contribution.
+ *
  * Copyright (C) 2006-2011 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -32,6 +35,16 @@
 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;
+const char * const AudioParameter::keyADSPStatus = AUDIO_PARAMETER_KEY_ADSP_STATUS;
+const char * const AudioParameter::keyCanOpenProxy = AUDIO_CAN_OPEN_PROXY;
+const char * const AudioParameter::keyFmVolume = AUDIO_PARAMETER_KEY_FM_VOLUME;
+#endif
 
 AudioParameter::AudioParameter(const String8& keyValuePairs)
 {
diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp
index ccbc5a3..34bb6f9 100644
--- a/media/libmedia/AudioRecord.cpp
+++ b/media/libmedia/AudioRecord.cpp
@@ -60,9 +60,14 @@
     // We double the size of input buffer for ping pong use of record buffer.
     size <<= 1;
 
-    // Assumes audio_is_linear_pcm(format)
+#ifdef QCOM_HARDWARE
+    if (audio_is_linear_pcm(format) || format == AUDIO_FORMAT_AMR_WB) {
+#endif
     uint32_t channelCount = popcount(channelMask);
     size /= channelCount * audio_bytes_per_sample(format);
+#ifdef QCOM_HARDWARE
+    }
+#endif
 
     *frameCount = size;
     return NO_ERROR;
@@ -194,11 +199,13 @@
         ALOGE("Invalid format %d", format);
         return BAD_VALUE;
     }
+#ifndef QCOM_HARDWARE
     // Temporary restriction: AudioFlinger currently supports 16-bit PCM only
     if (format != AUDIO_FORMAT_PCM_16_BIT) {
         ALOGE("Format %d is not supported", format);
         return BAD_VALUE;
     }
+#endif
     mFormat = format;
 
     if (!audio_is_input_channel(channelMask)) {
@@ -206,9 +213,32 @@
         return BAD_VALUE;
     }
     mChannelMask = channelMask;
-    uint32_t channelCount = popcount(channelMask);
+    uint32_t channelCount = popcount(channelMask
+#ifdef QCOM_HARDWARE
+        &(AUDIO_CHANNEL_IN_STEREO|AUDIO_CHANNEL_IN_MONO|AUDIO_CHANNEL_IN_5POINT1));
+#else
+    );
+#endif
     mChannelCount = channelCount;
 
+#ifdef QCOM_HARDWARE
+    mFrameSize = frameSize();
+
+    size_t inputBuffSizeInBytes = -1;
+    status_t status = AudioSystem::getInputBufferSize(sampleRate, format, channelMask, &inputBuffSizeInBytes);
+    if (status != NO_ERROR) {
+        ALOGE("AudioSystem could not query the input buffer size; status %d", status);
+        return NO_INIT;
+    }
+
+    if (inputBuffSizeInBytes == 0) {
+        ALOGE("Unsupported configuration: sampleRate %u, format %d, channelMask %#x",
+            sampleRate, format, channelMask);
+        return BAD_VALUE;
+    }
+
+    int minFrameCount = (inputBuffSizeInBytes * 2)/mFrameSize;
+#else
     // Assumes audio_is_linear_pcm(format), else sizeof(uint8_t)
     mFrameSize = channelCount * audio_bytes_per_sample(format);
 
@@ -220,6 +250,8 @@
         ALOGE("getMinFrameCount() failed; status %d", status);
         return status;
     }
+#endif
+
     ALOGV("AudioRecord::set() minFrameCount = %d", minFrameCount);
 
     if (frameCount == 0) {
@@ -276,6 +308,13 @@
     return NO_ERROR;
 }
 
+#ifdef QCOM_HARDWARE
+audio_source_t AudioRecord::inputSource() const
+{
+    return mInputSource;
+}
+#endif
+
 // -------------------------------------------------------------------------
 
 status_t AudioRecord::start(AudioSystem::sync_event_t event, int triggerSession)
@@ -463,6 +502,12 @@
     }
 
     int originalSessionId = mSessionId;
+#ifdef QCOM_HARDWARE
+    if (inputSource() == AUDIO_SOURCE_VOICE_COMMUNICATION) {
+        ALOGV("Notify use of Voice Communication");
+        trackFlags |= IAudioFlinger::TRACK_VOICE_COMMUNICATION;
+    }
+#endif
     sp<IAudioRecord> record = audioFlinger->openRecord(input,
                                                        mSampleRate, mFormat,
                                                        mChannelMask,
@@ -522,7 +567,7 @@
     void *buffers = (char*)cblk + sizeof(audio_track_cblk_t);
 
     // update proxy
-    mProxy = new AudioRecordClientProxy(cblk, buffers, mFrameCount, mFrameSize);
+    mProxy = new AudioRecordClientProxy(cblk, buffers, mCblk->frameCount_, mFrameSize);
     mProxy->setEpoch(epoch);
     mProxy->setMinimum(mNotificationFramesAct);
 
@@ -952,6 +997,38 @@
     return result;
 }
 
+#ifdef QCOM_HARDWARE
+size_t AudioRecord::frameSize() const
+{
+    if (inputSource() == AUDIO_SOURCE_VOICE_COMMUNICATION) {
+        if (audio_is_linear_pcm(mFormat)) {
+            return channelCount()*audio_bytes_per_sample(mFormat);
+        } else {
+            return channelCount()*sizeof(int16_t);
+        }
+    } else {
+        if (format() ==AUDIO_FORMAT_AMR_NB) {
+            return channelCount() * AMR_FRAMESIZE; // Full rate framesize
+        } else if (format() == AUDIO_FORMAT_EVRC) {
+            return channelCount() * EVRC_FRAMESIZE; // Full rate framesize
+        } else if (format() == AUDIO_FORMAT_QCELP) {
+           return channelCount() * QCELP_FRAMESIZE; // Full rate framesize
+        } else if (format() == AUDIO_FORMAT_AAC) {
+            // Not actual framsize but for variable frame rate AAC encoding,
+            // buffer size is treated as a frame size
+            return AAC_FRAMESIZE;
+        } else if(format() == AUDIO_FORMAT_AMR_WB) {
+            return channelCount() * AMR_WB_FRAMESIZE;
+        }
+        if (audio_is_linear_pcm(mFormat)) {
+            return channelCount()*audio_bytes_per_sample(mFormat);
+        } else {
+            return sizeof(uint8_t);
+        }
+   }
+}
+#endif
+
 // =========================================================================
 
 void AudioRecord::DeathNotifier::binderDied(const wp<IBinder>& who)
diff --git a/media/libmedia/AudioSystem.cpp b/media/libmedia/AudioSystem.cpp
index 8033c2c..1a1bfda 100644
--- a/media/libmedia/AudioSystem.cpp
+++ b/media/libmedia/AudioSystem.cpp
@@ -316,6 +316,11 @@
                                  audio_stream_type_t streamType,
                                  uint32_t* latency)
 {
+#ifdef QCOM_HARDWARE
+    const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
+    if (af == 0) return PERMISSION_DENIED;
+    *latency = af->latency(output);
+#else
     OutputDescriptor *outputDesc;
 
     gLock.lock();
@@ -329,6 +334,7 @@
         *latency = outputDesc->latency;
         gLock.unlock();
     }
+#endif
 
     ALOGV("getLatency() streamType %d, output %d, latency %d", streamType, output, *latency);
 
@@ -572,6 +578,12 @@
     return aps->getDeviceConnectionState(device, device_address);
 }
 
+extern "C" audio_policy_dev_state_t _ZN7android11AudioSystem24getDeviceConnectionStateE15audio_devices_tPKc(audio_devices_t device,
+                                                  const char *device_address)
+{
+    return AudioSystem::getDeviceConnectionState(device, device_address);
+}
+
 status_t AudioSystem::setPhoneState(audio_mode_t state)
 {
     if (uint32_t(state) >= AUDIO_MODE_CNT) return BAD_VALUE;
@@ -608,6 +620,14 @@
     return aps->getOutput(stream, samplingRate, format, channelMask, flags, offloadInfo);
 }
 
+extern "C" audio_io_handle_t _ZN7android11AudioSystem9getOutputE19audio_stream_type_tjjj27audio_policy_output_flags_t(audio_stream_type_t stream,
+                                    uint32_t samplingRate,
+                                    uint32_t format,
+                                    uint32_t channels,
+                                    audio_output_flags_t flags) {
+    return AudioSystem::getOutput(stream,samplingRate,(audio_format_t) format, channels, flags);
+}
+
 status_t AudioSystem::startOutput(audio_io_handle_t output,
                                   audio_stream_type_t stream,
                                   int session)
@@ -811,4 +831,13 @@
     ALOGW("AudioPolicyService server died!");
 }
 
+#ifdef USE_SAMSUNG_SEPARATEDSTREAM
+extern "C" bool _ZN7android11AudioSystem17isSeparatedStreamE19audio_stream_type_t(audio_stream_type_t stream)
+{
+    ALOGD("audio_stream_type_t: %d", stream);
+    ALOGD("isSeparatedStream: false");
+    return false;
+}
+#endif // USE_SAMSUNG_SEPARATEDSTREAM
+
 }; // namespace android
diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp
index e290627..05a0341 100644
--- a/media/libmedia/AudioTrack.cpp
+++ b/media/libmedia/AudioTrack.cpp
@@ -1,5 +1,6 @@
 /*
-**
+** Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+** Not a Contribution.
 ** Copyright 2007, The Android Open Source Project
 **
 ** Licensed under the Apache License, Version 2.0 (the "License");
@@ -53,19 +54,22 @@
     //          audio_format_t format
     //          audio_channel_mask_t channelMask
     //          audio_output_flags_t flags
-    uint32_t afSampleRate;
+    uint32_t afSampleRate = 0;
     if (AudioSystem::getOutputSamplingRate(&afSampleRate, streamType) != NO_ERROR) {
         return NO_INIT;
     }
-    size_t afFrameCount;
+    size_t afFrameCount = 0;
     if (AudioSystem::getOutputFrameCount(&afFrameCount, streamType) != NO_ERROR) {
         return NO_INIT;
     }
-    uint32_t afLatency;
+    uint32_t afLatency = 0;
     if (AudioSystem::getOutputLatency(&afLatency, streamType) != NO_ERROR) {
         return NO_INIT;
     }
-
+    if(!afSampleRate || !afFrameCount) {
+        ALOGW("samplerate or framecount 0");
+        return NO_INIT;
+    }
     // Ensure that buffer depth covers at least audio hardware latency
     uint32_t minBufCount = afLatency / ((1000 * afFrameCount) / afSampleRate);
     if (minBufCount < 2) {
@@ -85,8 +89,16 @@
     : mStatus(NO_INIT),
       mIsTimed(false),
       mPreviousPriority(ANDROID_PRIORITY_NORMAL),
+#ifdef QCOM_HARDWARE
+      mPreviousSchedulingGroup(SP_DEFAULT),
+      mAudioFlinger(NULL),
+      mObserver(NULL),
+      mCblk(NULL),
+      mPausedPosition(0)
+#else
       mPreviousSchedulingGroup(SP_DEFAULT),
       mPausedPosition(0)
+#endif
 {
 }
 
@@ -107,8 +119,16 @@
     : mStatus(NO_INIT),
       mIsTimed(false),
       mPreviousPriority(ANDROID_PRIORITY_NORMAL),
+#ifdef QCOM_HARDWARE
+      mPreviousSchedulingGroup(SP_DEFAULT),
+      mAudioFlinger(NULL),
+      mObserver(NULL),
+      mCblk(NULL),
+      mPausedPosition(0)
+#else
       mPreviousSchedulingGroup(SP_DEFAULT),
       mPausedPosition(0)
+#endif
 {
     mStatus = set(streamType, sampleRate, format, channelMask,
             frameCount, flags, cbf, user, notificationFrames,
@@ -133,8 +153,17 @@
     : mStatus(NO_INIT),
       mIsTimed(false),
       mPreviousPriority(ANDROID_PRIORITY_NORMAL),
+#ifdef QCOM_HARDWARE
+      mPreviousSchedulingGroup(SP_DEFAULT),
+      mProxy(NULL),
+      mAudioFlinger(NULL),
+      mObserver(NULL),
+      mCblk(NULL),
+      mPausedPosition(0)
+#else
       mPreviousSchedulingGroup(SP_DEFAULT),
       mPausedPosition(0)
+#endif
 {
     mStatus = set(streamType, sampleRate, format, channelMask,
             0 /*frameCount*/, flags, cbf, user, notificationFrames,
@@ -154,10 +183,23 @@
             mAudioTrackThread->requestExitAndWait();
             mAudioTrackThread.clear();
         }
+#ifdef QCOM_HARDWARE
+        if (mAudioTrack != 0) {
+            mAudioTrack->asBinder()->unlinkToDeath(mDeathNotifier, this);
+            mAudioTrack.clear();
+            AudioSystem::releaseAudioSessionId(mSessionId);
+        }
+
+        if (mDirectTrack != 0) {
+            mDirectTrack.clear();
+        }
+        IPCThreadState::self()->flushCommands();
+#else
         mAudioTrack->asBinder()->unlinkToDeath(mDeathNotifier, this);
         mAudioTrack.clear();
         IPCThreadState::self()->flushCommands();
         AudioSystem::releaseAudioSessionId(mSessionId);
+#endif
     }
 }
 
@@ -293,6 +335,33 @@
     uint32_t channelCount = popcount(channelMask);
     mChannelCount = channelCount;
 
+#ifdef QCOM_HARDWARE
+    if ((streamType == AUDIO_STREAM_VOICE_CALL)
+         && (channelCount == 1)
+         && ((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);
+    }
+
+    if ((audio_stream_type_t)streamType == AUDIO_STREAM_VOICE_CALL) {
+        if (audio_is_linear_pcm(format)) {
+            mFrameSize = channelCount * audio_bytes_per_sample(format);
+            mFrameSizeAF = channelCount * sizeof(int16_t);
+        } else {
+            mFrameSize = sizeof(uint16_t);
+            mFrameSizeAF = sizeof(uint16_t);
+        }
+    } else {
+        if (audio_is_linear_pcm(format)) {
+            mFrameSize = channelCount * audio_bytes_per_sample(format);
+            mFrameSizeAF = channelCount * sizeof(int16_t);
+        } else {
+            mFrameSize = sizeof(uint8_t);
+            mFrameSizeAF = sizeof(uint8_t);
+        }
+    }
+#else
     if (audio_is_linear_pcm(format)) {
         mFrameSize = channelCount * audio_bytes_per_sample(format);
         mFrameSizeAF = channelCount * sizeof(int16_t);
@@ -300,6 +369,7 @@
         mFrameSize = sizeof(uint8_t);
         mFrameSizeAF = sizeof(uint8_t);
     }
+#endif
 
     audio_io_handle_t output = AudioSystem::getOutput(
                                     streamType,
@@ -328,39 +398,77 @@
     mAuxEffectId = 0;
     mFlags = flags;
     mCbf = cbf;
+#ifdef QCOM_HARDWARE
+    mSampleRate = sampleRate;
 
-    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,
-                                  frameCount,
-                                  flags,
-                                  sharedBuffer,
-                                  output,
-                                  0 /*epoch*/);
-
-    if (status != NO_ERROR) {
-        if (mAudioTrackThread != 0) {
-            mAudioTrackThread->requestExit();   // see comment in AudioTrack.h
-            mAudioTrackThread->requestExitAndWait();
-            mAudioTrackThread.clear();
+    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;
         }
-        //Use of direct and offloaded output streams is ref counted by audio policy manager.
-        // As getOutput was called above and resulted in an output stream to be opened,
-        // we need to release it.
-        AudioSystem::releaseOutput(output);
-        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,
+                                      frameCount,
+                                      flags,
+                                      sharedBuffer,
+                                      output,
+                                      0 /*epoch*/);
+
+        if (status != NO_ERROR) {
+            if (mAudioTrackThread != 0) {
+                mAudioTrackThread->requestExit();   // see comment in AudioTrack.h
+                mAudioTrackThread->requestExitAndWait();
+                mAudioTrackThread.clear();
+            }
+            //Use of direct and offloaded output streams is ref counted by audio policy manager.
+            // As getOutput was called above and resulted in an output stream to be opened,
+            // we need to release it.
+            AudioSystem::releaseOutput(output);
+            return status;
+        }
+#ifdef QCOM_HARDWARE
+        AudioSystem::acquireAudioSessionId(mSessionId);
+        mAudioDirectOutput = -1;
+        mDirectTrack = NULL;
+        mSharedBuffer = sharedBuffer;
+    }
+    mUserData = user;
+#endif
     mStatus = NO_ERROR;
     mStreamType = streamType;
     mFormat = format;
+#ifndef QCOM_HARDWARE
     mSharedBuffer = sharedBuffer;
+#endif
     mState = STATE_STOPPED;
     mUserData = user;
     mLoopPeriod = 0;
@@ -368,7 +476,9 @@
     mMarkerReached = false;
     mNewPosition = 0;
     mUpdatePeriod = 0;
+#ifndef QCOM_HARDWARE
     AudioSystem::acquireAudioSessionId(mSessionId);
+#endif
     mSequence = 1;
     mObservedSequence = mSequence;
     mInUnderrun = false;
@@ -379,10 +489,29 @@
 
 // -------------------------------------------------------------------------
 
+#ifdef QCOM_HARDWARE
+uint32_t AudioTrack::latency() const
+{
+    if (mAudioDirectOutput != -1) {
+        return mAudioFlinger->latency(mAudioDirectOutput);
+    } else if (mOutput != 0) {
+        uint32_t afLatency = 0;
+        uint32_t newLatency = 0;
+        AudioSystem::getLatency(mOutput, mStreamType, &afLatency);
+        if (0 != mSampleRate){
+            newLatency = afLatency + (1000*mCblk->frameCount_) / mSampleRate;
+        }
+        ALOGV("latency() mLatency = %d, newLatency = %d", mLatency, newLatency);
+        return newLatency;
+    }
+    return mLatency;
+}
+#endif
+
 status_t AudioTrack::start()
 {
+    status_t status = NO_ERROR;
     AutoMutex lock(mLock);
-
     if (mState == STATE_ACTIVE) {
         return INVALID_OPERATION;
     }
@@ -395,6 +524,12 @@
     } else {
         mState = STATE_ACTIVE;
     }
+#ifdef QCOM_HARDWARE
+    if (mDirectTrack != NULL) {
+        mDirectTrack->start();
+        return status;
+    }
+#endif
     if (previousState == STATE_STOPPED || previousState == STATE_FLUSHED) {
         // reset current position as seen by client to 0
         mProxy->setEpoch(mProxy->getEpoch() - mProxy->getPosition());
@@ -418,7 +553,6 @@
         androidSetThreadPriority(0, ANDROID_PRIORITY_AUDIO);
     }
 
-    status_t status = NO_ERROR;
     if (!(flags & CBLK_INVALID)) {
         status = mAudioTrack->start();
         if (status == DEAD_OBJECT) {
@@ -459,29 +593,37 @@
         mState = STATE_STOPPED;
     }
 
-    mProxy->interrupt();
-    mAudioTrack->stop();
-    // the playback head position will reset to 0, so if a marker is set, we need
-    // to activate it again
-    mMarkerReached = false;
+#ifdef QCOM_HARDWARE
+    if(mDirectTrack != NULL) {
+        mDirectTrack->stop();
+    } else if (mAudioTrack != NULL) {
+#endif
+        mProxy->interrupt();
+        mAudioTrack->stop();
+        // the playback head position will reset to 0, so if a marker is set, we need
+        // to activate it again
+        mMarkerReached = false;
 #if 0
-    // Force flush if a shared buffer is used otherwise audioflinger
-    // will not stop before end of buffer is reached.
-    // It may be needed to make sure that we stop playback, likely in case looping is on.
-    if (mSharedBuffer != 0) {
-        flush_l();
-    }
+        // Force flush if a shared buffer is used otherwise audioflinger
+        // will not stop before end of buffer is reached.
+        // It may be needed to make sure that we stop playback, likely in case looping is on.
+        if (mSharedBuffer != 0) {
+            flush_l();
+        }
 #endif
 
-    sp<AudioTrackThread> t = mAudioTrackThread;
-    if (t != 0) {
-        if (!isOffloaded()) {
-            t->pause();
+        sp<AudioTrackThread> t = mAudioTrackThread;
+        if (t != 0) {
+            if (!isOffloaded()) {
+                t->pause();
+            }
+        } else {
+            setpriority(PRIO_PROCESS, 0, mPreviousPriority);
+            set_sched_policy(0, mPreviousSchedulingGroup);
         }
-    } else {
-        setpriority(PRIO_PROCESS, 0, mPreviousPriority);
-        set_sched_policy(0, mPreviousSchedulingGroup);
+#ifdef QCOM_HARDWARE
     }
+#endif
 }
 
 bool AudioTrack::stopped() const
@@ -492,10 +634,18 @@
 
 void AudioTrack::flush()
 {
+#ifdef QCOM_HARDWARE
+    if(mDirectTrack != NULL) {
+        ALOGE("mdirect track flush");
+        mDirectTrack->flush();
+        return ;
+    }
+#else
     if (mSharedBuffer != 0) {
         return;
     }
     AutoMutex lock(mLock);
+#endif
     if (mState == STATE_ACTIVE || mState == STATE_FLUSHED) {
         return;
     }
@@ -530,8 +680,17 @@
     } else {
         return;
     }
-    mProxy->interrupt();
-    mAudioTrack->pause();
+#ifdef QCOM_HARDWARE
+    if(mDirectTrack != NULL) {
+        ALOGV("mDirectTrack pause");
+        mDirectTrack->pause();
+    } else {
+#endif
+        mProxy->interrupt();
+        mAudioTrack->pause();
+#ifdef QCOM_HARDWARE
+    }
+#endif
 
     if (isOffloaded()) {
         if (mOutput != 0) {
@@ -553,8 +712,16 @@
     AutoMutex lock(mLock);
     mVolume[LEFT] = left;
     mVolume[RIGHT] = right;
-
-    mProxy->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
+       mProxy->setVolumeLR((uint32_t(uint16_t(right * 0x1000)) << 16) | uint16_t(left * 0x1000));
+#ifdef QCOM_HARDWARE
+    }
+#endif
 
     if (isOffloaded()) {
         mAudioTrack->signal();
@@ -569,6 +736,11 @@
 
 status_t AudioTrack::setAuxEffectSendLevel(float level)
 {
+#ifdef QCOM_HARDWARE
+    if (mDirectTrack != NULL) {
+        return NO_ERROR;
+    }
+#endif
     if (level < 0.0f || level > 1.0f) {
         return BAD_VALUE;
     }
@@ -616,6 +788,11 @@
     }
 
     AutoMutex lock(mLock);
+#ifdef QCOM_HARDWARE
+    if(mAudioDirectOutput != -1) {
+        return mAudioFlinger->sampleRate(mAudioDirectOutput);
+    }
+#endif
 
     // sample rate can be updated during playback by the offloaded decoder so we need to
     // query the HAL and update if needed.
@@ -629,6 +806,7 @@
             }
         }
     }
+
     return mSampleRate;
 }
 
@@ -861,21 +1039,21 @@
 
     // Not all of these values are needed under all conditions, but it is easier to get them all
 
-    uint32_t afLatency;
+    uint32_t afLatency = 0;
     status = AudioSystem::getLatency(output, streamType, &afLatency);
     if (status != NO_ERROR) {
         ALOGE("getLatency(%d) failed status %d", output, status);
         return NO_INIT;
     }
 
-    size_t afFrameCount;
+    size_t afFrameCount = 0;
     status = AudioSystem::getFrameCount(output, streamType, &afFrameCount);
     if (status != NO_ERROR) {
         ALOGE("getFrameCount(output=%d, streamType=%d) status %d", output, streamType, status);
         return NO_INIT;
     }
 
-    uint32_t afSampleRate;
+    uint32_t afSampleRate = 0;
     status = AudioSystem::getSamplingRate(output, streamType, &afSampleRate);
     if (status != NO_ERROR) {
         ALOGE("getSamplingRate(output=%d, streamType=%d) status %d", output, streamType, status);
@@ -945,6 +1123,10 @@
         // FIXME move these calculations and associated checks to server
 
         // Ensure that buffer depth covers at least audio hardware latency
+        if(!afSampleRate && !afFrameCount) {
+            ALOGW("samplerate or framecount zero");
+            return NO_INIT;
+        }
         uint32_t minBufCount = afLatency / ((1000 * afFrameCount)/afSampleRate);
         ALOGV("afFrameCount=%d, minBufCount=%d, afSampleRate=%u, afLatency=%d",
                 afFrameCount, minBufCount, afSampleRate, afLatency);
@@ -1084,7 +1266,11 @@
 
     mAudioTrack->attachAuxEffect(mAuxEffectId);
     // FIXME don't believe this lie
-    mLatency = afLatency + (1000*frameCount) / sampleRate;
+    if(sampleRate){
+        mLatency = afLatency + (1000*frameCount) / sampleRate;
+    }else{
+        mLatency = afLatency;
+    }
     mFrameCount = frameCount;
     // If IAudioTrack is re-created, don't let the requested frameCount
     // decrease.  This can confuse clients that cache frameCount().
@@ -1237,7 +1423,8 @@
     // restart track if it was disabled by audioflinger due to previous underrun
     if (mState == STATE_ACTIVE) {
         audio_track_cblk_t* cblk = mCblk;
-        if (android_atomic_and(~CBLK_DISABLED, &cblk->mFlags) & CBLK_DISABLED) {
+        if (cblk->mFlags & CBLK_DISABLED) {
+            android_atomic_and(~CBLK_DISABLED, &cblk->mFlags);
             ALOGW("releaseBuffer() track %p name=%s disabled due to previous underrun, restarting",
                     this, mName.string());
             // FIXME ignoring status
@@ -1250,6 +1437,13 @@
 
 ssize_t AudioTrack::write(const void* buffer, size_t userSize)
 {
+#ifdef QCOM_HARDWARE
+    if (mDirectTrack != NULL) {
+        ssize_t written = 0;
+        written = mDirectTrack->write(buffer,userSize);
+        return written;
+    }
+#endif
     if (mTransfer != TRANSFER_SYNC || mIsTimed) {
         return INVALID_OPERATION;
     }
@@ -1803,7 +1997,13 @@
     result.append(buffer);
     snprintf(buffer, 255, "  sample rate(%u), status(%d)\n", mSampleRate, mStatus);
     result.append(buffer);
+#ifdef QCOM_HARDWARE
+    uint32_t afLatency = 0;
+    AudioSystem::getLatency(mOutput, mStreamType, &afLatency);
+    snprintf(buffer, 255, "  state(%d), latency (%d)\n", mState, afLatency + (1000*mCblk->frameCount_) / mSampleRate);
+#else
     snprintf(buffer, 255, "  state(%d), latency (%d)\n", mState, mLatency);
+#endif
     result.append(buffer);
     ::write(fd, result.string(), result.size());
     return NO_ERROR;
@@ -1826,6 +2026,27 @@
     }
 }
 
+#ifdef QCOM_HARDWARE
+void AudioTrack::notify(int msg) {
+    if (msg == EVENT_UNDERRUN) {
+        ALOGV("Posting event underrun to Audio Sink.");
+        mCbf(EVENT_UNDERRUN, mUserData, 0);
+    }
+    if (msg == EVENT_HW_FAIL) {
+        ALOGV("Posting event HW fail to Audio Sink.");
+        mCbf(EVENT_HW_FAIL, mUserData, 0);
+    }
+}
+
+status_t AudioTrack::getTimeStamp(uint64_t *tstamp) {
+    if (mDirectTrack != NULL) {
+        *tstamp = mDirectTrack->getTimeStamp();
+        ALOGE("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 acfaea0..89d7a8d 100644
--- a/media/libmedia/IAudioFlinger.cpp
+++ b/media/libmedia/IAudioFlinger.cpp
@@ -1,5 +1,6 @@
 /*
-**
+** Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+** Not a Contribution.
 ** Copyright 2007, The Android Open Source Project
 **
 ** Licensed under the Apache License, Version 2.0 (the "License");
@@ -74,6 +75,9 @@
     GET_PRIMARY_OUTPUT_SAMPLING_RATE,
     GET_PRIMARY_OUTPUT_FRAME_COUNT,
     SET_LOW_RAM_DEVICE,
+#ifdef QCOM_HARDWARE
+    CREATE_DIRECT_TRACK,
+#endif
 };
 
 class BpAudioFlinger : public BpInterface<IAudioFlinger>
@@ -145,6 +149,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(
                                 audio_io_handle_t input,
                                 uint32_t sampleRate,
@@ -785,6 +832,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);
             audio_io_handle_t input = (audio_io_handle_t) data.readInt32();
diff --git a/media/libmedia/IAudioFlingerClient.cpp b/media/libmedia/IAudioFlingerClient.cpp
index 3c0d4cf..65dc3f6 100644
--- a/media/libmedia/IAudioFlingerClient.cpp
+++ b/media/libmedia/IAudioFlingerClient.cpp
@@ -1,4 +1,7 @@
 /*
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ * Not a Contribution.
+ *
  * Copyright (C) 2009 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -49,9 +52,12 @@
             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) {
-            const AudioSystem::OutputDescriptor *desc =
-                    (const AudioSystem::OutputDescriptor *)param2;
+        } else if (event != AudioSystem::OUTPUT_CLOSED && event != AudioSystem::INPUT_CLOSED
+#ifdef QCOM_HARDWARE
+                && event != AudioSystem::EFFECT_CONFIG_CHANGED
+#endif
+        ) {
+            const AudioSystem::OutputDescriptor *desc = (const AudioSystem::OutputDescriptor *)param2;
             data.writeInt32(desc->samplingRate);
             data.writeInt32(desc->format);
             data.writeInt32(desc->channelMask);
diff --git a/media/libmedia/IDirectTrack.cpp b/media/libmedia/IDirectTrack.cpp
new file mode 100644
index 0000000..e12cd74
--- /dev/null
+++ b/media/libmedia/IDirectTrack.cpp
@@ -0,0 +1,177 @@
+/*
+** Copyright (c) 2012, The Linux Foundation. All rights reserved.
+** Not a Contribution
+**
+** 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..f837a14
--- /dev/null
+++ b/media/libmedia/IDirectTrackClient.cpp
@@ -0,0 +1,68 @@
+/*
+** Copyright (c) 2012, The Linux Foundation. All rights reserved.
+** Not a Contribution.
+**
+** 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 8319cd7..2837bab 100644
--- a/media/libmedia/MediaProfiles.cpp
+++ b/media/libmedia/MediaProfiles.cpp
@@ -45,7 +45,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[] = {
@@ -70,6 +73,14 @@
     {"720p", CAMCORDER_QUALITY_720P},
     {"1080p", CAMCORDER_QUALITY_1080P},
     {"qvga", CAMCORDER_QUALITY_QVGA},
+    {"fwvga", CAMCORDER_QUALITY_FWVGA},
+    {"wvga", CAMCORDER_QUALITY_WVGA},
+    {"vga", CAMCORDER_QUALITY_VGA},
+    {"wqvga", CAMCORDER_QUALITY_WQVGA},
+#ifdef QCOM_HARDWARE
+    {"4kuhd", CAMCORDER_QUALITY_4kUHD},
+    {"4kdci", CAMCORDER_QUALITY_4kDCI},
+#endif
 
     {"timelapselow",  CAMCORDER_QUALITY_TIME_LAPSE_LOW},
     {"timelapsehigh", CAMCORDER_QUALITY_TIME_LAPSE_HIGH},
@@ -79,6 +90,12 @@
     {"timelapse720p", CAMCORDER_QUALITY_TIME_LAPSE_720P},
     {"timelapse1080p", CAMCORDER_QUALITY_TIME_LAPSE_1080P},
     {"timelapseqvga", CAMCORDER_QUALITY_TIME_LAPSE_QVGA},
+#ifdef QCOM_HARDWARE
+    {"timelapsevga", CAMCORDER_QUALITY_TIME_LAPSE_VGA},
+    {"timelapsewvga", CAMCORDER_QUALITY_TIME_LAPSE_WVGA},
+    {"timelapsefwvga", CAMCORDER_QUALITY_TIME_LAPSE_FWVGA},
+    {"timelapsewqvga", CAMCORDER_QUALITY_TIME_LAPSE_WQVGA},
+#endif
 };
 
 /*static*/ void
@@ -800,6 +817,10 @@
 MediaProfiles::createDefaultAudioEncoders(MediaProfiles *profiles)
 {
     profiles->mAudioEncoders.add(createDefaultAmrNBEncoderCap());
+#ifdef QCOM_HARDWARE
+    profiles->mAudioEncoders.add(createDefaultAacEncoderCap());
+    profiles->mAudioEncoders.add(createDefaultLpcmEncoderCap());
+#endif
 }
 
 /*static*/ void
@@ -833,6 +854,20 @@
     return new MediaProfiles::AudioEncoderCap(
         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)
diff --git a/media/libmedia/MediaScanner.cpp b/media/libmedia/MediaScanner.cpp
index 28b5aa7..6ea5b7e 100644
--- a/media/libmedia/MediaScanner.cpp
+++ b/media/libmedia/MediaScanner.cpp
@@ -139,6 +139,18 @@
         return MEDIA_SCAN_RESULT_OK;
     }
 
+    // Completely skip all directories containing a ".noscanandnomtp" file
+    if (pathRemaining >= 15 /* strlen(".noscanandnomtp") */ ) {
+        strcpy(fileSpot, ".noscanandnomtp");
+        if (access(path, F_OK) == 0) {
+            ALOGV("found .noscanandnomtp, completely skipping");
+            return MEDIA_SCAN_RESULT_SKIPPED;
+        }
+
+        // restore path
+        fileSpot[0] = 0;
+    }
+
     // Treat all files as non-media in directories that contain a  ".nomedia" file
     if (pathRemaining >= 8 /* strlen(".nomedia") */ ) {
         strcpy(fileSpot, ".nomedia");
diff --git a/media/libmedia/mediaplayer.cpp b/media/libmedia/mediaplayer.cpp
index 0f6d897..9a8f94e 100644
--- a/media/libmedia/mediaplayer.cpp
+++ b/media/libmedia/mediaplayer.cpp
@@ -683,7 +683,11 @@
     }
 
     // Allows calls from JNI in idle state to notify errors
+#ifdef QCOM_HARDWARE
+    if (!((msg == MEDIA_ERROR || msg == MEDIA_QOE) && mCurrentState == MEDIA_PLAYER_IDLE) && mPlayer == 0) {
+#else
     if (!(msg == MEDIA_ERROR && mCurrentState == MEDIA_PLAYER_IDLE) && mPlayer == 0) {
+#endif
         ALOGV("notify(%d, %d, %d) callback on disconnected mediaplayer", msg, ext1, ext2);
         if (locked) mLock.unlock();   // release the lock when done.
         return;
@@ -758,6 +762,10 @@
         break;
     case MEDIA_SUBTITLE_DATA:
         ALOGV("Received subtitle data message");
+#ifdef QCOM_HARDWARE
+    case MEDIA_QOE:
+        ALOGV("Received QOE Message for event : %d",ext2);
+#endif
         break;
     default:
         ALOGV("unrecognized message: (%d, %d, %d)", msg, ext1, ext2);
@@ -843,4 +851,11 @@
     return INVALID_OPERATION;
 }
 
+#ifdef SAMSUNG_CAMERA_LEGACY
+extern "C" int _ZN7android11MediaPlayer18setAudioStreamTypeE19audio_stream_type_t();
+extern "C" int _ZN7android11MediaPlayer18setAudioStreamTypeEi() {
+    return _ZN7android11MediaPlayer18setAudioStreamTypeE19audio_stream_type_t();
+}
+#endif
+
 }; // namespace android
diff --git a/media/libmediaplayerservice/Android.mk b/media/libmediaplayerservice/Android.mk
index 8f21632..badb84c 100644
--- a/media/libmediaplayerservice/Android.mk
+++ b/media/libmediaplayerservice/Android.mk
@@ -38,6 +38,7 @@
     libstagefright_omx          \
     libstagefright_wfd          \
     libutils                    \
+    libdl                       \
     libvorbisidec               \
 
 LOCAL_STATIC_LIBRARIES :=       \
@@ -52,8 +53,30 @@
     $(TOP)/frameworks/native/include/media/openmax                  \
     $(TOP)/external/tremolo/Tremolo                                 \
 
+ifeq ($(BOARD_USES_QCOM_HARDWARE),true)
+    ifneq ($(TARGET_QCOM_MEDIA_VARIANT),)
+    LOCAL_C_INCLUDES += \
+            $(TOP)/hardware/qcom/media-$(TARGET_QCOM_MEDIA_VARIANT)/mm-core/inc
+    else
+    LOCAL_C_INCLUDES += \
+            $(TOP)/hardware/qcom/media/mm-core/inc
+    endif
+endif
+
 LOCAL_MODULE:= libmediaplayerservice
 
+ifeq ($(TARGET_ENABLE_QC_AV_ENHANCEMENTS),true)
+    LOCAL_CFLAGS += -DENABLE_AV_ENHANCEMENTS
+    LOCAL_C_INCLUDES += $(TOP)/frameworks/av/include/media
+    ifneq ($(TARGET_QCOM_MEDIA_VARIANT),)
+        LOCAL_C_INCLUDES += \
+            $(TOP)/hardware/qcom/media-$(TARGET_QCOM_MEDIA_VARIANT)/mm-core/inc
+    else
+        LOCAL_C_INCLUDES += \
+            $(TOP)/hardware/qcom/media/mm-core/inc
+    endif
+endif #TARGET_ENABLE_QC_AV_ENHANCEMENTS
+
 include $(BUILD_SHARED_LIBRARY)
 
 include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/media/libmediaplayerservice/MediaPlayerFactory.cpp b/media/libmediaplayerservice/MediaPlayerFactory.cpp
index 90aed39..29e1edd 100644
--- a/media/libmediaplayerservice/MediaPlayerFactory.cpp
+++ b/media/libmediaplayerservice/MediaPlayerFactory.cpp
@@ -30,6 +30,7 @@
 #include "TestPlayerStub.h"
 #include "StagefrightPlayer.h"
 #include "nuplayer/NuPlayerDriver.h"
+#include <dlfcn.h>
 
 namespace android {
 
@@ -339,6 +340,32 @@
     registerFactory_l(new SonivoxPlayerFactory(), SONIVOX_PLAYER);
     registerFactory_l(new TestPlayerFactory(), TEST_PLAYER);
 
+    const char* FACTORY_LIB           = "libdashplayer.so";
+    const char* FACTORY_CREATE_FN     = "CreateDASHFactory";
+
+    MediaPlayerFactory::IFactory* pFactory  = NULL;
+    void* pFactoryLib = NULL;
+    typedef MediaPlayerFactory::IFactory* (*CreateDASHDriverFn)();
+    ALOGE("calling dlopen on FACTORY_LIB");
+    pFactoryLib = ::dlopen(FACTORY_LIB, RTLD_LAZY);
+    if (pFactoryLib == NULL) {
+      ALOGE("Failed to open FACTORY_LIB Error : %s ",::dlerror());
+    } else {
+      CreateDASHDriverFn pCreateFnPtr;
+      ALOGE("calling dlsym on pFactoryLib for FACTORY_CREATE_FN ");
+      pCreateFnPtr = (CreateDASHDriverFn) dlsym(pFactoryLib, FACTORY_CREATE_FN);
+      if (pCreateFnPtr == NULL) {
+          ALOGE("Could not locate pCreateFnPtr");
+      } else {
+        pFactory = pCreateFnPtr();
+        if(pFactory == NULL) {
+          ALOGE("Failed to invoke CreateDASHDriverFn...");
+        } else {
+          ALOGE("registering DASH Player factory...");
+          registerFactory_l(pFactory,DASH_PLAYER);
+        }
+      }
+    }
     sInitComplete = true;
 }
 
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index 9ac9105..685e181 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -1,5 +1,8 @@
 /*
 **
+** Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+** Not a Contribution.
+**
 ** Copyright 2008, The Android Open Source Project
 **
 ** Licensed under the Apache License, Version 2.0 (the "License");
@@ -78,6 +81,9 @@
 #include "HDCP.h"
 #include "HTTPBase.h"
 #include "RemoteDisplay.h"
+#ifdef QCOM_HARDWARE
+#define DEFAULT_SAMPLE_RATE 44100
+#endif
 
 namespace {
 using android::media::Metadata;
@@ -1373,6 +1379,13 @@
     return mTrack->latency();
 }
 
+#ifdef QCOM_HARDWARE
+audio_stream_type_t MediaPlayerService::AudioOutput::streamType () const
+{
+    return mStreamType;
+}
+#endif
+
 float MediaPlayerService::AudioOutput::msecsPerFrame() const
 {
     return mMsecsPerFrame;
@@ -1384,6 +1397,22 @@
     return mTrack->getPosition(position);
 }
 
+#ifdef QCOM_HARDWARE
+ssize_t MediaPlayerService::AudioOutput::sampleRate() const
+{
+    if (mTrack == 0) return NO_INIT;
+    return DEFAULT_SAMPLE_RATE;
+}
+
+status_t MediaPlayerService::AudioOutput::getTimeStamp(uint64_t *tstamp)
+{
+    if (tstamp == 0) return BAD_VALUE;
+    if (mTrack == 0) return NO_INIT;
+    mTrack->getTimeStamp(tstamp);
+    return NO_ERROR;
+}
+#endif
+
 status_t MediaPlayerService::AudioOutput::getFramesWritten(uint32_t *frameswritten) const
 {
     if (mTrack == 0) return NO_INIT;
@@ -1439,7 +1468,50 @@
 {
     mCallback = cb;
     mCallbackCookie = cookie;
+#ifdef QCOM_HARDWARE
+    if (flags & AUDIO_OUTPUT_FLAG_LPA || flags & AUDIO_OUTPUT_FLAG_TUNNEL) {
+        ALOGV("AudioOutput open: with flags %x",flags);
+        channelMask = audio_channel_out_mask_from_count(channelCount);
+        if (0 == channelMask) {
+            ALOGE("open() error, can't derive mask for %d audio channels", channelCount);
+            return NO_INIT;
+        }
+        AudioTrack *audioTrack = NULL;
+        CallbackData *newcbd = NULL;
+        if (mCallback != NULL) {
+            newcbd = new CallbackData(this);
+            audioTrack = new AudioTrack(
+                             mStreamType,
+                             sampleRate,
+                             format,
+                             channelMask,
+                             0,
+                             flags,
+                             CallbackWrapper,
+                             newcbd,
+                             0,
+                             mSessionId);
+            if ((audioTrack == 0) || (audioTrack->initCheck() != NO_ERROR)) {
+                ALOGE("Unable to create audio track");
+                delete audioTrack;
+                delete newcbd;
+                return NO_INIT;
+            }
+        } else {
+            ALOGE("no callback supplied");
+            return NO_INIT;
+        }
+        deleteRecycledTrack();
 
+        ALOGV("setVolume");
+        mCallbackData = newcbd;
+        audioTrack->setVolume(mLeftVolume, mRightVolume);
+        mSampleRateHz = sampleRate;
+        mFlags = flags;
+        mTrack = audioTrack;
+        return NO_ERROR;
+    }
+#endif
     // Check argument "bufferCount" against the mininum buffer count
     if (bufferCount < mMinBufferCount) {
         ALOGD("bufferCount (%d) is too small and increased to %d", bufferCount, mMinBufferCount);
@@ -1672,7 +1744,6 @@
 
 ssize_t MediaPlayerService::AudioOutput::write(const void* buffer, size_t size)
 {
-    LOG_FATAL_IF(mCallback != NULL, "Don't call write if supplying a callback.");
 
     //ALOGV("write(%p, %u)", buffer, size);
     if (mTrack != 0) {
@@ -1704,7 +1775,7 @@
 void MediaPlayerService::AudioOutput::close()
 {
     ALOGV("close");
-    mTrack.clear();
+    if (mTrack != 0) mTrack.clear();
 }
 
 void MediaPlayerService::AudioOutput::setVolume(float left, float right)
@@ -1757,55 +1828,101 @@
 void MediaPlayerService::AudioOutput::CallbackWrapper(
         int event, void *cookie, void *info) {
     //ALOGV("callbackwrapper");
-    CallbackData *data = (CallbackData*)cookie;
-    data->lock();
-    AudioOutput *me = data->getOutput();
-    AudioTrack::Buffer *buffer = (AudioTrack::Buffer *)info;
-    if (me == NULL) {
-        // no output set, likely because the track was scheduled to be reused
-        // by another player, but the format turned out to be incompatible.
+#ifdef QCOM_HARDWARE
+    if (event == AudioTrack::EVENT_UNDERRUN) {
+        ALOGW("Event underrun");
+        CallbackData *data = (CallbackData*)cookie;
+        data->lock();
+        AudioOutput *me = data->getOutput();
+        if (me == NULL) {
+            // no output set, likely because the track was scheduled to be reused
+            // by another player, but the format turned out to be incompatible.
+            data->unlock();
+            return;
+        }
+        ALOGD("Callback!!!");
+        (*me->mCallback)(
+            me, NULL, (size_t)AudioTrack::EVENT_UNDERRUN, me->mCallbackCookie, CB_EVENT_UNDERRUN);
         data->unlock();
-        if (buffer != NULL) {
-            buffer->size = 0;
+        return;
+    }
+    if (event == AudioTrack::EVENT_HW_FAIL) {
+        ALOGW("Event hardware failure");
+        CallbackData *data = (CallbackData*)cookie;
+        if (data != NULL) {
+            data->lock();
+            AudioOutput *me = data->getOutput();
+            if (me == NULL) {
+                // no output set, likely because the track was
+                // scheduled to be reused
+                // by another player, but the format turned out
+                // to be incompatible.
+                data->unlock();
+                return;
+            }
+            ALOGV("Callback!!!");
+            (*me->mCallback)(me, NULL, (size_t)AudioTrack::EVENT_HW_FAIL,
+                             me->mCallbackCookie, CB_EVENT_HW_FAIL);
+            data->unlock();
         }
         return;
     }
-
-    switch(event) {
-    case AudioTrack::EVENT_MORE_DATA: {
-        size_t actualSize = (*me->mCallback)(
-                me, buffer->raw, buffer->size, me->mCallbackCookie,
-                CB_EVENT_FILL_BUFFER);
-
-        if (actualSize == 0 && buffer->size > 0 && me->mNextOutput == NULL) {
-            // We've reached EOS but the audio track is not stopped yet,
-            // keep playing silence.
-
-            memset(buffer->raw, 0, buffer->size);
-            actualSize = buffer->size;
+    if (event == AudioTrack::EVENT_MORE_DATA) {
+#endif
+        CallbackData *data = (CallbackData*)cookie;
+        data->lock();
+        AudioOutput *me = data->getOutput();
+        AudioTrack::Buffer *buffer = (AudioTrack::Buffer *)info;
+        if (me == NULL) {
+            // no output set, likely because the track was scheduled to be reused
+            // by another player, but the format turned out to be incompatible.
+            data->unlock();
+            if (buffer != NULL) {
+                buffer->size = 0;
+            }
+            return;
         }
 
-        buffer->size = actualSize;
-        } break;
+        switch(event) {
+        case AudioTrack::EVENT_MORE_DATA: {
+            size_t actualSize = (*me->mCallback)(
+                    me, buffer->raw, buffer->size, me->mCallbackCookie,
+                    CB_EVENT_FILL_BUFFER);
+
+            if (actualSize == 0 && buffer->size > 0 && me->mNextOutput == NULL) {
+                // We've reached EOS but the audio track is not stopped yet,
+                // keep playing silence.
+
+                memset(buffer->raw, 0, buffer->size);
+                actualSize = buffer->size;
+            }
+
+            buffer->size = actualSize;
+            } break;
 
 
-    case AudioTrack::EVENT_STREAM_END:
-        ALOGV("callbackwrapper: deliver EVENT_STREAM_END");
-        (*me->mCallback)(me, NULL /* buffer */, 0 /* size */,
-                me->mCallbackCookie, CB_EVENT_STREAM_END);
-        break;
+        case AudioTrack::EVENT_STREAM_END:
+            ALOGV("callbackwrapper: deliver EVENT_STREAM_END");
+            (*me->mCallback)(me, NULL /* buffer */, 0 /* size */,
+                    me->mCallbackCookie, CB_EVENT_STREAM_END);
+            break;
 
-    case AudioTrack::EVENT_NEW_IAUDIOTRACK :
-        ALOGV("callbackwrapper: deliver EVENT_TEAR_DOWN");
-        (*me->mCallback)(me,  NULL /* buffer */, 0 /* size */,
-                me->mCallbackCookie, CB_EVENT_TEAR_DOWN);
-        break;
+        case AudioTrack::EVENT_NEW_IAUDIOTRACK :
+            ALOGV("callbackwrapper: deliver EVENT_TEAR_DOWN");
+            (*me->mCallback)(me,  NULL /* buffer */, 0 /* size */,
+                    me->mCallbackCookie, CB_EVENT_TEAR_DOWN);
+            break;
 
-    default:
-        ALOGE("received unknown event type: %d inside CallbackWrapper !", event);
+        default:
+            ALOGE("received unknown event type: %d inside CallbackWrapper !", event);
+        }
+
+        data->unlock();
+#ifdef QCOM_HARDWARE
     }
+#endif
 
-    data->unlock();
+    return;
 }
 
 int MediaPlayerService::AudioOutput::getSessionId() const
@@ -1844,6 +1961,13 @@
     return NO_ERROR;
 }
 
+#ifdef QCOM_HARDWARE
+ssize_t MediaPlayerService::AudioCache::sampleRate() const
+{
+    return mSampleRate;
+}
+#endif
+
 status_t MediaPlayerService::AudioCache::getFramesWritten(uint32_t *written) const
 {
     if (written == 0) return BAD_VALUE;
diff --git a/media/libmediaplayerservice/MediaPlayerService.h b/media/libmediaplayerservice/MediaPlayerService.h
index 9c084e1..83b074d 100644
--- a/media/libmediaplayerservice/MediaPlayerService.h
+++ b/media/libmediaplayerservice/MediaPlayerService.h
@@ -1,5 +1,8 @@
 /*
 **
+** Copyright (c) 2013, The Linux Foundation. All rights reserved.
+** Not a Contribution.
+**
 ** Copyright 2008, The Android Open Source Project
 **
 ** Licensed under the Apache License, Version 2.0 (the "License");
@@ -82,6 +85,9 @@
         virtual ssize_t         channelCount() const;
         virtual ssize_t         frameSize() const;
         virtual uint32_t        latency() const;
+#ifdef QCOM_HARDWARE
+        virtual audio_stream_type_t streamType() const;
+#endif
         virtual float           msecsPerFrame() const;
         virtual status_t        getPosition(uint32_t *position) const;
         virtual status_t        getFramesWritten(uint32_t *frameswritten) const;
@@ -116,9 +122,15 @@
                 void            setNextOutput(const sp<AudioOutput>& nextOutput);
                 void            switchToNextOutput();
         virtual bool            needsTrailingPadding() { return mNextOutput == NULL; }
+
         virtual status_t        setParameters(const String8& keyValuePairs);
         virtual String8         getParameters(const String8& keys);
 
+#ifdef QCOM_HARDWARE
+        virtual ssize_t         sampleRate() const;
+        virtual status_t        getTimeStamp(uint64_t *tstamp);
+#endif
+
     private:
         static void             setMinBufferCount();
         static void             CallbackWrapper(
@@ -217,7 +229,11 @@
 
                 void            setVolume(float left, float right) {}
         virtual status_t        setPlaybackRatePermille(int32_t ratePermille) { return INVALID_OPERATION; }
+#ifdef QCOM_HARDWARE
+        virtual ssize_t         sampleRate() const;
+#else
                 uint32_t        sampleRate() const { return mSampleRate; }
+#endif
                 audio_format_t  format() const { return mFormat; }
                 size_t          size() const { return mSize; }
                 status_t        wait();
diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp
index f9d9020..831de2c 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.cpp
+++ b/media/libmediaplayerservice/StagefrightRecorder.cpp
@@ -18,6 +18,9 @@
 #define LOG_TAG "StagefrightRecorder"
 #include <utils/Log.h>
 
+#ifdef QCOM_HARDWARE
+#include <media/AudioParameter.h>
+#endif
 #include "StagefrightRecorder.h"
 
 #include <binder/IPCThreadState.h>
@@ -29,6 +32,10 @@
 #include <media/stagefright/AudioSource.h>
 #include <media/stagefright/AMRWriter.h>
 #include <media/stagefright/AACWriter.h>
+#ifdef QCOM_HARDWARE
+#include <media/stagefright/ExtendedWriter.h>
+#include <media/stagefright/WAVEWriter.h>
+#endif
 #include <media/stagefright/CameraSource.h>
 #include <media/stagefright/CameraSourceTimeLapse.h>
 #include <media/stagefright/MPEG2TSWriter.h>
@@ -42,6 +49,7 @@
 #include <camera/ICamera.h>
 #include <camera/CameraParameters.h>
 #include <gui/Surface.h>
+#include <utils/String8.h>
 
 #include <utils/Errors.h>
 #include <sys/types.h>
@@ -49,8 +57,15 @@
 #include <unistd.h>
 
 #include <system/audio.h>
+#ifdef QCOM_HARDWARE
+#include "ExtendedUtils.h"
+#ifdef ENABLE_AV_ENHANCEMENTS
+#include <QCMediaDefs.h>
+#endif
+#endif
 
 #include "ARTPWriter.h"
+#include <cutils/properties.h>
 
 namespace android {
 
@@ -103,6 +118,11 @@
         ALOGE("Invalid audio source: %d", as);
         return BAD_VALUE;
     }
+#ifdef QCOM_HARDWARE
+    if (ExtendedUtils::ShellProp::isAudioDisabled()) {
+        return OK;
+    }
+#endif
 
     if (as == AUDIO_SOURCE_DEFAULT) {
         mAudioSource = AUDIO_SOURCE_MIC;
@@ -155,12 +175,36 @@
         return BAD_VALUE;
     }
 
+#ifdef QCOM_HARDWARE
+    if (ExtendedUtils::ShellProp::isAudioDisabled()) {
+        return OK;
+    }
+#endif
     if (ae == AUDIO_ENCODER_DEFAULT) {
         mAudioEncoder = AUDIO_ENCODER_AMR_NB;
     } else {
         mAudioEncoder = ae;
     }
 
+#ifdef QCOM_HARDWARE
+    if(mAudioEncoder == AUDIO_ENCODER_AAC) {
+        mSampleRate = mSampleRate ? mSampleRate : 48000;
+        mAudioChannels = mAudioChannels ? mAudioChannels : 2;
+        mAudioBitRate = mAudioBitRate ? mAudioBitRate : 156000;
+    } else if(mAudioEncoder == AUDIO_ENCODER_LPCM) {
+        mSampleRate = mSampleRate ? mSampleRate : 48000;
+        mAudioChannels = mAudioChannels ? mAudioChannels : 2;
+        mAudioBitRate = mAudioBitRate ? mAudioBitRate : 4608000;
+    } else if(mAudioEncoder == AUDIO_ENCODER_AMR_WB) {
+        mSampleRate = 16000;
+        mAudioChannels = 1;
+        mAudioBitRate = mAudioBitRate ? mAudioBitRate : 23850;
+    } else {
+        mSampleRate = mSampleRate ? mSampleRate : 8000;
+        mAudioChannels = mAudioChannels ? mAudioChannels : 1;
+        mAudioBitRate = mAudioBitRate ? mAudioBitRate : 12200;
+    }
+#endif
     return OK;
 }
 
@@ -329,7 +373,11 @@
 
 status_t StagefrightRecorder::setParamAudioNumberOfChannels(int32_t channels) {
     ALOGV("setParamAudioNumberOfChannels: %d", channels);
+#ifdef QCOM_HARDWARE
+    if (channels != 1 && channels != 2 && channels != 6) {
+#else
     if (channels <= 0 || channels >= 3) {
+#endif
         ALOGE("Invalid number of audio channels: %d", channels);
         return BAD_VALUE;
     }
@@ -416,6 +464,11 @@
         ALOGW("Target file size (%lld bytes) is too small to be respected", bytes);
     }
 
+    if (bytes >= 0xffffffffLL) {
+        ALOGW("Target file size (%lld bytes) too larger than supported, clip to 4GB", bytes);
+        bytes = 0xffffffffLL;
+    }
+
     mMaxFileSizeBytes = bytes;
     return OK;
 }
@@ -739,7 +792,18 @@
 }
 
 status_t StagefrightRecorder::prepare() {
-    return OK;
+  ALOGV(" %s E", __func__ );
+
+  if(mVideoSource != VIDEO_SOURCE_LIST_END && mVideoEncoder != VIDEO_ENCODER_LIST_END && mVideoHeight && mVideoWidth &&             /*Video recording*/
+         (mMaxFileDurationUs <=0 ||             /*Max duration is not set*/
+         (mVideoHeight * mVideoWidth < 720 * 1280 && mMaxFileDurationUs > 30*60*1000*1000) ||
+         (mVideoHeight * mVideoWidth >= 720 * 1280 && mMaxFileDurationUs > 10*60*1000*1000))) {
+    /*Above Check can be further optimized for lower resolutions to reduce file size*/
+    ALOGV("File is huge so setting 64 bit file offsets");
+    setParam64BitFileOffset(true);
+  }
+  ALOGV(" %s X", __func__ );
+  return OK;
 }
 
 status_t StagefrightRecorder::start() {
@@ -779,6 +843,16 @@
             status = startMPEG2TSRecording();
             break;
 
+#ifdef QCOM_HARDWARE
+#ifdef ENABLE_AV_ENHANCEMENTS
+        case OUTPUT_FORMAT_QCP:
+            status = startExtendedRecording( );
+            break;
+#endif
+        case OUTPUT_FORMAT_WAVE:
+            status = startWAVERecording( );
+            break;
+#endif
         default:
             ALOGE("Unsupported output file format: %d", mOutputFormat);
             status = UNKNOWN_ERROR;
@@ -803,6 +877,54 @@
 }
 
 sp<MediaSource> StagefrightRecorder::createAudioSource() {
+#ifdef QCOM_HARDWARE
+    bool tunneledSource = false;
+    const char *tunnelMime;
+    {
+        AudioParameter param;
+        String8 key("tunneled-input-formats");
+        param.add( key, String8("get") );
+        String8 valueStr = AudioSystem::getParameters( 0, param.toString());
+        AudioParameter result(valueStr);
+        int value;
+        if ( mAudioEncoder == AUDIO_ENCODER_AMR_NB &&
+            result.getInt(String8("AMR"),value) == NO_ERROR ) {
+            tunneledSource = true;
+            tunnelMime = MEDIA_MIMETYPE_AUDIO_AMR_NB;
+        }
+#ifdef ENABLE_AV_ENHANCEMENTS
+        else if ( mAudioEncoder == AUDIO_ENCODER_QCELP &&
+            result.getInt(String8("QCELP"),value) == NO_ERROR ) {
+            tunneledSource = true;
+            tunnelMime = MEDIA_MIMETYPE_AUDIO_QCELP;
+        }
+        else if ( mAudioEncoder == AUDIO_ENCODER_EVRC &&
+            result.getInt(String8("EVRC"),value) == NO_ERROR ) {
+            tunneledSource = true;
+            tunnelMime = MEDIA_MIMETYPE_AUDIO_EVRC;
+        }
+#endif
+        else if ( mAudioEncoder == AUDIO_ENCODER_AMR_WB &&
+            result.getInt(String8("AWB"),value) == NO_ERROR ) {
+            tunneledSource = true;
+            tunnelMime = MEDIA_MIMETYPE_AUDIO_AMR_WB;
+        }
+    }
+    if ( tunneledSource ) {
+        ALOGD("tunnel recording");
+        sp<AudioSource> audioSource = NULL;
+        sp<MetaData> meta = new MetaData;
+        meta->setInt32(kKeyChannelCount, mAudioChannels);
+        meta->setInt32(kKeySampleRate, mSampleRate);
+        meta->setInt32(kKeyBitRate, mAudioBitRate);
+        if (mAudioTimeScale > 0) {
+            meta->setInt32(kKeyTimeScale, mAudioTimeScale);
+        }
+        meta->setCString( kKeyMIMEType, tunnelMime );
+        audioSource = new AudioSource( mAudioSource, meta);
+        return audioSource->initCheck( ) == OK ? audioSource : NULL;
+    }
+#endif
     sp<AudioSource> audioSource =
         new AudioSource(
                 mAudioSource,
@@ -819,6 +941,11 @@
     sp<MetaData> encMeta = new MetaData;
     const char *mime;
     switch (mAudioEncoder) {
+#ifdef QCOM_HARDWARE
+        case AUDIO_ENCODER_LPCM:
+            mime = MEDIA_MIMETYPE_AUDIO_RAW;
+            break;
+#endif
         case AUDIO_ENCODER_AMR_NB:
         case AUDIO_ENCODER_DEFAULT:
             mime = MEDIA_MIMETYPE_AUDIO_AMR_NB;
@@ -838,6 +965,14 @@
             mime = MEDIA_MIMETYPE_AUDIO_AAC;
             encMeta->setInt32(kKeyAACProfile, OMX_AUDIO_AACObjectELD);
             break;
+#ifdef ENABLE_AV_ENHANCEMENTS
+        case AUDIO_ENCODER_EVRC:
+            mime = MEDIA_MIMETYPE_AUDIO_EVRC;
+            break;
+        case AUDIO_ENCODER_QCELP:
+            mime = MEDIA_MIMETYPE_AUDIO_QCELP;
+            break;
+#endif
 
         default:
             ALOGE("Unknown audio encoder: %d", mAudioEncoder);
@@ -859,9 +994,30 @@
 
     OMXClient client;
     CHECK_EQ(client.connect(), (status_t)OK);
+#ifdef ENABLE_AV_ENHANCEMENTS
+    sp<MediaSource> audioEncoder;
+    if (ExtendedUtils::UseQCHWAACEncoder(mAudioEncoder,mAudioChannels,mAudioBitRate,mSampleRate)) {
+        ALOGV("use QCOM HW AAC encoder");
+        audioEncoder = OMXCodec::Create(client.interface(), encMeta,
+            true /* createEncoder */, audioSource,"OMX.qcom.audio.encoder.aac",OMXCodec::kHardwareCodecsOnly );
+    } else {
+        audioEncoder = OMXCodec::Create(client.interface(), encMeta,
+            true /* createEncoder */, audioSource);
+    }
+#else
     sp<MediaSource> audioEncoder =
         OMXCodec::Create(client.interface(), encMeta,
                          true /* createEncoder */, audioSource);
+#endif
+#ifdef QCOM_HARDWARE
+    if (audioEncoder == NULL) {
+        ALOGD("No encoder is needed, use the AudioSource directly as the MediaSource for LPCM format");
+        audioEncoder = audioSource;
+    }
+    if (mAudioSourceNode != NULL) {
+        mAudioSourceNode.clear();
+    }
+#endif
     mAudioSourceNode = audioSource;
 
     return audioEncoder;
@@ -898,14 +1054,32 @@
                     mAudioEncoder);
             return BAD_VALUE;
         }
+        if (mSampleRate != 8000) {
+            ALOGE("Invalid sampling rate %d used for AMRNB recording",
+                    mSampleRate);
+            return BAD_VALUE;
+        }
     } else {  // mOutputFormat must be OUTPUT_FORMAT_AMR_WB
         if (mAudioEncoder != AUDIO_ENCODER_AMR_WB) {
             ALOGE("Invlaid encoder %d used for AMRWB recording",
                     mAudioEncoder);
             return BAD_VALUE;
         }
+#if 0
+//This check breaks android.media.cts.MediaRecorderTest#testRecordingAudioInRawFormats, which is hardwired to test 8kHz
+        if (mSampleRate != 16000) {
+            ALOGE("Invalid sample rate %d used for AMRWB recording",
+                    mSampleRate);
+            return BAD_VALUE;
+        }
+#endif
     }
 
+    if (mAudioChannels != 1) {
+        ALOGE("Invalid number of audio channels %d used for amr recording",
+                mAudioChannels);
+        return BAD_VALUE;
+    }
     mWriter = new AMRWriter(mOutputFd);
     status_t status = startRawAudioRecording();
     if (status != OK) {
@@ -915,6 +1089,21 @@
     return status;
 }
 
+#ifdef QCOM_HARDWARE
+status_t StagefrightRecorder::startWAVERecording() {
+    CHECK(mOutputFormat == OUTPUT_FORMAT_WAVE);
+    CHECK(mAudioEncoder == AUDIO_ENCODER_LPCM);
+    CHECK(mAudioSource != AUDIO_SOURCE_CNT);
+    mWriter = new WAVEWriter(mOutputFd);
+    status_t status = startRawAudioRecording();
+    if (status != OK) {
+        mWriter.clear();
+        mWriter = NULL;
+    }
+    return status;
+}
+#endif
+
 status_t StagefrightRecorder::startRawAudioRecording() {
     if (mAudioSource >= AUDIO_SOURCE_CNT) {
         ALOGE("Invalid audio source: %d", mAudioSource);
@@ -1427,6 +1616,17 @@
     if (mVideoTimeScale > 0) {
         enc_meta->setInt32(kKeyTimeScale, mVideoTimeScale);
     }
+
+#ifdef QCOM_HARDWARE
+    status_t retVal = ExtendedUtils::HFR::reCalculateFileDuration(
+            meta, enc_meta, mMaxFileDurationUs, mFrameRate, mVideoEncoder);
+    if(retVal != OK) {
+        return retVal;
+    }
+
+    ExtendedUtils::ShellProp::setEncoderProfile(mVideoEncoder, mVideoEncoderProfile);
+#endif
+
     if (mVideoEncoderProfile != -1) {
         enc_meta->setInt32(kKeyVideoProfile, mVideoEncoderProfile);
     }
@@ -1479,6 +1679,9 @@
         case AUDIO_ENCODER_AAC:
         case AUDIO_ENCODER_HE_AAC:
         case AUDIO_ENCODER_AAC_ELD:
+#ifdef QCOM_HARDWARE
+        case AUDIO_ENCODER_LPCM:
+#endif
             break;
 
         default:
@@ -1641,6 +1844,13 @@
         mOutputFd = -1;
     }
 
+#ifdef QCOM_HARDWARE
+    if (mAudioSourceNode != NULL) {
+        mAudioSourceNode.clear();
+        mAudioSourceNode = NULL;
+    }
+#endif
+
     if (mStarted) {
         mStarted = false;
 
@@ -1682,9 +1892,15 @@
     mVideoHeight   = 144;
     mFrameRate     = -1;
     mVideoBitRate  = 192000;
+#ifdef QCOM_HARDWARE
+    mSampleRate    = 0;
+    mAudioChannels = 0;
+    mAudioBitRate  = 0;
+#else
     mSampleRate    = 8000;
     mAudioChannels = 1;
     mAudioBitRate  = 12200;
+#endif
     mInterleaveDurationUs = 0;
     mIFramesIntervalSec = 1;
     mAudioSourceNode = 0;
@@ -1796,4 +2012,39 @@
     ::write(fd, result.string(), result.size());
     return OK;
 }
+#ifdef ENABLE_AV_ENHANCEMENTS
+status_t StagefrightRecorder::startExtendedRecording() {
+    CHECK(mOutputFormat == OUTPUT_FORMAT_QCP);
+    if (mSampleRate != 8000) {
+        ALOGE("Invalid sampling rate %d used for recording",
+             mSampleRate);
+        return BAD_VALUE;
+    }
+    if (mAudioChannels != 1) {
+        ALOGE("Invalid number of audio channels %d used for recording",
+                mAudioChannels);
+        return BAD_VALUE;
+    }
+    if (mAudioSource >= AUDIO_SOURCE_CNT) {
+        ALOGE("Invalid audio source: %d", mAudioSource);
+        return BAD_VALUE;
+    }
+    sp<MediaSource> audioEncoder = createAudioSource();
+    if (audioEncoder == NULL) {
+        ALOGE("AudioEncoder NULL");
+        return UNKNOWN_ERROR;
+    }
+    mWriter = new ExtendedWriter(dup(mOutputFd));
+    mWriter->addSource(audioEncoder);
+    if (mMaxFileDurationUs != 0) {
+        mWriter->setMaxFileDuration(mMaxFileDurationUs);
+    }
+    if (mMaxFileSizeBytes != 0) {
+        mWriter->setMaxFileSize(mMaxFileSizeBytes);
+    }
+    mWriter->setListener(mListener);
+    mWriter->start();
+    return OK;
+}
+#endif
 }  // namespace android
diff --git a/media/libmediaplayerservice/StagefrightRecorder.h b/media/libmediaplayerservice/StagefrightRecorder.h
index 31f09e0..2e834b4 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.h
+++ b/media/libmediaplayerservice/StagefrightRecorder.h
@@ -135,6 +135,9 @@
     status_t startMPEG4Recording();
     status_t startAMRRecording();
     status_t startAACRecording();
+#ifdef QCOM_HARDWARE
+    status_t startWAVERecording();
+#endif
     status_t startRawAudioRecording();
     status_t startRTPRecording();
     status_t startMPEG2TSRecording();
@@ -191,6 +194,9 @@
 
     StagefrightRecorder(const StagefrightRecorder &);
     StagefrightRecorder &operator=(const StagefrightRecorder &);
+#ifdef ENABLE_AV_ENHANCEMENTS
+    status_t startExtendedRecording();
+#endif
 };
 
 }  // namespace android
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
index 2423fd5..0357a68 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
@@ -25,6 +25,9 @@
 #include <media/stagefright/foundation/AMessage.h>
 #include <media/stagefright/ACodec.h>
 #include <media/stagefright/MediaDefs.h>
+#ifdef QCOM_HARDWARE
+#include <media/stagefright/ExtendedCodec.h>
+#endif
 
 namespace android {
 
@@ -57,6 +60,20 @@
         mCSD.push(csd);
     }
 
+#ifdef QCOM_HARDWARE
+    sp<ABuffer> extendedCSD = ExtendedCodec::getRawCodecSpecificData(format);
+    if (extendedCSD != NULL) {
+        ALOGV("pushing extended CSD of size %d", extendedCSD->size());
+        mCSD.push(extendedCSD);
+    }
+
+    sp<ABuffer> aacCSD = ExtendedCodec::getAacCodecSpecificData(format);
+    if (aacCSD != NULL) {
+        ALOGV("pushing AAC CSD of size %d", aacCSD->size());
+        mCSD.push(aacCSD);
+    }
+#endif
+
     if (mNativeWindow != NULL) {
         format->setObject("native-window", mNativeWindow);
     }
diff --git a/media/libnbaio/AudioStreamOutSink.cpp b/media/libnbaio/AudioStreamOutSink.cpp
index e4341d7..d5937b2 100644
--- a/media/libnbaio/AudioStreamOutSink.cpp
+++ b/media/libnbaio/AudioStreamOutSink.cpp
@@ -72,11 +72,14 @@
 
     if (NULL == mStream)
         return INVALID_OPERATION;
-
+#ifndef ICS_AUDIO_BLOB
     if (NULL == mStream->get_next_write_timestamp)
         return INVALID_OPERATION;
 
     return mStream->get_next_write_timestamp(mStream, timestamp);
+#else
+    return INVALID_OPERATION;
+#endif
 }
 
 status_t AudioStreamOutSink::getTimestamp(AudioTimestamp& timestamp)
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
old mode 100644
new mode 100755
index 9276818..03a8ac3
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -32,12 +32,26 @@
 #include <media/stagefright/NativeWindowWrapper.h>
 #include <media/stagefright/OMXClient.h>
 #include <media/stagefright/OMXCodec.h>
+#ifdef QCOM_HARDWARE
+#include <media/stagefright/ExtendedCodec.h>
+#endif
 
 #include <media/hardware/HardwareAPI.h>
 
 #include <OMX_Component.h>
 
+#ifdef USE_SAMSUNG_COLORFORMAT
+#include <sec_format.h>
+#endif
+
+#ifdef USE_TI_CUSTOM_DOMX
+#include <OMX_TI_IVCommon.h>
+#endif
+
 #include "include/avc_utils.h"
+#ifdef QCOM_HARDWARE
+#include "include/ExtendedUtils.h"
+#endif
 
 namespace android {
 
@@ -371,8 +385,14 @@
       mDequeueCounter(0),
       mStoreMetaDataInOutputBuffers(false),
       mMetaDataBuffersToSubmit(0),
+#ifdef QCOM_HARDWARE
+      mRepeatFrameDelayUs(-1ll),
+      mMaxPtsGapUs(-1l),
+      mInSmoothStreamingMode(false) {
+#else
       mRepeatFrameDelayUs(-1ll),
       mMaxPtsGapUs(-1l) {
+#endif
     mUninitializedState = new UninitializedState(this);
     mLoadedState = new LoadedState(this);
     mLoadedToIdleState = new LoadedToIdleState(this);
@@ -574,11 +594,22 @@
         return err;
     }
 
+#ifdef USE_SAMSUNG_COLORFORMAT
+    OMX_COLOR_FORMATTYPE eNativeColorFormat = def.format.video.eColorFormat;
+    setNativeWindowColorFormat(eNativeColorFormat);
+
+    err = native_window_set_buffers_geometry(
+    mNativeWindow.get(),
+    def.format.video.nFrameWidth,
+    def.format.video.nFrameHeight,
+    eNativeColorFormat);
+#else
     err = native_window_set_buffers_geometry(
             mNativeWindow.get(),
             def.format.video.nFrameWidth,
             def.format.video.nFrameHeight,
             def.format.video.eColorFormat);
+#endif
 
     if (err != 0) {
         ALOGE("native_window_set_buffers_geometry failed: %s (%d)",
@@ -792,6 +823,25 @@
     return OK;
 }
 
+#ifdef USE_SAMSUNG_COLORFORMAT
+void ACodec::setNativeWindowColorFormat(OMX_COLOR_FORMATTYPE &eNativeColorFormat)
+{
+    // In case of Samsung decoders, we set proper native color format for the Native Window
+    if (!strcasecmp(mComponentName.c_str(), "OMX.SEC.AVC.Decoder")
+        || !strcasecmp(mComponentName.c_str(), "OMX.SEC.FP.AVC.Decoder")) {
+        switch (eNativeColorFormat) {
+            case OMX_COLOR_FormatYUV420SemiPlanar:
+                eNativeColorFormat = (OMX_COLOR_FORMATTYPE)HAL_PIXEL_FORMAT_YCbCr_420_SP;
+                break;
+            case OMX_COLOR_FormatYUV420Planar:
+            default:
+                eNativeColorFormat = (OMX_COLOR_FORMATTYPE)HAL_PIXEL_FORMAT_YCbCr_420_P;
+                break;
+        }
+    }
+}
+#endif
+
 status_t ACodec::cancelBufferToNativeWindow(BufferInfo *info) {
     CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US);
 
@@ -955,6 +1005,10 @@
             "audio_decoder.amrnb", "audio_encoder.amrnb" },
         { MEDIA_MIMETYPE_AUDIO_AMR_WB,
             "audio_decoder.amrwb", "audio_encoder.amrwb" },
+#ifdef ENABLE_AV_ENHANCEMENTS
+        { MEDIA_MIMETYPE_AUDIO_AMR_WB_PLUS,
+            "audio_decoder.amrwbplus", "audio_encoder.amrwbplus" },
+#endif
         { MEDIA_MIMETYPE_AUDIO_AAC,
             "audio_decoder.aac", "audio_encoder.aac" },
         { MEDIA_MIMETYPE_AUDIO_VORBIS,
@@ -992,7 +1046,11 @@
     }
 
     if (i == kNumMimeToRole) {
+#ifdef QCOM_HARDWARE
+        return ExtendedCodec::setSupportedRole(mOMX, mNode, isEncoder, mime);
+#else
         return ERROR_UNSUPPORTED;
+#endif
     }
 
     const char *role =
@@ -1123,10 +1181,19 @@
     mStoreMetaDataInOutputBuffers = false;
     mIsConfiguredForAdaptivePlayback = false;
     if (!encoder && video && haveNativeWindow) {
-        err = mOMX->storeMetaDataInBuffers(mNode, kPortIndexOutput, OMX_TRUE);
-        if (err != OK) {
-            ALOGE("[%s] storeMetaDataInBuffers failed w/ err %d",
-                  mComponentName.c_str(), err);
+        int32_t preferAdaptive = 0;
+        if (msg->findInt32("prefer-adaptive-playback", &preferAdaptive)
+                && preferAdaptive == 1) {
+            ALOGI("[%s] Adaptive playback preferred", mComponentName.c_str());
+        } else {
+            preferAdaptive = 0;
+            err = mOMX->storeMetaDataInBuffers(mNode, kPortIndexOutput, OMX_TRUE);
+        }
+        if (err != OK || preferAdaptive) {
+            if (!preferAdaptive) {
+                ALOGE("[%s] storeMetaDataInBuffers failed w/ err %d",
+                      mComponentName.c_str(), err);
+            }
 
             // if adaptive playback has been requested, try JB fallback
             // NOTE: THIS FALLBACK MECHANISM WILL BE REMOVED DUE TO ITS
@@ -1158,7 +1225,7 @@
             if (canDoAdaptivePlayback &&
                 msg->findInt32("max-width", &maxWidth) &&
                 msg->findInt32("max-height", &maxHeight)) {
-                ALOGV("[%s] prepareForAdaptivePlayback(%ldx%ld)",
+                ALOGI("[%s] prepareForAdaptivePlayback(%ldx%ld)",
                       mComponentName.c_str(), maxWidth, maxHeight);
 
                 err = mOMX->prepareForAdaptivePlayback(
@@ -1168,6 +1235,14 @@
                         mComponentName.c_str(), err);
                 mIsConfiguredForAdaptivePlayback = (err == OK);
             }
+            // if Adaptive mode was tried first and codec failed it, try dynamic mode
+            if (err != OK && preferAdaptive) {
+                err = mOMX->storeMetaDataInBuffers(mNode, kPortIndexOutput, OMX_TRUE);
+                if (err != OK) {
+                    ALOGE("[%s] storeMetaDataInBuffers failed w/ err %d",
+                          mComponentName.c_str(), err);
+                }
+            }
             // allow failure
             err = OK;
         } else {
@@ -1176,6 +1251,9 @@
             mIsConfiguredForAdaptivePlayback = true;
         }
 
+        ALOGI("DRC Mode: %s",(mStoreMetaDataInOutputBuffers ? "Dynamic Buffer Mode" :
+                (mIsConfiguredForAdaptivePlayback ? "Adaptive Mode" : "Port Reconfig Mode")));
+
         int32_t push;
         if (msg->findInt32("push-blank-buffers-on-shutdown", &push)
                 && push != 0) {
@@ -1195,6 +1273,12 @@
                 err = setupVideoDecoder(mime, width, height);
             }
         }
+#ifdef QCOM_HARDWARE
+        if (err == OK) {
+            const char* componentName = mComponentName.c_str();
+            ExtendedCodec::configureVideoDecoder(msg, mime, mOMX, 0, mNode, componentName);
+        }
+#endif
     } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_MPEG)) {
         int32_t numChannels, sampleRate;
         if (!msg->findInt32("channel-count", &numChannels)
@@ -1277,6 +1361,21 @@
         } else {
             err = setupRawAudioFormat(kPortIndexInput, sampleRate, numChannels);
         }
+#ifdef QCOM_HARDWARE
+    } else {
+        if (encoder) {
+            int32_t numChannels, sampleRate;
+            if (msg->findInt32("channel-count", &numChannels)
+                  && msg->findInt32("sample-rate", &sampleRate)) {
+                setupRawAudioFormat(kPortIndexInput, sampleRate, numChannels);
+            }
+       }
+       err = ExtendedCodec::setAudioFormat(
+                 msg, mime, mOMX, mNode, mIsEncoder);
+       if(err != OK) {
+           return err;
+       }
+#endif
     }
 
     if (err != OK) {
@@ -1755,7 +1854,11 @@
     status_t err = GetVideoCodingTypeFromMime(mime, &compressionFormat);
 
     if (err != OK) {
-        return err;
+#ifdef QCOM_HARDWARE
+        err = ExtendedCodec::setVideoOutputFormat(mime, &compressionFormat);
+        if (err != OK)
+#endif
+            return err;
     }
 
     err = setVideoPortFormatType(
@@ -1785,6 +1888,11 @@
         return err;
     }
 
+#ifdef QCOM_HARDWARE
+    ExtendedCodec::enableSmoothStreaming(
+            mOMX, mNode, &mInSmoothStreamingMode, mComponentName.c_str());
+#endif
+
     return OK;
 }
 
@@ -1878,7 +1986,15 @@
     err = GetVideoCodingTypeFromMime(mime, &compressionFormat);
 
     if (err != OK) {
-        return err;
+#ifdef QCOM_HARDWARE
+        err = ExtendedCodec::setVideoInputFormat(mime, &compressionFormat);
+        if (err != OK) {
+            ALOGE("Not a supported video mime type: %s", mime);
+#endif
+            return err;
+#ifdef QCOM_HARDWARE
+        }
+#endif
     }
 
     err = setVideoPortFormatType(
@@ -2558,6 +2674,11 @@
                             rect.nTop,
                             rect.nLeft + rect.nWidth,
                             rect.nTop + rect.nHeight);
+#ifdef QCOM_HARDWARE
+                    reply->setInt32(
+                            "color-format",
+                            (int)(videoDef->eColorFormat));
+#endif
                 }
             }
             break;
@@ -2674,7 +2795,26 @@
                 }
 
                 default:
+                {
+#ifdef QCOM_HARDWARE
+                    AString mimeType;
+                    status_t err = ExtendedCodec::handleSupportedAudioFormats(
+                        audioDef->eEncoding, &mimeType);
+                    if (err == OK) {
+                        int channelCount;
+                        err = ExtendedCodec::getSupportedAudioFormatInfo(
+                                      &mimeType,
+                                      mOMX,
+                                      mNode,
+                                      kPortIndexOutput,
+                                      &channelCount);
+                        notify->setString("mime", mimeType.c_str());
+                        notify->setInt32("channel-count", channelCount);
+                        break;
+                    }
+#endif
                     TRESPASS();
+                }
             }
             break;
         }
@@ -3429,6 +3569,15 @@
     android_native_rect_t crop;
     if (msg->findRect("crop",
             &crop.left, &crop.top, &crop.right, &crop.bottom)) {
+#ifdef QCOM_HARDWARE
+        if (mCodec->mInSmoothStreamingMode) {
+            OMX_COLOR_FORMATTYPE eColorFormat = OMX_COLOR_FormatUnused;
+            CHECK(msg->findInt32("color-format", (int32_t*)&eColorFormat));
+            ExtendedUtils::updateNativeWindowBufferGeometry(
+                    mCodec->mNativeWindow.get(), crop.right,
+                    crop.bottom, eColorFormat);
+        }
+#endif
         CHECK_EQ(0, native_window_set_crop(
                 mCodec->mNativeWindow.get(), &crop));
     }
@@ -3641,6 +3790,9 @@
             ++matchIndex) {
         componentName = matchingCodecs.itemAt(matchIndex).mName.string();
         quirks = matchingCodecs.itemAt(matchIndex).mQuirks;
+#ifdef QCOM_HARDWARE
+        ExtendedCodec::overrideComponentName(quirks, msg, &componentName);
+#endif
 
         pid_t tid = androidGetTid();
         int prevPriority = androidGetThreadPriority(tid);
diff --git a/media/libstagefright/Android.mk b/media/libstagefright/Android.mk
index 6a2a696..c819046 100644
--- a/media/libstagefright/Android.mk
+++ b/media/libstagefright/Android.mk
@@ -3,6 +3,10 @@
 
 include frameworks/av/media/libstagefright/codecs/common/Config.mk
 
+ifeq ($(BOARD_HTC_3D_SUPPORT),true)
+   LOCAL_CFLAGS += -DHTC_3D_SUPPORT
+endif
+
 LOCAL_SRC_FILES:=                         \
         ACodec.cpp                        \
         AACExtractor.cpp                  \
@@ -52,6 +56,7 @@
         Utils.cpp                         \
         VBRISeeker.cpp                    \
         WAVExtractor.cpp                  \
+        WAVEWriter.cpp                    \
         WVMExtractor.cpp                  \
         XINGSeeker.cpp                    \
         avc_utils.cpp                     \
@@ -61,12 +66,48 @@
 LOCAL_C_INCLUDES:= \
         $(TOP)/frameworks/av/include/media/stagefright/timedtext \
         $(TOP)/frameworks/native/include/media/hardware \
-        $(TOP)/frameworks/native/include/media/openmax \
         $(TOP)/frameworks/native/services/connectivitymanager \
         $(TOP)/external/flac/include \
         $(TOP)/external/tremolo \
         $(TOP)/external/openssl/include \
 
+ifneq ($(TI_CUSTOM_DOMX_PATH),)
+LOCAL_C_INCLUDES += $(TI_CUSTOM_DOMX_PATH)/omx_core/inc
+LOCAL_CPPFLAGS += -DUSE_TI_CUSTOM_DOMX
+else
+LOCAL_C_INCLUDES += $(TOP)/frameworks/native/include/media/openmax
+endif
+
+ifneq ($(filter caf bfam,$(TARGET_QCOM_AUDIO_VARIANT)),)
+    ifeq ($(BOARD_USES_ALSA_AUDIO),true)
+        LOCAL_SRC_FILES += LPAPlayerALSA.cpp
+        ifeq ($(call is-chipset-in-board-platform,msm8960),true)
+            LOCAL_SRC_FILES += TunnelPlayer.cpp
+            LOCAL_CFLAGS += -DUSE_TUNNEL_MODE
+            LOCAL_CFLAGS += -DTUNNEL_MODE_SUPPORTS_AMRWB
+        endif
+        ifeq ($(call is-chipset-in-board-platform,msm8974),true)
+            LOCAL_SRC_FILES += TunnelPlayer.cpp
+            LOCAL_CFLAGS += -DUSE_TUNNEL_MODE
+        endif
+        ifeq ($(NO_TUNNEL_MODE_FOR_MULTICHANNEL),true)
+            LOCAL_CFLAGS += -DNO_TUNNEL_MODE_FOR_MULTICHANNEL
+        endif
+    else
+        LOCAL_SRC_FILES += LPAPlayer.cpp
+        LOCAL_CFLAGS += -DLEGACY_LPA
+    endif
+    LOCAL_CFLAGS += -DQCOM_ENHANCED_AUDIO -DUSE_LPA_MODE
+endif
+
+ifneq ($(TARGET_QCOM_MEDIA_VARIANT),)
+LOCAL_C_INCLUDES += \
+        $(TOP)/hardware/qcom/media-$(TARGET_QCOM_MEDIA_VARIANT)/mm-core/inc
+else
+LOCAL_C_INCLUDES += \
+        $(TOP)/hardware/qcom/media/mm-core/inc
+endif
+
 LOCAL_SHARED_LIBRARIES := \
         libbinder \
         libcamera_client \
@@ -93,6 +134,7 @@
 
 LOCAL_STATIC_LIBRARIES := \
         libstagefright_color_conversion \
+        libstagefright_mp3dec \
         libstagefright_aacenc \
         libstagefright_matroska \
         libstagefright_timedtext \
@@ -103,6 +145,22 @@
         libFLAC \
         libmedia_helper
 
+
+LOCAL_SRC_FILES += ExtendedCodec.cpp ExtendedExtractor.cpp ExtendedUtils.cpp
+
+ifeq ($(TARGET_ENABLE_QC_AV_ENHANCEMENTS),true)
+       LOCAL_CFLAGS     += -DENABLE_AV_ENHANCEMENTS
+       LOCAL_SRC_FILES  += ExtendedMediaDefs.cpp ExtendedWriter.cpp
+
+       ifneq ($(TARGET_QCOM_MEDIA_VARIANT),)
+           LOCAL_C_INCLUDES += \
+               $(TOP)/hardware/qcom/media-$(TARGET_QCOM_MEDIA_VARIANT)/mm-core/inc
+       else
+           LOCAL_C_INCLUDES += \
+               $(TOP)/hardware/qcom/media/mm-core/inc
+       endif
+endif #TARGET_ENABLE_AV_ENHANCEMENTS
+
 LOCAL_SRC_FILES += \
         chromium_http_stub.cpp
 LOCAL_CPPFLAGS += -DCHROMIUM_AVAILABLE=1
@@ -118,6 +176,26 @@
 
 LOCAL_CFLAGS += -Wno-multichar
 
+ifeq ($(BOARD_USE_SAMSUNG_COLORFORMAT), true)
+LOCAL_CFLAGS += -DUSE_SAMSUNG_COLORFORMAT
+
+# Include native color format header path
+LOCAL_C_INCLUDES += \
+	$(TOP)/hardware/samsung/exynos4/hal/include \
+	$(TOP)/hardware/samsung/exynos4/include
+
+endif
+
+ifeq ($(BOARD_USE_TI_DUCATI_H264_PROFILE), true)
+LOCAL_CFLAGS += -DUSE_TI_DUCATI_H264_PROFILE
+endif
+
+ifdef DOLBY_UDC
+  LOCAL_CFLAGS += -DDOLBY_UDC
+endif #DOLBY_UDC
+ifdef DOLBY_UDC_MULTICHANNEL
+  LOCAL_CFLAGS += -DDOLBY_UDC_MULTICHANNEL
+endif #DOLBY_UDC_MULTICHANNEL
 LOCAL_MODULE:= libstagefright
 
 LOCAL_MODULE_TAGS := optional
diff --git a/media/libstagefright/AudioPlayer.cpp b/media/libstagefright/AudioPlayer.cpp
index 05ee34e..c07d79e 100644
--- a/media/libstagefright/AudioPlayer.cpp
+++ b/media/libstagefright/AudioPlayer.cpp
@@ -1,4 +1,6 @@
 /*
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ * Not a Contribution.
  * Copyright (C) 2009 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -36,8 +38,7 @@
 
 AudioPlayer::AudioPlayer(
         const sp<MediaPlayerBase::AudioSink> &audioSink,
-        uint32_t flags,
-        AwesomePlayer *observer)
+        uint32_t flags, AwesomePlayer *observer)
     : mInputBuffer(NULL),
       mSampleRate(0),
       mLatencyUs(0),
@@ -51,6 +52,9 @@
       mFinalStatus(OK),
       mSeekTimeUs(0),
       mStarted(false),
+#ifdef QCOM_HARDWARE
+      mSourcePaused(false),
+#endif
       mIsFirstBuffer(false),
       mFirstBufferResult(OK),
       mFirstBuffer(NULL),
@@ -79,6 +83,9 @@
 
     status_t err;
     if (!sourceAlreadyStarted) {
+#ifdef QCOM_HARDWARE
+        mSourcePaused = false;
+#endif
         err = mSource->start();
 
         if (err != OK) {
@@ -253,7 +260,6 @@
 
 void AudioPlayer::pause(bool playPendingSamples) {
     CHECK(mStarted);
-
     if (playPendingSamples) {
         if (mAudioSink.get() != NULL) {
             mAudioSink->stop();
@@ -274,10 +280,23 @@
     }
 
     mPlaying = false;
+#ifdef QCOM_HARDWARE
+    CHECK(mSource != NULL);
+    if (mSource->pause() == OK) {
+        mSourcePaused = true;
+    }
+#endif
 }
 
 status_t AudioPlayer::resume() {
     CHECK(mStarted);
+#ifdef QCOM_HARDWARE
+    CHECK(mSource != NULL);
+    if (mSourcePaused == true) {
+        mSourcePaused = false;
+        mSource->start();
+    }
+#endif
     status_t err;
 
     if (mAudioSink.get() != NULL) {
@@ -339,7 +358,9 @@
         mInputBuffer->release();
         mInputBuffer = NULL;
     }
-
+#ifdef QCOM_HARDWARE
+    mSourcePaused = false;
+#endif
     mSource->stop();
 
     // The following hack is necessary to ensure that the OMX
@@ -415,6 +436,13 @@
         MediaPlayerBase::AudioSink::cb_event_t event) {
     AudioPlayer *me = (AudioPlayer *)cookie;
 
+#ifdef QCOM_HARDWARE
+    if (buffer == NULL) {
+        //Not applicable for AudioPlayer
+        ALOGE("This indicates the event underrun case for LPA/Tunnel");
+        return 0;
+    }
+#endif
     switch(event) {
     case MediaPlayerBase::AudioSink::CB_EVENT_FILL_BUFFER:
         return me->fillBuffer(buffer, size);
@@ -668,11 +696,11 @@
     {
         Mutex::Autolock autoLock(mLock);
         mNumFramesPlayed += size_done / mFrameSize;
-        mNumFramesPlayedSysTimeUs = ALooper::GetNowUs();
 
         if (mReachedEOS) {
             mPinnedTimeUs = mNumFramesPlayedSysTimeUs;
         } else {
+            mNumFramesPlayedSysTimeUs = ALooper::GetNowUs();
             mPinnedTimeUs = -1ll;
         }
     }
@@ -691,10 +719,14 @@
 int64_t AudioPlayer::getRealTimeUs() {
     Mutex::Autolock autoLock(mLock);
     if (useOffload()) {
+        int64_t playPosition = 0;
         if (mSeeking) {
             return mSeekTimeUs;
         }
-        mPositionTimeRealUs = getOutputPlayPositionUs_l();
+        playPosition = getOutputPlayPositionUs_l();
+        if(!mReachedEOS)
+            mPositionTimeRealUs = playPosition;
+        mPositionTimeMediaUs = mPositionTimeRealUs;
         return mPositionTimeRealUs;
     }
 
@@ -711,14 +743,21 @@
     // compensate using system time.
     int64_t diffUs;
     if (mPinnedTimeUs >= 0ll) {
-        diffUs = mPinnedTimeUs;
+        if(mReachedEOS)
+            diffUs = ALooper::GetNowUs();
+        else
+            diffUs = mPinnedTimeUs;
+
     } else {
         diffUs = ALooper::GetNowUs();
     }
 
     diffUs -= mNumFramesPlayedSysTimeUs;
 
-    return result + diffUs;
+    if(result + diffUs <= mPositionTimeRealUs)
+        return result + diffUs;
+    else
+        return mPositionTimeRealUs;
 }
 
 int64_t AudioPlayer::getOutputPlayPositionUs_l()
@@ -753,12 +792,17 @@
     Mutex::Autolock autoLock(mLock);
 
     if (useOffload()) {
+        int64_t playPosition = 0;
         if (mSeeking) {
             return mSeekTimeUs;
         }
-        mPositionTimeRealUs = getOutputPlayPositionUs_l();
-        ALOGV("getMediaTimeUs getOutputPlayPositionUs_l() mPositionTimeRealUs %lld",
-              mPositionTimeRealUs);
+
+        playPosition = getOutputPlayPositionUs_l();
+        if (!mReachedEOS)
+            mPositionTimeRealUs = playPosition;
+        ALOGV("getMediaTimeUs getOutputPlayPositionUs_l() playPosition = %lld,\
+              mPositionTimeRealUs %lld", playPosition, mPositionTimeRealUs);
+        mPositionTimeMediaUs = mPositionTimeRealUs;
         return mPositionTimeRealUs;
     }
 
@@ -781,7 +825,11 @@
     Mutex::Autolock autoLock(mLock);
 
     if (useOffload()) {
-        mPositionTimeRealUs = getOutputPlayPositionUs_l();
+        int64_t playPosition = 0;
+        playPosition = getOutputPlayPositionUs_l();
+        if(!mReachedEOS)
+            mPositionTimeRealUs = playPosition;
+        mPositionTimeMediaUs = mPositionTimeRealUs;
         *realtime_us = mPositionTimeRealUs;
         *mediatime_us = mPositionTimeRealUs;
     } else {
diff --git a/media/libstagefright/AudioSource.cpp b/media/libstagefright/AudioSource.cpp
index d7223d9..17d7e1b 100644
--- a/media/libstagefright/AudioSource.cpp
+++ b/media/libstagefright/AudioSource.cpp
@@ -27,9 +27,15 @@
 #include <media/stagefright/foundation/ALooper.h>
 #include <cutils/properties.h>
 #include <stdlib.h>
+#ifdef ENABLE_AV_ENHANCEMENTS
+#include <QCMediaDefs.h>
+#endif
+#include <system/audio.h>
+#define DEFAULT_TUNNEL_BUFFER_COUNT 4
 
 namespace android {
 
+const static int64_t WaitLockEventTimeOutNs = 1000000000LL;
 static void AudioRecordCallbackFunction(int event, void *user, void *info) {
     AudioSource *source = (AudioSource *) user;
     switch (event) {
@@ -49,23 +55,49 @@
 
 AudioSource::AudioSource(
         audio_source_t inputSource, uint32_t sampleRate, uint32_t channelCount)
+#ifdef QCOM_HARDWARE
+    : mRecord(NULL),
+      mStarted(false),
+#else
     : mStarted(false),
+#endif
       mSampleRate(sampleRate),
       mPrevSampleTimeUs(0),
       mNumFramesReceived(0),
+#ifdef QCOM_HARDWARE
+      mNumClientOwnedBuffers(0),
+      mFormat(AUDIO_FORMAT_PCM_16_BIT),
+      mMime(MEDIA_MIMETYPE_AUDIO_RAW) {
+#else
       mNumClientOwnedBuffers(0) {
+#endif
     ALOGV("sampleRate: %d, channelCount: %d", sampleRate, channelCount);
+#ifdef QCOM_HARDWARE
+    CHECK(channelCount == 1 || channelCount == 2 || channelCount == 6);
+#else
     CHECK(channelCount == 1 || channelCount == 2);
+#endif
 
     size_t minFrameCount;
     status_t status = AudioRecord::getMinFrameCount(&minFrameCount,
                                            sampleRate,
                                            AUDIO_FORMAT_PCM_16_BIT,
                                            audio_channel_in_mask_from_count(channelCount));
+#ifdef QCOM_HARDWARE
+    if ( NO_ERROR != AudioSystem::getInputBufferSize(
+        sampleRate, mFormat, channelCount, (size_t*)&mMaxBufferSize) ) {
+        mMaxBufferSize = kMaxBufferSize;
+        ALOGV("mMaxBufferSize = %d", mMaxBufferSize);
+    }
+#endif
     if (status == OK) {
         // make sure that the AudioRecord callback never returns more than the maximum
         // buffer size
+#ifdef QCOM_HARDWARE
+        int frameCount = mMaxBufferSize / sizeof(int16_t) / channelCount;
+#else
         int frameCount = kMaxBufferSize / sizeof(int16_t) / channelCount;
+#endif
 
         // make sure that the AudioRecord total buffer size is large enough
         int bufCount = 2;
@@ -76,16 +108,85 @@
         mRecord = new AudioRecord(
                     inputSource, sampleRate, AUDIO_FORMAT_PCM_16_BIT,
                     audio_channel_in_mask_from_count(channelCount),
+#ifdef QCOM_HARDWARE
+                    DEFAULT_TUNNEL_BUFFER_COUNT * mMaxBufferSize / sizeof(int16_t), /* Enable ping-pong buffers */
+#else
                     bufCount * frameCount,
+#endif
                     AudioRecordCallbackFunction,
                     this,
                     frameCount);
         mInitCheck = mRecord->initCheck();
+        mAutoRampStartUs = kAutoRampStartUs;
+        uint32_t playbackLatencyMs = 0;
+        if (AudioSystem::getOutputLatency(&playbackLatencyMs,
+                                          AUDIO_STREAM_DEFAULT) == OK) {
+            if (2*playbackLatencyMs*1000LL > kAutoRampStartUs) {
+                mAutoRampStartUs = 2*playbackLatencyMs*1000LL;
+            }
+        }
+        ALOGD("Start autoramp from %lld", mAutoRampStartUs);
     } else {
         mInitCheck = status;
     }
 }
 
+#ifdef QCOM_HARDWARE
+AudioSource::AudioSource( audio_source_t inputSource, const sp<MetaData>& meta )
+    : mStarted(false),
+      mPrevSampleTimeUs(0),
+      mNumFramesReceived(0),
+      mNumClientOwnedBuffers(0),
+      mFormat(AUDIO_FORMAT_PCM_16_BIT),
+      mMime(MEDIA_MIMETYPE_AUDIO_RAW) {
+    const char * mime;
+    ALOGE("SK: in AudioSource : inputSource: %d", inputSource);
+    CHECK( meta->findCString( kKeyMIMEType, &mime ) );
+    mMime = mime;
+    int32_t sampleRate = 0; //these are the only supported values
+    int32_t channels = 0;      //for the below tunnel formats
+    CHECK( meta->findInt32( kKeyChannelCount, &channels ) );
+    CHECK( meta->findInt32( kKeySampleRate, &sampleRate ) );
+    int32_t frameSize = -1;
+    mSampleRate = sampleRate;
+    if ( !strcasecmp( mime, MEDIA_MIMETYPE_AUDIO_AMR_NB ) ) {
+        mFormat = AUDIO_FORMAT_AMR_NB;
+        frameSize = AMR_FRAMESIZE;
+        mMaxBufferSize = AMR_FRAMESIZE*10;
+    }
+#ifdef ENABLE_AV_ENHANCEMENTS
+    else if ( !strcasecmp( mime, MEDIA_MIMETYPE_AUDIO_QCELP ) ) {
+        mFormat = AUDIO_FORMAT_QCELP;
+        frameSize = QCELP_FRAMESIZE;
+        mMaxBufferSize = QCELP_FRAMESIZE*10;
+    }
+    else if ( !strcasecmp( mime, MEDIA_MIMETYPE_AUDIO_EVRC ) ) {
+        mFormat = AUDIO_FORMAT_EVRC;
+        frameSize = EVRC_FRAMESIZE;
+        mMaxBufferSize = EVRC_FRAMESIZE*10;
+    }
+#endif
+    else if ( !strcasecmp( mime, MEDIA_MIMETYPE_AUDIO_AMR_WB ) ) {
+        mFormat = AUDIO_FORMAT_AMR_WB;
+        frameSize = AMR_WB_FRAMESIZE;
+        mMaxBufferSize = AMR_WB_FRAMESIZE*10;
+    }
+    else {
+        CHECK(0);
+    }
+    mAutoRampStartUs = 0;
+    CHECK(channels == 1 || channels == 2);
+    mRecord = new AudioRecord(
+                inputSource, sampleRate, mFormat,
+                channels > 1? AUDIO_CHANNEL_IN_STEREO:
+                AUDIO_CHANNEL_IN_MONO,
+                4*mMaxBufferSize/channels/frameSize,
+                AudioRecordCallbackFunction,
+                this);
+    mInitCheck = mRecord->initCheck();
+}
+#endif
+
 AudioSource::~AudioSource() {
     if (mStarted) {
         reset();
@@ -167,10 +268,19 @@
     }
 
     sp<MetaData> meta = new MetaData;
+#ifdef QCOM_HARDWARE
+    meta->setCString(kKeyMIMEType, mMime);
+    meta->setInt32(kKeySampleRate, mRecord->getSampleRate());
+#else
     meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_RAW);
     meta->setInt32(kKeySampleRate, mSampleRate);
+#endif
     meta->setInt32(kKeyChannelCount, mRecord->channelCount());
+#ifdef QCOM_HARDWARE
+    meta->setInt32(kKeyMaxInputSize, mMaxBufferSize);
+#else
     meta->setInt32(kKeyMaxInputSize, kMaxBufferSize);
+#endif
 
     return meta;
 }
@@ -217,7 +327,9 @@
     }
 
     while (mStarted && mBuffersReceived.empty()) {
-        mFrameAvailableCondition.wait(mLock);
+       status_t err = mFrameAvailableCondition.waitRelative(mLock,WaitLockEventTimeOutNs);
+       if(err == -ETIMEDOUT)
+           return (status_t)err;
     }
     if (!mStarted) {
         return OK;
@@ -232,9 +344,12 @@
     int64_t timeUs;
     CHECK(buffer->meta_data()->findInt64(kKeyTime, &timeUs));
     int64_t elapsedTimeUs = timeUs - mStartTimeUs;
-    if (elapsedTimeUs < kAutoRampStartUs) {
+#ifdef QCOM_HARDWARE
+    if ( mFormat == AUDIO_FORMAT_PCM_16_BIT ) {
+#endif
+        if (elapsedTimeUs < mAutoRampStartUs) {
         memset((uint8_t *) buffer->data(), 0, buffer->range_length());
-    } else if (elapsedTimeUs < kAutoRampStartUs + kAutoRampDurationUs) {
+        } else if (elapsedTimeUs < mAutoRampStartUs + kAutoRampDurationUs) {
         int32_t autoRampDurationFrames =
                     ((int64_t)kAutoRampDurationUs * mSampleRate + 500000LL) / 1000000LL; //Need type casting
 
@@ -244,10 +359,17 @@
         int32_t nFrames = mNumFramesReceived - autoRampStartFrames;
         rampVolume(nFrames, autoRampDurationFrames,
                 (uint8_t *) buffer->data(), buffer->range_length());
+        }
+#ifdef QCOM_HARDWARE
     }
+#endif
 
     // Track the max recording signal amplitude.
+#ifdef QCOM_HARDWARE
+    if (mTrackMaxAmplitude && ( mFormat == AUDIO_FORMAT_PCM_16_BIT)) {
+#else
     if (mTrackMaxAmplitude) {
+#endif
         trackMaxAmplitude(
             (int16_t *) buffer->data(), buffer->range_length() >> 1);
     }
@@ -304,6 +426,9 @@
     }
 
     CHECK_EQ(numLostBytes & 1, 0u);
+#ifdef QCOM_HARDWARE
+    if ( mFormat == AUDIO_FORMAT_PCM_16_BIT )
+#endif
     CHECK_EQ(audioBuffer.size & 1, 0u);
     if (numLostBytes > 0) {
         // Loss of audio frames should happen rarely; thus the LOGW should
@@ -342,19 +467,45 @@
 void AudioSource::queueInputBuffer_l(MediaBuffer *buffer, int64_t timeUs) {
     const size_t bufferSize = buffer->range_length();
     const size_t frameSize = mRecord->frameSize();
+#ifdef QCOM_HARDWARE
+    int64_t timestampUs = mPrevSampleTimeUs;
+    int64_t recordDurationUs = 0;
+    if ( mFormat == AUDIO_FORMAT_PCM_16_BIT && mSampleRate){
+        recordDurationUs = ((1000000LL * (bufferSize / (2 * mRecord->channelCount()))) +
+                        (mSampleRate >> 1)) / mSampleRate;
+    } else {
+       recordDurationUs = bufferDurationUs(bufferSize);
+    }
+    timestampUs += recordDurationUs;
+#else
     const int64_t timestampUs =
                 mPrevSampleTimeUs +
                     ((1000000LL * (bufferSize / frameSize)) +
                         (mSampleRate >> 1)) / mSampleRate;
+#endif
 
     if (mNumFramesReceived == 0) {
         buffer->meta_data()->setInt64(kKeyAnchorTime, mStartTimeUs);
     }
 
     buffer->meta_data()->setInt64(kKeyTime, mPrevSampleTimeUs);
+#ifdef QCOM_HARDWARE
+    if (mFormat == AUDIO_FORMAT_PCM_16_BIT) {
+#endif
     buffer->meta_data()->setInt64(kKeyDriftTime, timeUs - mInitialReadTimeUs);
+#ifdef QCOM_HARDWARE
+    } else {
+        int64_t wallClockTimeUs = timeUs - mInitialReadTimeUs;
+        int64_t mediaTimeUs = mStartTimeUs + mPrevSampleTimeUs;
+        buffer->meta_data()->setInt64(kKeyDriftTime, mediaTimeUs - wallClockTimeUs);
+    }
+#endif
     mPrevSampleTimeUs = timestampUs;
+#ifdef QCOM_HARDWARE
+    mNumFramesReceived += buffer->range_length() / sizeof(int16_t);
+#else
     mNumFramesReceived += bufferSize / frameSize;
+#endif
     mBuffersReceived.push_back(buffer);
     mFrameAvailableCondition.signal();
 }
@@ -382,4 +533,24 @@
     return value;
 }
 
+#ifdef QCOM_HARDWARE
+int64_t AudioSource::bufferDurationUs( ssize_t n ) {
+    int64_t dataDurationMs = 0;
+    if (mFormat == AUDIO_FORMAT_AMR_NB) {
+        dataDurationMs = (n/AMR_FRAMESIZE) * 20; //ms
+    }
+    else if (mFormat == AUDIO_FORMAT_EVRC) {
+       dataDurationMs = (n/EVRC_FRAMESIZE) * 20; //ms
+    }
+    else if (mFormat == AUDIO_FORMAT_QCELP) {
+        dataDurationMs = (n/QCELP_FRAMESIZE) * 20; //ms
+    }
+    else if (mFormat == AUDIO_FORMAT_AMR_WB) {
+        dataDurationMs = (n/AMR_WB_FRAMESIZE) * 20; //ms
+    }
+    else
+        CHECK(0);
+    return dataDurationMs*1000LL;
+}
+#endif
 }  // namespace android
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp
index 130207d..e9223f0 100644
--- a/media/libstagefright/AwesomePlayer.cpp
+++ b/media/libstagefright/AwesomePlayer.cpp
@@ -1,5 +1,8 @@
 /*
+ * Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
+ * Not a Contribution.
  * Copyright (C) 2009 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.
@@ -39,6 +42,16 @@
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/timedtext/TimedTextDriver.h>
 #include <media/stagefright/AudioPlayer.h>
+#ifdef QCOM_ENHANCED_AUDIO
+#ifdef LEGACY_LPA
+#include <media/stagefright/LPAPlayerLegacy.h>
+#else
+#include <media/stagefright/LPAPlayer.h>
+#endif
+#ifdef USE_TUNNEL_MODE
+#include <media/stagefright/TunnelPlayer.h>
+#endif
+#endif
 #include <media/stagefright/DataSource.h>
 #include <media/stagefright/FileSource.h>
 #include <media/stagefright/MediaBuffer.h>
@@ -47,6 +60,7 @@
 #include <media/stagefright/MediaSource.h>
 #include <media/stagefright/MetaData.h>
 #include <media/stagefright/OMXCodec.h>
+#include "include/ExtendedUtils.h"
 #include <media/stagefright/Utils.h>
 
 #include <gui/IGraphicBufferProducer.h>
@@ -58,6 +72,10 @@
 
 #define USE_SURFACE_ALLOC 1
 #define FRAME_DROP_FREQ 0
+#ifdef QCOM_HARDWARE
+#define LPA_MIN_DURATION_USEC_ALLOWED 30000000
+#define LPA_MIN_DURATION_USEC_DEFAULT 60000000
+#endif
 
 namespace android {
 
@@ -65,6 +83,12 @@
 static int64_t kHighWaterMarkUs = 5000000ll;  // 5secs
 static const size_t kLowWaterMarkBytes = 40000;
 static const size_t kHighWaterMarkBytes = 200000;
+static const int64_t kInitFrameDurationUs = 16000;
+static const int64_t kScheduleLagGapUs = 1000;
+static const int64_t kDefaultEventDelayUs = 10000;
+#ifdef QCOM_ENHANCED_AUDIO
+int AwesomePlayer::mTunnelAliveAP = 0;
+#endif
 
 // maximum time in paused state when offloading audio decompression. When elapsed, the AudioPlayer
 // is destroyed to allow the audio DSP to power down.
@@ -202,6 +226,7 @@
       mVideoBuffer(NULL),
       mDecryptHandle(NULL),
       mLastVideoTimeUs(-1),
+      mFrameDurationUs(kInitFrameDurationUs),
       mTextDriver(NULL),
       mOffloadAudio(false),
       mAudioTearDown(false) {
@@ -228,6 +253,10 @@
     mAudioTearDownEventPending = false;
 
     reset();
+#ifdef QCOM_ENHANCED_AUDIO
+    mIsTunnelAudio = false;
+#endif
+    mLateAVSyncMargin = ExtendedUtils::ShellProp::getMaxAVSyncLateMargin();
 }
 
 AwesomePlayer::~AwesomePlayer() {
@@ -237,9 +266,59 @@
 
     reset();
 
+#ifdef QCOM_ENHANCED_AUDIO
+    // Disable Tunnel Mode Audio
+    if (mIsTunnelAudio) {
+        if (mTunnelAliveAP > 0) {
+            mTunnelAliveAP--;
+            ALOGV("mTunnelAliveAP = %d", mTunnelAliveAP);
+        }
+    }
+    mIsTunnelAudio = false;
+#endif
     mClient.disconnect();
 }
 
+void AwesomePlayer::printStats() {
+    char value[PROPERTY_VALUE_MAX];
+    property_get("persist.debug.sf.statistics", value, "0");
+    if (atoi(value) && mVideoSource != NULL) {
+        ALOGE("===========================\n"
+            "   videoDimensions(%d x %d)\n"
+            "   Total Video Frames Decoded(%lld)\n"
+            "   Total Video Frames Rendered(%lld)\n"
+            "   Total Playback Duration(%lld ms)\n"
+            "   numVideoFramesDropped(%lld)\n"
+            "   Average Frames Per Second(%.4f)\n"
+            "   Last Seek To Time(%lld ms)\n"
+            "   Last Paused Time(%lld ms)\n"
+            "   First Frame Latency (%lld ms)\n"
+            "   Number of times AV Sync Lost(%u)\n"
+            "   Max Video Ahead Time Delta(%u)\n"
+            "   Max Video Behind Time Delta(%u)\n"
+            "   Max Time Sync Loss(%u)\n"
+            "   EOS(%d)\n"
+            "   PLAYING(%d)\n"
+            "===========================\n\n",
+            mStats.mVideoWidth,
+            mStats.mVideoHeight,
+            mStats.mNumVideoFramesDecoded,
+            mStats.mTotalFrames,
+            mStats.mTotalTimeUs/1000,
+            mStats.mNumVideoFramesDropped,
+            mStats.mTotalTimeUs > 0 ? ((double)(mStats.mTotalFrames)*1E6)/((double)mStats.mTotalTimeUs) : 0,
+            mStats.mLastSeekToTimeMs,
+            mStats.mLastPausedTimeMs,
+            mStats.mFirstFrameLatencyUs/1000,
+            mStats.mNumTimesSyncLoss,
+            -mStats.mMaxEarlyDelta/1000,
+            mStats.mMaxLateDelta/1000,
+            mStats.mMaxTimeSyncLoss/1000,
+            (mFlags & VIDEO_AT_EOS) > 0,
+            (mFlags & PLAYING) > 0);
+    }
+}
+
 void AwesomePlayer::cancelPlayerEvents(bool keepNotifications) {
     mQueue.cancelEvent(mVideoEvent->eventID());
     mVideoEventPending = false;
@@ -316,12 +395,28 @@
     return OK;
 }
 
+void AwesomePlayer::printFileName(int fd) {
+
+    char symName[40] = {0};
+    char fileName[256] = {0};
+
+    snprintf(symName, sizeof(symName), "/proc/%d/fd/%d", getpid(), fd);
+
+    if (readlink( symName, fileName, (sizeof(fileName) - 1)) != -1 ) {
+        ALOGD("printFileName fd(%d) -> %s", fd, fileName);
+    }
+}
+
 status_t AwesomePlayer::setDataSource(
         int fd, int64_t offset, int64_t length) {
     Mutex::Autolock autoLock(mLock);
 
+    ALOGD("Before reset_l");
     reset_l();
 
+    if(fd)
+        printFileName(fd);
+
     sp<DataSource> dataSource = new FileSource(fd, offset, length);
 
     status_t err = dataSource->initCheck();
@@ -567,6 +662,8 @@
 
     mVideoRenderer.clear();
 
+    modifyFlags(PLAYING, CLEAR);
+    printStats();
     if (mVideoSource != NULL) {
         shutdownVideoDecoder_l();
     }
@@ -588,7 +685,7 @@
 
     mBitrate = -1;
     mLastVideoTimeUs = -1;
-
+    mFrameDurationUs = kInitFrameDurationUs;
     {
         Mutex::Autolock autoLock(mStatsLock);
         mStats.mFd = -1;
@@ -602,6 +699,21 @@
         mStats.mVideoHeight = -1;
         mStats.mFlags = 0;
         mStats.mTracks.clear();
+        mStats.mConsecutiveFramesDropped = 0;
+        mStats.mCatchupTimeStart = 0;
+        mStats.mNumTimesSyncLoss = 0;
+        mStats.mMaxEarlyDelta = 0;
+        mStats.mMaxLateDelta = 0;
+        mStats.mMaxTimeSyncLoss = 0;
+        mStats.mTotalFrames = 0;
+        mStats.mLastFrameUs = 0;
+        mStats.mTotalTimeUs = 0;
+        mStats.mVeryFirstFrame = true;
+        mStats.mFirstFrameLatencyUs = 0;
+        mStats.mLastPausedTimeMs = 0;
+        mStats.mLastSeekToTimeMs = 0;
+        mStats.mResumeDelayStartUs = -1;
+        mStats.mSeekDelayStartUs = -1;
     }
 
     mWatchForAudioSeekComplete = false;
@@ -929,9 +1041,14 @@
 
             // We don't want to post an error notification at this point,
             // the error returned from MediaPlayer::start() will suffice.
-
-            status_t err = startAudioPlayer_l(
-                    false /* sendErrorNotification */);
+            bool sendErrorNotification = false;
+#ifdef QCOM_ENHANCED_AUDIO
+            if(mIsTunnelAudio) {
+                // For tunnel Audio error has to be posted to the client
+                sendErrorNotification = true;
+            }
+#endif
+            status_t err = startAudioPlayer_l(sendErrorNotification);
 
             if ((err != OK) && mOffloadAudio) {
                 ALOGI("play_l() cannot create offload output, fallback to sw decode");
@@ -983,6 +1100,15 @@
         mTimeSource = &mSystemTimeSource;
     }
 
+    {
+        Mutex::Autolock autoLock(mStatsLock);
+        if (mStats.mVeryFirstFrame) {
+            mStats.mFirstFrameLatencyStartUs = getTimeOfDayUs();
+        } else {
+            mStats.mResumeDelayStartUs = getTimeOfDayUs();
+        }
+    }
+
     if (mVideoSource != NULL) {
         // Kick off video playback
         postVideoEvent_l();
@@ -1020,7 +1146,13 @@
     uint32_t flags = 0;
     int64_t cachedDurationUs;
     bool eos;
-
+#ifdef QCOM_ENHANCED_AUDIO
+    sp<MetaData> format = mAudioTrack->getFormat();
+    const char *mime;
+    bool success = format->findCString(kKeyMIMEType, &mime);
+    int tunnelObjectsAlive = 0;
+    CHECK(success);
+#endif
     if (mOffloadAudio) {
         flags |= AudioPlayer::USE_OFFLOAD;
     } else if (mVideoSource == NULL
@@ -1035,8 +1167,89 @@
     if (mVideoSource != NULL) {
         flags |= AudioPlayer::HAS_VIDEO;
     }
+#ifdef QCOM_ENHANCED_AUDIO
+#ifdef USE_TUNNEL_MODE
+    // Create tunnel player if tunnel mode is enabled
+    ALOGW("Trying to create tunnel player mIsTunnelAudio %d, \
+            LPAPlayer::mObjectsAlive %d, \
+            TunnelPlayer::mTunnelObjectsAlive = %d,\
+            (mAudioPlayer == NULL) %d",
+            mIsTunnelAudio, TunnelPlayer::mTunnelObjectsAlive,
+            LPAPlayer::mObjectsAlive,(mAudioPlayer == NULL));
 
+    if(mIsTunnelAudio && (mAudioPlayer == NULL) &&
+            (LPAPlayer::mObjectsAlive == 0) &&
+            (TunnelPlayer::mTunnelObjectsAlive < TunnelPlayer::getTunnelObjectsAliveMax())) {
+        ALOGD("Tunnel player created for  mime %s duration %lld\n",\
+            mime, mDurationUs);
+        bool initCheck =  false;
+        if(mVideoSource != NULL) {
+            // The parameter true is to inform tunnel player that
+            // clip is audio video
+            ALOGD("Tunnel for video");
+            mAudioPlayer = new TunnelPlayer(mAudioSink, initCheck,
+                    this, true);
+        }
+        else {
+            ALOGD("Tunnel for audio");
+            mAudioPlayer = new TunnelPlayer(mAudioSink, initCheck,
+                    this);
+        }
+        if(!initCheck) {
+            ALOGE("deleting Tunnel Player - initCheck failed");
+            delete mAudioPlayer;
+            mAudioPlayer = NULL;
+        }
+    }
+    tunnelObjectsAlive = (TunnelPlayer::mTunnelObjectsAlive);
+#endif
+    int32_t nchannels = 0;
+    if(mAudioTrack != NULL) {
+        sp<MetaData> format = mAudioTrack->getFormat();
+        if(format != NULL) {
+            format->findInt32( kKeyChannelCount, &nchannels );
+            ALOGV("nchannels %d;LPA will be skipped if nchannels is > 2 or nchannels == 0",nchannels);
+        }
+    }
+    char lpaDecode[PROPERTY_VALUE_MAX];
+    uint32_t minDurationForLPA = LPA_MIN_DURATION_USEC_DEFAULT;
+    char minUserDefDuration[PROPERTY_VALUE_MAX];
+    property_get("lpa.decode",lpaDecode,"0");
+    property_get("lpa.min_duration",minUserDefDuration,"LPA_MIN_DURATION_USEC_DEFAULT");
+    minDurationForLPA = atoi(minUserDefDuration);
+    if(minDurationForLPA < LPA_MIN_DURATION_USEC_ALLOWED) {
+        if(mAudioPlayer == NULL) {
+            ALOGE("LPAPlayer::Clip duration setting of less than 30sec not supported, defaulting to 60sec");
+            minDurationForLPA = LPA_MIN_DURATION_USEC_DEFAULT;
+        }
+    }
+    if((strcmp("true",lpaDecode) == 0) && (mAudioPlayer == NULL) &&
+#ifdef USE_ENHANCED_AUDIO
+       (tunnelObjectsAlive < TunnelPlayer::getTunnelObjectsAliveMax()) &&
+#endif
+       (nchannels && (nchannels <= 2)))
+    {
+        ALOGV("LPAPlayer::getObjectsAlive() %d",LPAPlayer::mObjectsAlive);
+        if ( mDurationUs > minDurationForLPA
+             && (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_MPEG) || !strcasecmp(mime,MEDIA_MIMETYPE_AUDIO_AAC))
+             && LPAPlayer::mObjectsAlive == 0 && mVideoSource == NULL) {
+            ALOGD("LPAPlayer created, LPA MODE detected mime %s duration %lld", mime, mDurationUs);
+            bool initCheck =  false;
+            mAudioPlayer = new LPAPlayer(mAudioSink, initCheck, this);
+            if(!initCheck) {
+                 ALOGE("deleting Tunnel Player - initCheck failed");
+                 delete mAudioPlayer;
+                 mAudioPlayer = NULL;
+            }
+        }
+    }
+    if(mAudioPlayer == NULL) {
+        ALOGV("AudioPlayer created, Non-LPA mode mime %s duration %lld\n", mime, mDurationUs);
+        mAudioPlayer = new AudioPlayer(mAudioSink, flags, this);
+    }
+#else
     mAudioPlayer = new AudioPlayer(mAudioSink, flags, this);
+#endif
     mAudioPlayer->setSource(mAudioSource);
 
     mTimeSource = mAudioPlayer;
@@ -1077,6 +1290,7 @@
                 true /* sourceAlreadyStarted */);
 
         if (err != OK) {
+            ALOGE("AudioPlayer start error");
             if (sendErrorNotification) {
                 notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
             }
@@ -1267,6 +1481,12 @@
                 Playback::PAUSE, 0);
     }
 
+    if(!(mFlags & VIDEO_AT_EOS)){
+        Mutex::Autolock autoLock(mStatsLock);
+        mStats.mLastPausedTimeMs = mVideoTimeUs/1000;
+        printStats();
+    }
+
     uint32_t params = IMediaPlayerService::kBatteryDataTrackDecoder;
     if ((mAudioSource != NULL) && (mAudioSource != mAudioTrack)) {
         params |= IMediaPlayerService::kBatteryDataTrackAudio;
@@ -1402,7 +1622,8 @@
 status_t AwesomePlayer::seekTo(int64_t timeUs) {
     ATRACE_CALL();
 
-    if (mExtractorFlags & MediaExtractor::CAN_SEEK) {
+    if (((timeUs == 0) && (mExtractorFlags & MediaExtractor::CAN_SEEK_TO_ZERO)) ||
+        (mExtractorFlags & MediaExtractor::CAN_SEEK)) {
         Mutex::Autolock autoLock(mLock);
         return seekTo_l(timeUs);
     }
@@ -1425,6 +1646,11 @@
     }
 
     mSeeking = SEEK;
+
+    {
+        Mutex::Autolock autoLock(mStatsLock);
+        mStats.mSeekDelayStartUs = getTimeOfDayUs();
+    }
     mSeekNotificationSent = false;
     mSeekTimeUs = timeUs;
     modifyFlags((AT_EOS | AUDIO_AT_EOS | VIDEO_AT_EOS), CLEAR);
@@ -1507,6 +1733,119 @@
     mOffloadAudio = canOffloadStream(meta, (mVideoSource != NULL),
                                      isStreamingHTTP(), streamType);
 
+#ifdef QCOM_ENHANCED_AUDIO
+    int32_t nchannels = 0;
+    int32_t isADTS = 0;
+    meta->findInt32( kKeyChannelCount, &nchannels );
+    meta->findInt32(kKeyIsADTS, &isADTS);
+    if (isADTS == 1) {
+        ALOGV("Widevine content\n");
+    }
+
+    ALOGV("nchannels %d;LPA will be skipped if nchannels is > 2 or nchannels == 0",
+           nchannels);
+
+#ifdef USE_TUNNEL_MODE
+    char tunnelDecode[PROPERTY_VALUE_MAX];
+    property_get("tunnel.decode",tunnelDecode,"0");
+    // Enable tunnel mode for mp3 and aac and if the clip is not aac adif
+    // and if no other tunnel mode instances aare running.
+    ALOGD("Tunnel Mime Type: %s, object alive = %d, mTunnelAliveAP = %d",\
+            mime, (TunnelPlayer::mTunnelObjectsAlive), mTunnelAliveAP);
+
+    bool sys_prop_enabled = !strcmp("true",tunnelDecode) || atoi(tunnelDecode);
+    ALOGD("maxPossible tunnels = %d", TunnelPlayer::getTunnelObjectsAliveMax());
+    //widevine will fallback to software decoder
+    if (sys_prop_enabled && (TunnelPlayer::mTunnelObjectsAlive < TunnelPlayer::getTunnelObjectsAliveMax()) &&
+       (mTunnelAliveAP < TunnelPlayer::getTunnelObjectsAliveMax()) && (isADTS == 0) &&
+        mAudioSink->realtime() &&
+        inSupportedTunnelFormats(mime)) {
+
+        if (mVideoSource != NULL) {
+           char tunnelAVDecode[PROPERTY_VALUE_MAX];
+           property_get("tunnel.audiovideo.decode",tunnelAVDecode,"0");
+           sys_prop_enabled = !strncmp("true", tunnelAVDecode, 4) || atoi(tunnelAVDecode);
+           if (sys_prop_enabled) {
+               ALOGD("Enable Tunnel Mode for A-V playback");
+               mIsTunnelAudio = true;
+           }
+        }
+        else {
+            ALOGI("Tunnel Mode Audio Enabled");
+            mIsTunnelAudio = true;
+        }
+#ifdef NO_TUNNEL_MODE_FOR_MULTICHANNEL
+        if (nchannels > 2 || nchannels <= 0) {
+            ALOGD("Use tunnel mode only for mono and stereo channels");
+            mIsTunnelAudio = false;
+        }
+#endif
+    }
+    else
+       ALOGD("Normal Audio Playback");
+#endif
+
+    checkTunnelExceptions();
+
+    if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW) ||
+             (mIsTunnelAudio
+#ifdef USE_TUNNEL_MODE
+             && (mTunnelAliveAP < TunnelPlayer::getTunnelObjectsAliveMax())
+#endif
+    )) {
+        ALOGD("Set Audio Track as Audio Source");
+        if(mIsTunnelAudio) {
+            mTunnelAliveAP++;
+        }
+        mAudioSource = mAudioTrack;
+    } else {
+        // For LPA Playback use the decoder without OMX layer
+        char *matchComponentName = NULL;
+        int64_t durationUs;
+        uint32_t flags = 0;
+        char lpaDecode[128];
+        uint32_t minDurationForLPA = LPA_MIN_DURATION_USEC_DEFAULT;
+        char minUserDefDuration[PROPERTY_VALUE_MAX];
+        property_get("lpa.decode",lpaDecode,"0");
+        property_get("lpa.min_duration",minUserDefDuration,"LPA_MIN_DURATION_USEC_DEFAULT");
+        minDurationForLPA = atoi(minUserDefDuration);
+        if(minDurationForLPA < LPA_MIN_DURATION_USEC_ALLOWED) {
+            ALOGE("LPAPlayer::Clip duration setting of less than 30sec not supported, defaulting to 60sec");
+            minDurationForLPA = LPA_MIN_DURATION_USEC_DEFAULT;
+        }
+        if (mAudioTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) {
+            Mutex::Autolock autoLock(mMiscStateLock);
+            if (mDurationUs < 0 || durationUs > mDurationUs) {
+                mDurationUs = durationUs;
+            }
+        }
+        if ( mDurationUs > minDurationForLPA
+             && (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_MPEG) || !strcasecmp(mime,MEDIA_MIMETYPE_AUDIO_AAC))
+             && LPAPlayer::mObjectsAlive == 0 && mVideoSource == NULL && (strcmp("true",lpaDecode) == 0)
+             && (nchannels && (nchannels <= 2)) ) {
+            char nonOMXDecoder[128];
+            if(!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_MPEG)) {
+                ALOGD("matchComponentName is set to MP3Decoder %lld, mime %s",mDurationUs,mime);
+                property_get("use.non-omx.mp3.decoder",nonOMXDecoder,"0");
+                if((strcmp("true",nonOMXDecoder) == 0)) {
+                    matchComponentName = (char *) "MP3Decoder";
+                }
+            } else if((!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC))) {
+                ALOGD("matchComponentName is set to AACDecoder %lld, mime %s",mDurationUs,mime);
+                property_get("use.non-omx.aac.decoder",nonOMXDecoder,"0");
+                if((strcmp("true",nonOMXDecoder) == 0)) {
+                    matchComponentName = (char *) "AACDecoder";
+                } else {
+                    matchComponentName = (char *) "OMX.google.aac.decoder";
+                }
+            }
+            flags |= OMXCodec::kSoftwareCodecsOnly;
+        }
+        mAudioSource = OMXCodec::Create(
+                mClient.interface(), mAudioTrack->getFormat(),
+                false, // createEncoder
+                mAudioTrack, matchComponentName, flags,NULL);
+#else
     if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW)) {
         ALOGV("createAudioPlayer: bypass OMX (raw)");
         mAudioSource = mAudioTrack;
@@ -1517,12 +1856,15 @@
                 mClient.interface(), mAudioTrack->getFormat(),
                 false, // createEncoder
                 mAudioTrack);
+#endif
 
         if (mOffloadAudio) {
             ALOGV("createAudioPlayer: bypass OMX (offload)");
             mAudioSource = mAudioTrack;
+#ifndef QCOM_ENHANCED_AUDIO
         } else {
             mAudioSource = mOmxSource;
+#endif
         }
     }
 
@@ -1718,10 +2060,18 @@
         mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
                 Playback::START, videoTimeUs / 1000);
     }
+
+    {
+        Mutex::Autolock autoLock(mStatsLock);
+        mStats.mLastSeekToTimeMs = mSeekTimeUs/1000;
+        printStats();
+    }
 }
 
 void AwesomePlayer::onVideoEvent() {
     ATRACE_CALL();
+    int64_t eventStartTimeUs = mSystemTimeSource.getRealTimeUs();
+    int64_t earlyGapUs = kScheduleLagGapUs; // gap for in case of event scheduling lag
     Mutex::Autolock autoLock(mLock);
     if (!mVideoEventPending) {
         // The event has been cancelled in reset_l() but had already
@@ -1730,6 +2080,14 @@
     }
     mVideoEventPending = false;
 
+    {
+        Mutex::Autolock autoLock(mStatsLock);
+        if(!mStats.mVeryFirstFrame && mSeeking == NO_SEEK){
+            mStats.mTotalTimeUs += getTimeOfDayUs() - mStats.mLastFrameUs;
+        }
+        mStats.mLastFrameUs = getTimeOfDayUs();
+    }
+
     if (mSeeking != NO_SEEK) {
         if (mVideoBuffer) {
             mVideoBuffer->release();
@@ -1823,7 +2181,11 @@
 
     int64_t timeUs;
     CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &timeUs));
-
+    if ((mLastVideoTimeUs != timeUs)
+          && (mLastVideoTimeUs > 0)
+          && (mSeeking == NO_SEEK)) {
+        mFrameDurationUs = timeUs - mLastVideoTimeUs;
+    }
     mLastVideoTimeUs = timeUs;
 
     if (mSeeking == SEEK_VIDEO_ONLY) {
@@ -1863,18 +2225,27 @@
         modifyFlags(FIRST_FRAME, CLEAR);
         mSinceLastDropped = 0;
         mTimeSourceDeltaUs = ts->getRealTimeUs() - timeUs;
+
+        {
+            Mutex::Autolock autoLock(mStatsLock);
+            if(mStats.mVeryFirstFrame){
+                logFirstFrame();
+                printStats();
+                mStats.mLastFrameUs = getTimeOfDayUs();
+            }
+        }
     }
 
-    int64_t realTimeUs, mediaTimeUs;
+    int64_t realTimeUs, mediaTimeUs, nowUs = 0, latenessUs = 0;
     if (!(mFlags & AUDIO_AT_EOS) && mAudioPlayer != NULL
         && mAudioPlayer->getMediaTimeMapping(&realTimeUs, &mediaTimeUs)) {
         mTimeSourceDeltaUs = realTimeUs - mediaTimeUs;
     }
 
     if (wasSeeking == SEEK_VIDEO_ONLY) {
-        int64_t nowUs = ts->getRealTimeUs() - mTimeSourceDeltaUs;
+        nowUs = ts->getRealTimeUs() - mTimeSourceDeltaUs;
 
-        int64_t latenessUs = nowUs - timeUs;
+        latenessUs = nowUs - timeUs;
 
         ATRACE_INT("Video Lateness (ms)", latenessUs / 1E3);
 
@@ -1886,9 +2257,9 @@
     if (wasSeeking == NO_SEEK) {
         // Let's display the first frame after seeking right away.
 
-        int64_t nowUs = ts->getRealTimeUs() - mTimeSourceDeltaUs;
+        nowUs = ts->getRealTimeUs() - mTimeSourceDeltaUs;
 
-        int64_t latenessUs = nowUs - timeUs;
+        latenessUs = nowUs - timeUs;
 
         ATRACE_INT("Video Lateness (ms)", latenessUs / 1E3);
 
@@ -1916,7 +2287,7 @@
             }
         }
 
-        if (latenessUs > 40000) {
+        if (latenessUs > mLateAVSyncMargin) {
             // We're more than 40ms late.
             ALOGV("we're late by %lld us (%.2f secs)",
                  latenessUs, latenessUs / 1E6);
@@ -1935,6 +2306,11 @@
                 {
                     Mutex::Autolock autoLock(mStatsLock);
                     ++mStats.mNumVideoFramesDropped;
+                    mStats.mConsecutiveFramesDropped++;
+                    if (mStats.mConsecutiveFramesDropped == 1){
+                        mStats.mCatchupTimeStart = mTimeSource->getRealTimeUs();
+                    }
+                    if(!(mFlags & AT_EOS)) logLate(timeUs,nowUs,latenessUs);
                 }
 
                 postVideoEvent_l(0);
@@ -1944,6 +2320,11 @@
 
         if (latenessUs < -10000) {
             // We're more than 10ms early.
+            logOnTime(timeUs,nowUs,latenessUs);
+            {
+                Mutex::Autolock autoLock(mStatsLock);
+                mStats.mConsecutiveFramesDropped = 0;
+            }
             postVideoEvent_l(10000);
             return;
         }
@@ -1967,6 +2348,26 @@
         if (mFlags & PLAYING) {
             notifyIfMediaStarted_l();
         }
+        {
+            Mutex::Autolock autoLock(mStatsLock);
+            logOnTime(timeUs,nowUs,latenessUs);
+            mStats.mTotalFrames++;
+            mStats.mConsecutiveFramesDropped = 0;
+            char value[PROPERTY_VALUE_MAX];
+            property_get("persist.debug.sf.statistics", value, "0");
+            if (atoi(value) && mVideoSource != NULL) {
+                if (mStats.mResumeDelayStartUs > 0) {
+                    printStats();
+                    ALOGE("Resume Latency = %lld us", getTimeOfDayUs() - mStats.mResumeDelayStartUs);
+                    mStats.mResumeDelayStartUs = -1;
+                }
+                if (mStats.mSeekDelayStartUs > 0) {
+                    printStats();
+                    ALOGE("Seek Latency = %lld us", getTimeOfDayUs() - mStats.mSeekDelayStartUs);
+                    mStats.mSeekDelayStartUs = -1;
+                }
+            }
+        }
     }
 
     mVideoBuffer->release();
@@ -2058,6 +2459,18 @@
         return;
     }
     mAudioStatusEventPending = true;
+
+#ifdef EXYNOS4_ENHANCEMENTS
+    /*
+     * Do not honor delay when audio reached EOS
+     * in order to change immediately time source from AudioPlayer to SystemTime
+     */
+    status_t finalStatus;
+    if (mWatchForAudioEOS && mAudioPlayer->reachedEOS(&finalStatus)) {
+        delayUs = 0;
+    }
+#endif
+
     // Do not honor delay when looping in order to limit audio gap
     if (mFlags & (LOOPING | AUTO_LOOPING)) {
         delayUs = 0;
@@ -2834,13 +3247,33 @@
 
         if ((ssize_t)i == mStats.mVideoTrackIndex) {
             fprintf(out,
-                    "   videoDimensions(%d x %d), "
-                    "numVideoFramesDecoded(%lld), "
-                    "numVideoFramesDropped(%lld)\n",
+                    "   videoDimensions(%d x %d)\n"
+                    "   Total Video Frames Decoded(%lld)\n"
+                    "   Total Video Frames Rendered(%lld)\n"
+                    "   Total Playback Duration(%lld ms)\n"
+                    "   numVideoFramesDropped(%lld)\n"
+                    "   Average Frames Per Second(%.4f)\n"
+                    "   First Frame Latency (%lld ms)\n"
+                    "   Number of times AV Sync Lost(%u)\n"
+                    "   Max Video Ahead Time Delta(%u)\n"
+                    "   Max Video Behind Time Delta(%u)\n"
+                    "   Max Time Sync Loss(%u)\n"
+                    "   EOS(%d)\n"
+                    "   PLAYING(%d)\n",
                     mStats.mVideoWidth,
                     mStats.mVideoHeight,
                     mStats.mNumVideoFramesDecoded,
-                    mStats.mNumVideoFramesDropped);
+                    mStats.mTotalFrames,
+                    mStats.mTotalTimeUs/1000,
+                    mStats.mNumVideoFramesDropped,
+                    ((double)(mStats.mTotalFrames)*1E6)/((double)mStats.mTotalTimeUs),
+                    mStats.mFirstFrameLatencyUs/1000,
+                    mStats.mNumTimesSyncLoss,
+                    -mStats.mMaxEarlyDelta/1000,
+                    mStats.mMaxLateDelta/1000,
+                    mStats.mMaxTimeSyncLoss/1000,
+                    (mFlags & AT_EOS) > 0,
+                    (mFlags & PLAYING) > 0);
         }
     }
 
@@ -2922,4 +3355,139 @@
     beginPrepareAsync_l();
 }
 
+#ifdef QCOM_ENHANCED_AUDIO
+bool AwesomePlayer::inSupportedTunnelFormats(const char * mime) {
+    const char * tunnelFormats [ ] = {
+        MEDIA_MIMETYPE_AUDIO_MPEG,
+        MEDIA_MIMETYPE_AUDIO_AAC,
+#ifdef TUNNEL_MODE_SUPPORTS_AMRWB
+        MEDIA_MIMETYPE_AUDIO_AMR_WB,
+    #ifdef ENABLE_AV_ENHANCEMENTS
+        MEDIA_MIMETYPE_AUDIO_AMR_WB_PLUS
+    #endif
+#endif
+    };
+
+    if (!mime) {
+        return false;
+    }
+
+    size_t len = sizeof(tunnelFormats)/sizeof(const char *);
+    for (size_t i = 0; i < len; i++) {
+        const char * tf = tunnelFormats[i];
+        if (!strncasecmp(mime, tf, strlen(tf))) {
+            if (strlen(mime) == strlen(tf)) { //to prevent a substring match
+                ALOGD("Tunnel playback supported for %s", tf);
+                return true;
+            }
+        }
+    }
+
+    ALOGW("Tunnel playback unsupported for %s", mime);
+    return false;
+}
+
+void AwesomePlayer::checkTunnelExceptions()
+{
+    /* exception 1: No streaming */
+    if (isStreamingHTTP()) {
+        ALOGV("Streaming, force disable tunnel mode playback");
+        mIsTunnelAudio = false;
+        return;
+    }
+
+    CHECK(mAudioTrack != NULL);
+
+    /*
+     * exception 2: No AAC-LD content,
+     * hint given by setting kKeyTunnelException in the track meta
+     */
+    int32_t exception = 0;
+    if (mAudioTrack->getFormat()->findInt32(kKeyTunnelException, &exception) &&
+        exception) {
+        ALOGV("kKeyTunnelException set, disable tunnel mode");
+        mIsTunnelAudio = false;
+        return;
+    }
+
+    /* exception 3: use tunnel player only for AUDIO_STREAM_MUSIC */
+    if (mAudioSink->streamType() != AUDIO_STREAM_MUSIC ) {
+        ALOGV("Use tunnel player only for AUDIO_STREAM_MUSIC");
+        mIsTunnelAudio = false;
+        return;
+    }
+
+    /* below exceptions are only for av content */
+    if (mVideoTrack == NULL) return;
+
+    /* exception 3: No avi having video + mp3 */
+    if (mExtractor == NULL) return;
+
+    sp<MetaData> metaData = mExtractor->getMetaData();
+    const char * container;
+
+    /*only proceed for avi content.*/
+    if (!metaData->findCString(kKeyMIMEType, &container) ||
+        strcmp(container, MEDIA_MIMETYPE_CONTAINER_AVI)) {
+        return;
+    }
+
+    const char * mime;
+    metaData = mAudioTrack->getFormat();
+    /*disable for av content having mp3*/
+    if (metaData->findCString(kKeyMIMEType, &mime) &&
+        !strcmp(mime, MEDIA_MIMETYPE_AUDIO_MPEG)) {
+        ALOGV("Clip has AVI extractor and mp3 content, disable tunnel mode");
+        mIsTunnelAudio = false;
+        return;
+    }
+
+    return;
+}
+#endif
+
+inline void AwesomePlayer::logFirstFrame() {
+    mStats.mFirstFrameLatencyUs = getTimeOfDayUs()-mStats.mFirstFrameLatencyStartUs;
+    mStats.mVeryFirstFrame = false;
+}
+
+inline void AwesomePlayer::logCatchUp(int64_t ts, int64_t clock, int64_t delta)
+{
+    if (mStats.mConsecutiveFramesDropped > 0) {
+        mStats.mNumTimesSyncLoss++;
+        if (mStats.mMaxTimeSyncLoss < (clock - mStats.mCatchupTimeStart) && clock > 0 && ts > 0) {
+            mStats.mMaxTimeSyncLoss = clock - mStats.mCatchupTimeStart;
+        }
+    }
+}
+
+inline void AwesomePlayer::logLate(int64_t ts, int64_t clock, int64_t delta)
+{
+    if (mStats.mMaxLateDelta < delta && clock > 0 && ts > 0) {
+        mStats.mMaxLateDelta = delta;
+    }
+}
+
+inline void AwesomePlayer::logOnTime(int64_t ts, int64_t clock, int64_t delta)
+{
+    bool needLogLate = false;
+    logCatchUp(ts, clock, delta);
+    if (delta <= 0) {
+        if ((-delta) > (-mStats.mMaxEarlyDelta) && clock > 0 && ts > 0) {
+            mStats.mMaxEarlyDelta = delta;
+        }
+    }
+    else {
+        needLogLate = true;
+    }
+
+    if(needLogLate) logLate(ts, clock, delta);
+}
+
+inline int64_t AwesomePlayer::getTimeOfDayUs() {
+    struct timeval tv;
+    gettimeofday(&tv, NULL);
+
+    return (int64_t)tv.tv_sec * 1000000 + tv.tv_usec;
+}
 }  // namespace android
diff --git a/media/libstagefright/CameraSource.cpp b/media/libstagefright/CameraSource.cpp
index 3017fe7..d054a14 100644
--- a/media/libstagefright/CameraSource.cpp
+++ b/media/libstagefright/CameraSource.cpp
@@ -30,6 +30,13 @@
 #include <gui/Surface.h>
 #include <utils/String8.h>
 #include <cutils/properties.h>
+#ifdef QCOM_HARDWARE
+#include "include/ExtendedUtils.h"
+#endif
+
+#ifdef USE_TI_CUSTOM_DOMX
+#include <OMX_TI_IVCommon.h>
+#endif
 
 namespace android {
 
@@ -96,11 +103,20 @@
     }
 
     if (!strcmp(colorFormat, CameraParameters::PIXEL_FORMAT_YUV420SP)) {
+#ifdef USE_SAMSUNG_COLORFORMAT
+        static const int OMX_SEC_COLOR_FormatNV12LPhysicalAddress = 0x7F000002;
+        return OMX_SEC_COLOR_FormatNV12LPhysicalAddress;
+#else
         return OMX_COLOR_FormatYUV420SemiPlanar;
+#endif
     }
 
     if (!strcmp(colorFormat, CameraParameters::PIXEL_FORMAT_YUV422I)) {
+#if defined(TARGET_OMAP3) && defined(OMAP_ENHANCEMENT)
+        return OMX_COLOR_FormatCbYCrY;
+#else
         return OMX_COLOR_FormatYCbYCr;
+#endif
     }
 
     if (!strcmp(colorFormat, CameraParameters::PIXEL_FORMAT_RGB565)) {
@@ -340,11 +356,13 @@
         ALOGV("Supported frame rates: %s", supportedFrameRates);
         char buf[4];
         snprintf(buf, 4, "%d", frameRate);
+#ifndef HTC_3D_SUPPORT  // HTC uses invalid frame rates intentionally on the 3D camera
         if (strstr(supportedFrameRates, buf) == NULL) {
             ALOGE("Requested frame rate (%d) is not supported: %s",
                 frameRate, supportedFrameRates);
             return BAD_VALUE;
         }
+#endif
 
         // The frame rate is supported, set the camera to the requested value.
         params->setPreviewFrameRate(frameRate);
@@ -442,11 +460,13 @@
 
     // Check the actual video frame rate against the target/requested
     // video frame rate.
+#ifndef HTC_3D_SUPPORT  // HTC uses invalid frame rates intentionally on the 3D camera
     if (frameRate != -1 && (frameRateActual - frameRate) != 0) {
         ALOGE("Failed to set preview frame rate to %d fps. The actual "
                 "frame rate is %d", frameRate, frameRateActual);
         return UNKNOWN_ERROR;
     }
+#endif
 
     // Good now.
     mVideoFrameRate = frameRateActual;
@@ -563,6 +583,11 @@
     mMeta->setInt32(kKeyStride,      mVideoSize.width);
     mMeta->setInt32(kKeySliceHeight, mVideoSize.height);
     mMeta->setInt32(kKeyFrameRate,   mVideoFrameRate);
+
+#ifdef QCOM_HARDWARE
+    ExtendedUtils::HFR::setHFRIfEnabled(params, mMeta);
+#endif
+
     return OK;
 }
 
@@ -813,6 +838,10 @@
 void CameraSource::dataCallbackTimestamp(int64_t timestampUs,
         int32_t msgType, const sp<IMemory> &data) {
     ALOGV("dataCallbackTimestamp: timestamp %lld us", timestampUs);
+    if (!mStarted) {
+       ALOGD("Stop recording issued. Return here.");
+       return;
+    }
     Mutex::Autolock autoLock(mLock);
     if (!mStarted || (mNumFramesReceived == 0 && timestampUs < mStartTimeUs)) {
         ALOGV("Drop frame at %lld/%lld us", timestampUs, mStartTimeUs);
diff --git a/media/libstagefright/DataSource.cpp b/media/libstagefright/DataSource.cpp
old mode 100644
new mode 100755
index 97987e2..32dafb2
--- a/media/libstagefright/DataSource.cpp
+++ b/media/libstagefright/DataSource.cpp
@@ -32,6 +32,9 @@
 #include "include/OggExtractor.h"
 #include "include/WAVExtractor.h"
 #include "include/WVMExtractor.h"
+#ifdef QCOM_HARDWARE
+#include "include/ExtendedExtractor.h"
+#endif
 
 #include "matroska/MatroskaExtractor.h"
 
@@ -169,6 +172,9 @@
     RegisterSniffer_l(SniffAAC);
     RegisterSniffer_l(SniffMPEG2PS);
     RegisterSniffer_l(SniffWVM);
+#ifdef QCOM_HARDWARE
+    RegisterSniffer_l(ExtendedExtractor::Sniff);
+#endif
 
     char value[PROPERTY_VALUE_MAX];
     if (property_get("drm.service.enabled", value, NULL)
diff --git a/media/libstagefright/ExtendedCodec.cpp b/media/libstagefright/ExtendedCodec.cpp
new file mode 100644
index 0000000..8cde8bd
--- /dev/null
+++ b/media/libstagefright/ExtendedCodec.cpp
@@ -0,0 +1,1077 @@
+/*
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials provided
+ *      with the distribution.
+ *     * Neither the name of The Linux Foundation nor the names of its
+ *      contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "ExtendedCodec"
+#include <utils/Log.h>
+#include <cutils/properties.h>
+
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AMessage.h>
+#include <media/stagefright/foundation/ABuffer.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MediaCodecList.h>
+
+#include <media/stagefright/MetaData.h>
+#include <media/stagefright/ExtendedCodec.h>
+#include <media/stagefright/OMXCodec.h>
+
+#ifdef ENABLE_AV_ENHANCEMENTS
+
+#include <QCMetaData.h>
+#include <QCMediaDefs.h>
+#include <OMX_QCOMExtns.h>
+#include <OMX_Component.h>
+#include <QOMX_AudioExtensions.h>
+#include "include/ExtendedUtils.h"
+
+namespace android {
+enum MetaKeyType{
+    INT32, INT64, STRING, DATA, CSD
+};
+
+struct MetaKeyEntry{
+    int MetaKey;
+    const char* MsgKey;
+    MetaKeyType KeyType;
+};
+
+static const MetaKeyEntry MetaKeyTable[] {
+   {kKeyBitRate              , "bitrate"                , INT32},
+   {kKeyAacCodecSpecificData , "aac-codec-specific-data", CSD},
+   {kKeyRawCodecSpecificData , "raw-codec-specific-data", CSD},
+   {kKeyDivXVersion          , "divx-version"           , INT32},  // int32_t
+   {kKeyDivXDrm              , "divx-drm"               , DATA},  // void *
+   {kKeyWMAEncodeOpt         , "wma-encode-opt"         , INT32},  // int32_t
+   {kKeyWMABlockAlign        , "wma-block-align"        , INT32},  // int32_t
+   {kKeyWMAVersion           , "wma-version"            , INT32},  // int32_t
+   {kKeyWMAAdvEncOpt1        , "wma-adv-enc-opt1"       , INT32},  // int16_t
+   {kKeyWMAAdvEncOpt2        , "wma-adv-enc-opt2"       , INT32},  // int32_t
+   {kKeyWMAFormatTag         , "wma-format-tag"         , INT32},  // int32_t
+   {kKeyWMABitspersample     , "wma-bits-per-sample"    , INT32},  // int32_t
+   {kKeyWMAVirPktSize        , "wma-vir-pkt-size"       , INT32},  // int32_t
+   {kKeyWMAChannelMask       , "wma-channel-mask"       , INT32},  // int32_t
+
+   {kKeyFileFormat           , "file-format"            , STRING},  // cstring
+
+   {kkeyAacFormatAdif        , "aac-format-adif"        , INT32},  // bool (int32_t)
+   {kkeyAacFormatLtp         , "aac-format-ltp"         , INT32},
+
+   //DTS subtype
+   {kKeyDTSSubtype           , "dts-subtype"            , INT32},  //int32_t
+
+   //Extractor sets this
+   {kKeyUseArbitraryMode     , "use-arbitrary-mode"     , INT32},  //bool (int32_t)
+   {kKeySmoothStreaming      , "smooth-streaming"       , INT32},  //bool (int32_t)
+   {kKeyHFR                  , "hfr"                    , INT32},  // int32_t
+
+   {kKeySampleRate           , "sample-rate"            , INT32},
+   {kKeyChannelCount         , "channel-count"          , INT32},
+};
+
+const char* ExtendedCodec::getMsgKey(int key) {
+    static const size_t numMetaKeys =
+                     sizeof(MetaKeyTable) / sizeof(MetaKeyTable[0]);
+    size_t i;
+    for (i = 0; i < numMetaKeys; ++i) {
+        if (key == MetaKeyTable[i].MetaKey) {
+            return MetaKeyTable[i].MsgKey;
+        }
+    }
+    return "unknown";
+}
+
+status_t ExtendedCodec::convertMetaDataToMessage(
+        const sp<MetaData> &meta, sp<AMessage> *format) {
+    const char * str_val;
+    int32_t int32_val;
+    int64_t int64_val;
+    uint32_t data_type;
+    const void * data;
+    size_t size;
+    static const size_t numMetaKeys =
+                     sizeof(MetaKeyTable) / sizeof(MetaKeyTable[0]);
+    size_t i;
+    for (i = 0; i < numMetaKeys; ++i) {
+        if (MetaKeyTable[i].KeyType == INT32 &&
+            meta->findInt32(MetaKeyTable[i].MetaKey, &int32_val)) {
+            ALOGV("found metakey %s of type int32", MetaKeyTable[i].MsgKey);
+            format->get()->setInt32(MetaKeyTable[i].MsgKey, int32_val);
+        }
+        else if (MetaKeyTable[i].KeyType == INT64 &&
+                 meta->findInt64(MetaKeyTable[i].MetaKey, &int64_val)) {
+            ALOGV("found metakey %s of type int64", MetaKeyTable[i].MsgKey);
+            format->get()->setInt64(MetaKeyTable[i].MsgKey, int64_val);
+        }
+        else if (MetaKeyTable[i].KeyType == STRING &&
+                 meta->findCString(MetaKeyTable[i].MetaKey, &str_val)) {
+            ALOGV("found metakey %s of type string", MetaKeyTable[i].MsgKey);
+            format->get()->setString(MetaKeyTable[i].MsgKey, str_val);
+        }
+        else if ( (MetaKeyTable[i].KeyType == DATA ||
+                   MetaKeyTable[i].KeyType == CSD) &&
+                   meta->findData(MetaKeyTable[i].MetaKey, &data_type, &data, &size)) {
+            ALOGV("found metakey %s of type data", MetaKeyTable[i].MsgKey);
+            sp<ABuffer> buffer = new ABuffer(size);
+            memcpy(buffer->data(), data, size);
+            if (MetaKeyTable[i].KeyType == CSD) {
+                buffer->meta()->setInt32("csd", true);
+                buffer->meta()->setInt64("timeUs", 0);
+            }
+            format->get()->setBuffer(MetaKeyTable[i].MsgKey, buffer);
+        }
+    }
+    return OK;
+}
+
+uint32_t ExtendedCodec::getComponentQuirks(
+        const MediaCodecList *list, size_t index) {
+    uint32_t quirks = 0;
+
+    if (list->codecHasQuirk(
+                index, "requires-wma-pro-component")) {
+        quirks |= kRequiresWMAProComponent;
+    }
+    return quirks;
+}
+
+const char* ExtendedCodec::overrideComponentName(
+        uint32_t quirks, const sp<MetaData> &meta) {
+    const char* componentName = NULL;
+    if(quirks & kRequiresWMAProComponent)
+    {
+       int32_t version = 0;
+       if (meta->findInt32(kKeyWMAVersion, &version)) {
+           if(version==kTypeWMA) {
+              componentName = "OMX.qcom.audio.decoder.wma";
+           } else if(version==kTypeWMAPro) {
+              componentName = "OMX.qcom.audio.decoder.wma10Pro";
+           } else if(version==kTypeWMALossLess) {
+              componentName = "OMX.qcom.audio.decoder.wmaLossLess";
+           }
+       }
+    }
+    return componentName;
+}
+
+void ExtendedCodec::overrideComponentName(
+        uint32_t quirks, const sp<AMessage> &msg, AString* componentName) {
+    if(quirks & kRequiresWMAProComponent)
+    {
+       int32_t version = 0;
+       if (msg->findInt32(getMsgKey(kKeyWMAVersion), &version)) {
+           if(version==kTypeWMA) {
+              componentName->setTo("OMX.qcom.audio.decoder.wma");
+           } else if(version==kTypeWMAPro) {
+              componentName->setTo("OMX.qcom.audio.decoder.wma10Pro");
+           } else if(version==kTypeWMALossLess) {
+              componentName->setTo("OMX.qcom.audio.decoder.wmaLossLess");
+           }
+       }
+    }
+}
+
+template<class T>
+static void InitOMXParams(T *params) {
+    params->nSize = sizeof(T);
+    params->nVersion.s.nVersionMajor = 1;
+    params->nVersion.s.nVersionMinor = 0;
+    params->nVersion.s.nRevision = 0;
+    params->nVersion.s.nStep = 0;
+}
+
+status_t ExtendedCodec::setDIVXFormat(
+        const sp<AMessage> &msg, const char* mime, sp<IOMX> OMXhandle,
+        IOMX::node_id nodeID, int port_index) {
+    status_t err = OK;
+
+    if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_DIVX, mime) ||
+        !strcasecmp(MEDIA_MIMETYPE_VIDEO_DIVX4, mime) ||
+        !strcasecmp(MEDIA_MIMETYPE_VIDEO_DIVX311, mime)) {
+        ALOGV("Setting the QOMX_VIDEO_PARAM_DIVXTYPE params ");
+        QOMX_VIDEO_PARAM_DIVXTYPE paramDivX;
+        InitOMXParams(&paramDivX);
+        paramDivX.nPortIndex = port_index;
+        int32_t DivxVersion = 0;
+        CHECK(msg->findInt32(getMsgKey(kKeyDivXVersion),&DivxVersion));
+        ALOGV("Divx Version Type %d\n",DivxVersion);
+
+        if(DivxVersion == kTypeDivXVer_4) {
+            paramDivX.eFormat = QOMX_VIDEO_DIVXFormat4;
+        } else if(DivxVersion == kTypeDivXVer_5) {
+            paramDivX.eFormat = QOMX_VIDEO_DIVXFormat5;
+        } else if(DivxVersion == kTypeDivXVer_6) {
+            paramDivX.eFormat = QOMX_VIDEO_DIVXFormat6;
+        } else if(DivxVersion == kTypeDivXVer_3_11 ) {
+            paramDivX.eFormat = QOMX_VIDEO_DIVXFormat311;
+        } else {
+            paramDivX.eFormat = QOMX_VIDEO_DIVXFormatUnused;
+        }
+        paramDivX.eProfile = (QOMX_VIDEO_DIVXPROFILETYPE)0;    //Not used for now.
+
+        err =  OMXhandle->setParameter(nodeID,
+                         (OMX_INDEXTYPE)OMX_QcomIndexParamVideoDivx,
+                         &paramDivX, sizeof(paramDivX));
+    }
+
+    return err;
+}
+
+void ExtendedCodec::getRawCodecSpecificData(
+        const sp<MetaData> &meta, const void* &data, size_t &size) {
+    uint32_t type = 0;
+    size = 0;
+    if (meta->findData(kKeyRawCodecSpecificData, &type, &data, &size)) {
+        ALOGV("OMXCodec::configureCodec found kKeyRawCodecSpecificData of size %d\n", size);
+    }
+}
+
+sp<ABuffer> ExtendedCodec::getRawCodecSpecificData(
+        const sp<AMessage> &msg) {
+    sp<ABuffer> buffer;
+    if (msg->findBuffer(getMsgKey(kKeyRawCodecSpecificData), &buffer)) {
+        ALOGV("ACodec found kKeyRawCodecSpecificData of size %d\n", buffer->size());
+        return buffer;
+    }
+    return NULL;
+}
+
+void ExtendedCodec::getAacCodecSpecificData(
+        const sp<MetaData> &meta, const void* &data, size_t &size) {
+    uint32_t type = 0;
+    size = 0;
+    if (meta->findData(kKeyAacCodecSpecificData, &type, &data, &size)) {
+        ALOGV("OMXCodec::configureCodec found kKeyAacCodecSpecificData of size %d\n", size);
+    }
+}
+
+sp<ABuffer> ExtendedCodec::getAacCodecSpecificData(
+        const sp<AMessage> &msg) {
+    sp<ABuffer> buffer;
+    if (msg->findBuffer(getMsgKey(kKeyAacCodecSpecificData), &buffer)) {
+        ALOGV("ACodec found kKeyAacCodecSpecificData of size %d\n", buffer->size());
+        return buffer;
+    }
+    return NULL;
+}
+
+status_t ExtendedCodec::setAudioFormat(
+        const sp<MetaData> &meta, const char* mime, sp<IOMX> OMXhandle,
+        IOMX::node_id nodeID, bool isEncoder ) {
+    sp<AMessage> msg = new AMessage();
+    msg->clear();
+    convertMetaDataToMessage(meta, &msg);
+    return setAudioFormat(msg, mime, OMXhandle, nodeID, isEncoder);
+}
+
+status_t ExtendedCodec::setAudioFormat(
+        const sp<AMessage> &msg, const char* mime, sp<IOMX> OMXhandle,
+        IOMX::node_id nodeID, bool isEncoder ) {
+    ALOGV("setAudioFormat called");
+    status_t err = OK;
+
+    if ((!strcasecmp(MEDIA_MIMETYPE_AUDIO_AC3, mime)) ||
+        (!strcasecmp(MEDIA_MIMETYPE_AUDIO_EAC3, mime))){
+        int32_t numChannels, sampleRate;
+        /* Commenting follwoing call as AC3 soft decoder does not
+         need it and it causes issue with playback*/
+        //setAC3Format(numChannels, sampleRate, OMXhandle, nodeID);
+        CHECK(msg->findInt32("channel-count", &numChannels));
+        CHECK(msg->findInt32("sample-rate", &sampleRate));
+    } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_EVRC, mime)) {
+        int32_t numChannels, sampleRate;
+        CHECK(msg->findInt32("channel-count", &numChannels));
+        CHECK(msg->findInt32("sample-rate", &sampleRate));
+        setEVRCFormat(numChannels, sampleRate, OMXhandle, nodeID, isEncoder );
+    } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_QCELP, mime)) {
+        int32_t numChannels, sampleRate;
+        CHECK(msg->findInt32("channel-count", &numChannels));
+        CHECK(msg->findInt32("sample-rate", &sampleRate));
+        setQCELPFormat(numChannels, sampleRate, OMXhandle, nodeID, isEncoder);
+    } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_WMA, mime))  {
+        err = setWMAFormat(msg, OMXhandle, nodeID, isEncoder);
+    }
+    return err;
+}
+
+status_t ExtendedCodec::setVideoInputFormat(
+        const char *mime, OMX_VIDEO_CODINGTYPE *compressionFormat) {
+    status_t retVal = OK;
+    if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_DIVX, mime)){
+        *compressionFormat= (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingDivx;
+    } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_DIVX4, mime)){
+        *compressionFormat= (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingDivx;
+    } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_DIVX311, mime)){
+        *compressionFormat= (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingDivx;
+    } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_WMV, mime)){
+        *compressionFormat = OMX_VIDEO_CodingWMV;
+    } else if (!strcasecmp(MEDIA_MIMETYPE_CONTAINER_MPEG2, mime)){
+        *compressionFormat = OMX_VIDEO_CodingMPEG2;
+    } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_HEVC, mime)){
+        *compressionFormat = (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingHevc;
+    } else {
+        retVal = BAD_VALUE;
+    }
+
+    return retVal;
+}
+
+status_t ExtendedCodec::setVideoOutputFormat(
+        const char *mime, OMX_VIDEO_CODINGTYPE *compressionFormat) {
+    status_t retVal = OK;
+    if(!strcasecmp(MEDIA_MIMETYPE_VIDEO_DIVX, mime)) {
+        *compressionFormat = (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingDivx;
+    } else if(!strcasecmp(MEDIA_MIMETYPE_VIDEO_DIVX311, mime)) {
+        *compressionFormat = (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingDivx;
+    } else if(!strcasecmp(MEDIA_MIMETYPE_VIDEO_DIVX4, mime)) {
+        *compressionFormat = (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingDivx;
+    } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_WMV, mime)){
+        *compressionFormat = OMX_VIDEO_CodingWMV;
+    } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_HEVC, mime)){
+        *compressionFormat = (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingHevc;
+    } else {
+        retVal = BAD_VALUE;
+    }
+    return retVal;
+}
+
+status_t ExtendedCodec::setSupportedRole(
+        const sp<IOMX> &omx, IOMX::node_id node,
+        bool isEncoder, const char *mime){
+    ALOGV("setSupportedRole Called %s", mime);
+    struct MimeToRole {
+        const char *mime;
+        const char *decoderRole;
+        const char *encoderRole;
+    };
+
+    static const MimeToRole kQCMimeToRole[] = {
+        { MEDIA_MIMETYPE_AUDIO_EVRC,
+          "audio_decoder.evrchw", "audio_encoder.evrc" },
+        { MEDIA_MIMETYPE_AUDIO_QCELP,
+          "audio_decoder,qcelp13Hw", "audio_encoder.qcelp13" },
+        { MEDIA_MIMETYPE_VIDEO_DIVX,
+          "video_decoder.divx", NULL },
+        { MEDIA_MIMETYPE_VIDEO_DIVX4,
+          "video_decoder.divx", NULL },
+        { MEDIA_MIMETYPE_VIDEO_DIVX311,
+          "video_decoder.divx", NULL },
+        { MEDIA_MIMETYPE_VIDEO_WMV,
+          "video_decoder.vc1",  NULL },
+        { MEDIA_MIMETYPE_AUDIO_AC3,
+          "audio_decoder.ac3", NULL },
+        { MEDIA_MIMETYPE_AUDIO_WMA,
+          "audio_decoder.wma" , NULL },
+        };
+
+    static const size_t kNumMimeToRole =
+                     sizeof(kQCMimeToRole) / sizeof(kQCMimeToRole[0]);
+
+    size_t i;
+    for (i = 0; i < kNumMimeToRole; ++i) {
+        if (!strcasecmp(mime, kQCMimeToRole[i].mime)) {
+            break;
+        }
+    }
+
+    if (i == kNumMimeToRole) {
+        return ERROR_UNSUPPORTED;
+    }
+
+    const char *role =
+        isEncoder ? kQCMimeToRole[i].encoderRole
+                  : kQCMimeToRole[i].decoderRole;
+
+    if (role != NULL) {
+        OMX_PARAM_COMPONENTROLETYPE roleParams;
+        InitOMXParams(&roleParams);
+
+        strncpy((char *)roleParams.cRole,
+                role, OMX_MAX_STRINGNAME_SIZE - 1);
+
+        roleParams.cRole[OMX_MAX_STRINGNAME_SIZE - 1] = '\0';
+
+        status_t err = omx->setParameter(
+                node, OMX_IndexParamStandardComponentRole,
+                &roleParams, sizeof(roleParams));
+
+        if (err != OK) {
+            ALOGW("Failed to set standard component role '%s'.", role);
+            return err;
+        }
+    }
+    return OK;
+}
+
+status_t ExtendedCodec::getSupportedAudioFormatInfo(
+        const AString* mime,
+        sp<IOMX> OMXhandle,
+        IOMX::node_id nodeID,
+        int portIndex,
+        int* channelCount) {
+    status_t retVal = OK;
+    if (!strcmp(mime->c_str(),MEDIA_MIMETYPE_AUDIO_QCELP)) {
+        OMX_AUDIO_PARAM_QCELP13TYPE params;
+        InitOMXParams(&params);
+        params.nPortIndex = portIndex;
+        CHECK_EQ(OMXhandle->getParameter(
+                   nodeID, OMX_IndexParamAudioQcelp13, &params, sizeof(params)), (status_t)OK);
+        *channelCount = params.nChannels;
+    } else if(!strcmp(mime->c_str(), MEDIA_MIMETYPE_AUDIO_EVRC)) {
+        OMX_AUDIO_PARAM_EVRCTYPE params;
+        InitOMXParams(&params);
+        params.nPortIndex = portIndex;
+        CHECK_EQ(OMXhandle->getParameter(
+                   nodeID, OMX_IndexParamAudioEvrc, &params, sizeof(params)), (status_t)OK);
+        *channelCount = params.nChannels;
+    } else {
+        retVal = BAD_VALUE;
+    }
+    return retVal;
+}
+
+status_t ExtendedCodec::handleSupportedAudioFormats(int format, AString* mime) {
+    ALOGV("checkQCFormats called");
+    status_t retVal = OK;
+    if (format == OMX_AUDIO_CodingQCELP13 ) {
+        *mime = MEDIA_MIMETYPE_AUDIO_QCELP;
+    } else if(format == OMX_AUDIO_CodingEVRC ) {
+        *mime = MEDIA_MIMETYPE_AUDIO_EVRC;
+    } else {
+        retVal = BAD_VALUE;
+    }
+    return retVal;
+}
+
+void ExtendedCodec::configureFramePackingFormat(
+        const sp<AMessage> &msg, sp<IOMX> OMXhandle, IOMX::node_id nodeID,
+        const char* componentName) {
+    //ignore non QC components
+    if (strncmp(componentName, "OMX.qcom.", 9)) {
+        return;
+    }
+
+    int32_t arbitraryMode = 0;
+    bool success = msg->findInt32(getMsgKey(kKeyUseArbitraryMode), &arbitraryMode);
+    bool useFrameByFrameMode = true; //default option
+    if (success && arbitraryMode) {
+        useFrameByFrameMode = false;
+    }
+
+    if (useFrameByFrameMode) {
+        ALOGI("Enable frame by frame mode");
+        OMX_QCOM_PARAM_PORTDEFINITIONTYPE portFmt;
+        portFmt.nPortIndex = kPortIndexInput;
+        portFmt.nFramePackingFormat = OMX_QCOM_FramePacking_OnlyOneCompleteFrame;
+        status_t err = OMXhandle->setParameter(
+        nodeID, (OMX_INDEXTYPE)OMX_QcomIndexPortDefn, (void *)&portFmt, sizeof(portFmt));
+        if(err != OK) {
+            ALOGW("Failed to set frame packing format on component");
+        }
+    } else {
+        ALOGI("Decoder should be in arbitrary mode");
+    }
+}
+
+void ExtendedCodec::configureFramePackingFormat(
+        const sp<MetaData> &meta, sp<IOMX> OMXhandle, IOMX::node_id nodeID,
+        const char* componentName) {
+    sp<AMessage> msg = new AMessage();
+    msg->clear();
+    convertMetaDataToMessage(meta, &msg);
+    configureFramePackingFormat(msg, OMXhandle, nodeID, componentName);
+}
+
+void ExtendedCodec::configureVideoDecoder(
+        const sp<AMessage> &msg, const char* mime, sp<IOMX> OMXhandle,
+        const uint32_t flags, IOMX::node_id nodeID, const char* componentName ) {
+    if (strncmp(componentName, "OMX.qcom.", 9)) {
+        //do nothing for non QC component
+        return;
+    }
+
+    setDIVXFormat(msg, mime, OMXhandle, nodeID, kPortIndexOutput);
+    AString fileFormat;
+    const char *fileFormatCStr = NULL;
+    bool success = msg->findString(getMsgKey(kKeyFileFormat), &fileFormat);
+    if (success) {
+        fileFormatCStr = fileFormat.c_str();
+    }
+
+    // Enable timestamp reordering for AVI file type, mpeg4 and vc1 codec types
+    if (!strcmp(componentName, "OMX.qcom.video.decoder.vc1") ||
+        !strcmp(componentName, "OMX.qcom.video.decoder.mpeg4") ||
+        (fileFormatCStr!= NULL && !strncmp(fileFormatCStr, "video/avi", 9))) {
+        ALOGI("Enabling timestamp reordering");
+        QOMX_INDEXTIMESTAMPREORDER reorder;
+        InitOMXParams(&reorder);
+        reorder.nPortIndex = kPortIndexOutput;
+        reorder.bEnable = OMX_TRUE;
+        status_t err = OMXhandle->setParameter(nodeID,
+                       (OMX_INDEXTYPE)OMX_QcomIndexParamEnableTimeStampReorder,
+                       (void *)&reorder, sizeof(reorder));
+
+        if(err != OK) {
+            ALOGW("Failed to enable timestamp reordering");
+        }
+    }
+
+    // Enable Sync-frame decode mode for thumbnails
+    if (flags & OMXCodec::kClientNeedsFramebuffer) {
+        ALOGV("Enabling thumbnail mode.");
+        QOMX_ENABLETYPE enableType;
+        OMX_INDEXTYPE indexType;
+
+        status_t err = OMXhandle->getExtensionIndex(
+                nodeID, OMX_QCOM_INDEX_PARAM_VIDEO_SYNCFRAMEDECODINGMODE,
+                &indexType);
+        if(err != OK) {
+            ALOGW("Failed to get extension for SYNCFRAMEDECODINGMODE");
+            return;
+        }
+
+        enableType.bEnable = OMX_TRUE;
+        err = OMXhandle->setParameter(nodeID,indexType,
+                   (void *)&enableType, sizeof(enableType));
+        if(err != OK) {
+            ALOGW("Failed to get extension for SYNCFRAMEDECODINGMODE");
+            return;
+        }
+        ALOGI("Thumbnail mode enabled.");
+    }
+
+}
+
+void ExtendedCodec::configureVideoDecoder(
+        const sp<MetaData> &meta, const char* mime, sp<IOMX> OMXhandle,
+        const uint32_t flags, IOMX::node_id nodeID, const char* componentName ) {
+    sp<AMessage> msg = new AMessage();
+    msg->clear();
+    convertMetaDataToMessage(meta, &msg);
+    configureVideoDecoder(msg, mime, OMXhandle, flags, nodeID, componentName);
+}
+
+void ExtendedCodec::enableSmoothStreaming(
+        const sp<IOMX> &omx, IOMX::node_id nodeID, bool* isEnabled,
+        const char* componentName) {
+    *isEnabled = false;
+
+    if (!ExtendedUtils::ShellProp::isSmoothStreamingEnabled()) {
+        return;
+    }
+
+    //ignore non QC components
+    if (strncmp(componentName, "OMX.qcom.", 9)) {
+        return;
+    }
+    status_t err = omx->setParameter(
+            nodeID,
+            (OMX_INDEXTYPE)OMX_QcomIndexParamEnableSmoothStreaming,
+            &err, sizeof(status_t));
+    if (err != OK) {
+        ALOGE("Failed to enable Smoothstreaming!");
+        return;
+    }
+    *isEnabled = true;
+    ALOGI("Smoothstreaming Enabled");
+    return;
+}
+
+//private methods
+void ExtendedCodec::setEVRCFormat(
+        int32_t numChannels, int32_t sampleRate, sp<IOMX> OMXhandle,
+        IOMX::node_id nodeID, bool isEncoder ) {
+    ALOGV("setEVRCFormat called");
+
+    if (isEncoder) {
+        CHECK(numChannels == 1);
+        //////////////// input port ////////////////////
+        //handle->setRawAudioFormat(kPortIndexInput, sampleRate, numChannels);
+        //////////////// output port ////////////////////
+        // format
+        OMX_AUDIO_PARAM_PORTFORMATTYPE format;
+        format.nPortIndex = kPortIndexOutput;
+        format.nIndex = 0;
+        status_t err = OMX_ErrorNone;
+        while (OMX_ErrorNone == err) {
+            CHECK_EQ(OMXhandle->getParameter(nodeID, OMX_IndexParamAudioPortFormat,
+                    &format, sizeof(format)), (status_t)OK);
+            if (format.eEncoding == OMX_AUDIO_CodingEVRC) {
+                break;
+            }
+            format.nIndex++;
+        }
+        CHECK_EQ((status_t)OK, err);
+        CHECK_EQ(OMXhandle->setParameter(nodeID, OMX_IndexParamAudioPortFormat,
+                &format, sizeof(format)), (status_t)OK);
+
+        // port definition
+        OMX_PARAM_PORTDEFINITIONTYPE def;
+        InitOMXParams(&def);
+        def.nPortIndex = kPortIndexOutput;
+        def.format.audio.cMIMEType = NULL;
+        CHECK_EQ(OMXhandle->getParameter(nodeID, OMX_IndexParamPortDefinition,
+                &def, sizeof(def)), (status_t)OK);
+        def.format.audio.bFlagErrorConcealment = OMX_TRUE;
+        def.format.audio.eEncoding = OMX_AUDIO_CodingEVRC;
+        CHECK_EQ(OMXhandle->setParameter(nodeID, OMX_IndexParamPortDefinition,
+                &def, sizeof(def)), (status_t)OK);
+
+        // profile
+        OMX_AUDIO_PARAM_EVRCTYPE profile;
+        InitOMXParams(&profile);
+        profile.nPortIndex = kPortIndexOutput;
+        CHECK_EQ(OMXhandle->getParameter(nodeID, OMX_IndexParamAudioEvrc,
+                &profile, sizeof(profile)), (status_t)OK);
+        profile.nChannels = numChannels;
+        CHECK_EQ(OMXhandle->setParameter(nodeID, OMX_IndexParamAudioEvrc,
+                &profile, sizeof(profile)), (status_t)OK);
+    }
+    else{
+      ALOGI("EVRC decoder \n");
+    }
+}
+
+void ExtendedCodec::setQCELPFormat(
+        int32_t numChannels, int32_t sampleRate, sp<IOMX> OMXhandle,
+        IOMX::node_id nodeID, bool isEncoder ) {
+
+    if (isEncoder) {
+        CHECK(numChannels == 1);
+        //////////////// input port ////////////////////
+        //handle->setRawAudioFormat(kPortIndexInput, sampleRate, numChannels);
+        //////////////// output port ////////////////////
+        // format
+        OMX_AUDIO_PARAM_PORTFORMATTYPE format;
+        format.nPortIndex = kPortIndexOutput;
+        format.nIndex = 0;
+        status_t err = OMX_ErrorNone;
+        while (OMX_ErrorNone == err) {
+            CHECK_EQ(OMXhandle->getParameter(nodeID, OMX_IndexParamAudioPortFormat,
+                    &format, sizeof(format)), (status_t)OK);
+            if (format.eEncoding == OMX_AUDIO_CodingQCELP13) {
+                break;
+            }
+            format.nIndex++;
+        }
+        CHECK_EQ((status_t)OK, err);
+        CHECK_EQ(OMXhandle->setParameter(nodeID, OMX_IndexParamAudioPortFormat,
+                &format, sizeof(format)), (status_t)OK);
+
+        // port definition
+        OMX_PARAM_PORTDEFINITIONTYPE def;
+        InitOMXParams(&def);
+        def.nPortIndex = kPortIndexOutput;
+        def.format.audio.cMIMEType = NULL;
+        CHECK_EQ(OMXhandle->getParameter(nodeID, OMX_IndexParamPortDefinition,
+                &def, sizeof(def)), (status_t)OK);
+        def.format.audio.bFlagErrorConcealment = OMX_TRUE;
+        def.format.audio.eEncoding = OMX_AUDIO_CodingQCELP13;
+        CHECK_EQ(OMXhandle->setParameter(nodeID, OMX_IndexParamPortDefinition,
+                &def, sizeof(def)), (status_t)OK);
+
+        // profile
+        OMX_AUDIO_PARAM_QCELP13TYPE profile;
+        InitOMXParams(&profile);
+        profile.nPortIndex = kPortIndexOutput;
+        CHECK_EQ(OMXhandle->getParameter(nodeID, OMX_IndexParamAudioQcelp13,
+                &profile, sizeof(profile)), (status_t)OK);
+        profile.nChannels = numChannels;
+        CHECK_EQ(OMXhandle->setParameter(nodeID, OMX_IndexParamAudioQcelp13,
+                &profile, sizeof(profile)), (status_t)OK);
+    }
+    else {
+        ALOGI("QCELP decoder \n");
+    }
+}
+
+status_t ExtendedCodec::setWMAFormat(
+        const sp<MetaData> &meta, sp<IOMX> OMXhandle,
+        IOMX::node_id nodeID, bool isEncoder ) {
+    sp<AMessage> msg = new AMessage();
+    msg->clear();
+    convertMetaDataToMessage(meta, &msg);
+    return setWMAFormat(msg, OMXhandle, nodeID, isEncoder);
+}
+
+status_t ExtendedCodec::setWMAFormat(
+        const sp<AMessage> &msg, sp<IOMX> OMXhandle,
+        IOMX::node_id nodeID, bool isEncoder ) {
+    ALOGV("setWMAFormat Called");
+
+    if (isEncoder) {
+        ALOGE("WMA encoding not supported");
+        return OK;
+    } else {
+        int32_t version;
+        OMX_AUDIO_PARAM_WMATYPE paramWMA;
+        QOMX_AUDIO_PARAM_WMA10PROTYPE paramWMA10;
+        CHECK(msg->findInt32(getMsgKey(kKeyWMAVersion), &version));
+        int32_t numChannels;
+        int32_t bitRate;
+        int32_t sampleRate;
+        int32_t encodeOptions;
+        int32_t blockAlign;
+        int32_t bitspersample;
+        int32_t formattag;
+        int32_t advencopt1;
+        int32_t advencopt2;
+        int32_t VirtualPktSize;
+        if(version==kTypeWMAPro || version==kTypeWMALossLess) {
+            CHECK(msg->findInt32(getMsgKey(kKeyWMABitspersample), &bitspersample));
+            CHECK(msg->findInt32(getMsgKey(kKeyWMAFormatTag), &formattag));
+            CHECK(msg->findInt32(getMsgKey(kKeyWMAAdvEncOpt1), &advencopt1));
+            CHECK(msg->findInt32(getMsgKey(kKeyWMAAdvEncOpt2), &advencopt2));
+            CHECK(msg->findInt32(getMsgKey(kKeyWMAVirPktSize), &VirtualPktSize));
+        }
+        if(version==kTypeWMA) {
+            InitOMXParams(&paramWMA);
+            paramWMA.nPortIndex = kPortIndexInput;
+        } else if(version==kTypeWMAPro || version==kTypeWMALossLess) {
+            InitOMXParams(&paramWMA10);
+            paramWMA10.nPortIndex = kPortIndexInput;
+        }
+        CHECK(msg->findInt32("channel-count", &numChannels));
+        CHECK(msg->findInt32("sample-rate", &sampleRate));
+        CHECK(msg->findInt32(getMsgKey(kKeyBitRate), &bitRate));
+        CHECK(msg->findInt32(getMsgKey(kKeyWMAEncodeOpt), &encodeOptions));
+        CHECK(msg->findInt32(getMsgKey(kKeyWMABlockAlign), &blockAlign));
+        ALOGV("Channels: %d, SampleRate: %d, BitRate; %d"
+                   "EncodeOptions: %d, blockAlign: %d", numChannels,
+                   sampleRate, bitRate, encodeOptions, blockAlign);
+        if(sampleRate>48000 || numChannels>2)
+        {
+            ALOGE("Unsupported samplerate/channels");
+            return ERROR_UNSUPPORTED;
+        }
+        if(version==kTypeWMAPro || version==kTypeWMALossLess)
+        {
+            ALOGV("Bitspersample: %d, wmaformattag: %d,"
+                       "advencopt1: %d, advencopt2: %d VirtualPktSize %d", bitspersample,
+                       formattag, advencopt1, advencopt2, VirtualPktSize);
+        }
+        status_t err = OK;
+        OMX_INDEXTYPE index;
+        if(version==kTypeWMA) {
+            err = OMXhandle->getParameter(
+                   nodeID, OMX_IndexParamAudioWma, &paramWMA, sizeof(paramWMA));
+        } else if(version==kTypeWMAPro || version==kTypeWMALossLess) {
+            OMXhandle->getExtensionIndex(nodeID,"OMX.Qualcomm.index.audio.wma10Pro",&index);
+            err = OMXhandle->getParameter(
+                   nodeID, index, &paramWMA10, sizeof(paramWMA10));
+        }
+        CHECK_EQ(err, (status_t)OK);
+        if(version==kTypeWMA) {
+            paramWMA.nChannels = numChannels;
+            paramWMA.nSamplingRate = sampleRate;
+            paramWMA.nEncodeOptions = encodeOptions;
+            paramWMA.nBitRate = bitRate;
+            paramWMA.nBlockAlign = blockAlign;
+        } else if(version==kTypeWMAPro || version==kTypeWMALossLess) {
+            paramWMA10.nChannels = numChannels;
+            paramWMA10.nSamplingRate = sampleRate;
+            paramWMA10.nEncodeOptions = encodeOptions;
+            paramWMA10.nBitRate = bitRate;
+            paramWMA10.nBlockAlign = blockAlign;
+        }
+        if(version==kTypeWMAPro || version==kTypeWMALossLess) {
+            paramWMA10.advancedEncodeOpt = advencopt1;
+            paramWMA10.advancedEncodeOpt2 = advencopt2;
+            paramWMA10.formatTag = formattag;
+            paramWMA10.validBitsPerSample = bitspersample;
+            paramWMA10.nVirtualPktSize = VirtualPktSize;
+        }
+        if(version==kTypeWMA) {
+            err = OMXhandle->setParameter(
+                  nodeID, OMX_IndexParamAudioWma, &paramWMA, sizeof(paramWMA));
+        } else if(version==kTypeWMAPro || version==kTypeWMALossLess) {
+           err = OMXhandle->setParameter(
+                 nodeID, index, &paramWMA10, sizeof(paramWMA10));
+        }
+        return err;
+    }
+    return OK;
+}
+
+void ExtendedCodec::setAC3Format(
+        int32_t numChannels, int32_t sampleRate, sp<IOMX> OMXhandle,
+        IOMX::node_id nodeID) {
+    QOMX_AUDIO_PARAM_AC3TYPE profileAC3;
+    QOMX_AUDIO_PARAM_AC3PP profileAC3PP;
+    OMX_INDEXTYPE indexTypeAC3;
+    OMX_INDEXTYPE indexTypeAC3PP;
+    OMX_PARAM_PORTDEFINITIONTYPE portParam;
+
+    //configure input port
+    ALOGV("setAC3Format samplerate %d, numChannels %d", sampleRate, numChannels);
+    InitOMXParams(&portParam);
+    portParam.nPortIndex = 0;
+    status_t err = OMXhandle->getParameter(
+       nodeID, OMX_IndexParamPortDefinition, &portParam, sizeof(portParam));
+    CHECK_EQ(err, (status_t)OK);
+    err = OMXhandle->setParameter(
+       nodeID, OMX_IndexParamPortDefinition, &portParam, sizeof(portParam));
+    CHECK_EQ(err, (status_t)OK);
+
+    //configure output port
+    portParam.nPortIndex = 1;
+    err = OMXhandle->getParameter(
+       nodeID, OMX_IndexParamPortDefinition, &portParam, sizeof(portParam));
+    CHECK_EQ(err, (status_t)OK);
+    err = OMXhandle->setParameter(
+       nodeID, OMX_IndexParamPortDefinition, &portParam, sizeof(portParam));
+    CHECK_EQ(err, (status_t)OK);
+
+    err = OMXhandle->getExtensionIndex(nodeID, OMX_QCOM_INDEX_PARAM_AC3TYPE, &indexTypeAC3);
+
+    InitOMXParams(&profileAC3);
+    profileAC3.nPortIndex = kPortIndexInput;
+    err = OMXhandle->getParameter(nodeID, indexTypeAC3, &profileAC3, sizeof(profileAC3));
+    CHECK_EQ(err,(status_t)OK);
+
+    profileAC3.nSamplingRate  =  sampleRate;
+    profileAC3.nChannels      =  2;
+    profileAC3.eChannelConfig =  OMX_AUDIO_AC3_CHANNEL_CONFIG_2_0;
+
+    ALOGV("numChannels = %d, profileAC3.nChannels = %d", numChannels, profileAC3.nChannels);
+
+    err = OMXhandle->setParameter(nodeID, indexTypeAC3, &profileAC3, sizeof(profileAC3));
+    CHECK_EQ(err,(status_t)OK);
+
+    //for output port
+    OMX_AUDIO_PARAM_PCMMODETYPE profilePcm;
+    InitOMXParams(&profilePcm);
+    profilePcm.nPortIndex = kPortIndexOutput;
+    err = OMXhandle->getParameter(
+            nodeID, OMX_IndexParamAudioPcm, &profilePcm, sizeof(profilePcm));
+    CHECK_EQ(err, (status_t)OK);
+
+    profilePcm.nSamplingRate  =  sampleRate;
+    err = OMXhandle->setParameter(
+            nodeID, OMX_IndexParamAudioPcm, &profilePcm, sizeof(profilePcm));
+    CHECK_EQ(err, (status_t)OK);
+    OMXhandle->getExtensionIndex(nodeID, OMX_QCOM_INDEX_PARAM_AC3PP, &indexTypeAC3PP);
+
+    InitOMXParams(&profileAC3PP);
+    profileAC3PP.nPortIndex = kPortIndexInput;
+    err = OMXhandle->getParameter(
+            nodeID, indexTypeAC3PP, &profileAC3PP, sizeof(profileAC3PP));
+    CHECK_EQ(err, (status_t)OK);
+
+    int i;
+    int channel_routing[6] = {0};
+
+    for (i=0; i<6; i++) {
+        channel_routing[i] = -1;
+    }
+    for (i=0; i<6; i++) {
+        profileAC3PP.eChannelRouting[i] =  (OMX_AUDIO_AC3_CHANNEL_ROUTING)channel_routing[i];
+    }
+
+    profileAC3PP.eChannelRouting[0] =  OMX_AUDIO_AC3_CHANNEL_LEFT;
+    profileAC3PP.eChannelRouting[1] =  OMX_AUDIO_AC3_CHANNEL_RIGHT;
+    err = OMXhandle->setParameter(nodeID, indexTypeAC3PP, &profileAC3PP, sizeof(profileAC3PP));
+    CHECK_EQ(err, (status_t)OK);
+}
+
+bool ExtendedCodec::useHWAACDecoder(const char *mime) {
+    char value[PROPERTY_VALUE_MAX] = {0};
+    int aaccodectype = 0;
+    aaccodectype = property_get("media.aaccodectype", value, NULL);
+    if (aaccodectype && !strncmp("0", value, 1) &&
+        !strncmp(mime, MEDIA_MIMETYPE_AUDIO_AAC,sizeof(MEDIA_MIMETYPE_AUDIO_AAC))) {
+        ALOGI("Using Hardware AAC Decoder");
+        return true;
+    }
+    return false;
+}
+
+} //namespace android
+
+#else //ENABLE_AV_ENHANCEMENTS
+
+namespace android {
+    status_t ExtendedCodec::convertMetaDataToMessage(
+            const sp<MetaData> &meta, sp<AMessage> *format) {
+        return OK;
+    }
+
+    uint32_t ExtendedCodec::getComponentQuirks (
+            const MediaCodecList *list, size_t index) {
+        return 0;
+    }
+
+    status_t ExtendedCodec::setDIVXFormat(
+            const sp<AMessage> &msg, const char* mime,
+            sp<IOMX> OMXhandle,IOMX::node_id nodeID, int port_index) {
+        return OK;
+    }
+
+    status_t ExtendedCodec::setAudioFormat(
+            const sp<MetaData> &meta, const char* mime,
+            sp<IOMX> OMXhandle,IOMX::node_id nodeID,
+            bool isEncoder) {
+        return OK;
+    }
+
+    status_t ExtendedCodec::setAudioFormat(
+            const sp<AMessage> &msg, const char* mime,
+            sp<IOMX> OMXhandle,IOMX::node_id nodeID,
+            bool isEncoder) {
+        return OK;
+    }
+
+    status_t ExtendedCodec::setVideoInputFormat(
+            const char *mime,
+            OMX_VIDEO_CODINGTYPE *compressionFormat) {
+        return OK;
+    }
+
+    status_t ExtendedCodec::setVideoOutputFormat(
+            const char *mime,
+            OMX_VIDEO_CODINGTYPE *compressionFormat) {
+        return OK;
+    }
+
+    status_t ExtendedCodec::getSupportedAudioFormatInfo(
+            const AString* mime,
+            sp<IOMX> OMXhandle,
+            IOMX::node_id nodeID,
+            int portIndex,
+            int* channelCount) {
+        return OK;
+    }
+
+    status_t ExtendedCodec::handleSupportedAudioFormats(
+            int format, AString* meta) {
+        return UNKNOWN_ERROR;
+    }
+
+    const char* ExtendedCodec::overrideComponentName (
+            uint32_t quirks, const sp<MetaData> &meta) {
+        return NULL;
+    }
+
+    void ExtendedCodec::overrideComponentName(
+            uint32_t quirks, const sp<AMessage> &msg,
+            AString* componentName){
+    }
+
+    void ExtendedCodec::getRawCodecSpecificData(
+        const sp<MetaData> &meta, const void* &data, size_t &size) {
+            size = 0;
+    }
+
+    sp<ABuffer> ExtendedCodec::getRawCodecSpecificData(
+            const sp<AMessage> &msg){
+        return NULL;
+    }
+
+    void ExtendedCodec::getAacCodecSpecificData(
+            const sp<MetaData> &meta,
+            const void* &data,
+            size_t& size){
+        return;
+    }
+
+    sp<ABuffer> ExtendedCodec::getAacCodecSpecificData(
+            const sp<AMessage> &msg){
+        return NULL;
+    }
+
+
+    status_t ExtendedCodec::setSupportedRole(
+            const sp<IOMX> &omx, IOMX::node_id node,
+            bool isEncoder, const char *mime) {
+        return OK;
+    }
+
+    status_t ExtendedCodec::setWMAFormat(
+            const sp<MetaData> &meta, sp<IOMX> OMXhandle,
+            IOMX::node_id nodeID, bool isEncoder) {
+        return OK;
+    }
+
+    status_t ExtendedCodec::setWMAFormat(
+            const sp<AMessage> &msg, sp<IOMX> OMXhandle,
+            IOMX::node_id nodeID, bool isEncoder) {
+        return OK;
+    }
+
+    void ExtendedCodec::setEVRCFormat(
+            int32_t numChannels, int32_t sampleRate,
+            sp<IOMX> OMXhandle, IOMX::node_id nodeID,
+            bool isEncoder) {
+    }
+
+    void ExtendedCodec::setQCELPFormat(
+            int32_t numChannels, int32_t sampleRate,
+            sp<IOMX> OMXhandle, IOMX::node_id nodeID,
+            bool isEncoder) {
+    }
+
+    void ExtendedCodec::setAC3Format(
+            int32_t numChannels, int32_t sampleRate,
+            sp<IOMX> OMXhandle, IOMX::node_id nodeID) {
+    }
+
+    void ExtendedCodec::configureFramePackingFormat(
+            const sp<AMessage> &msg, sp<IOMX> OMXhandle,
+            IOMX::node_id nodeID, const char* componentName){
+    }
+
+    void ExtendedCodec::configureFramePackingFormat(
+            const sp<MetaData> &meta, sp<IOMX> OMXhandle,
+            IOMX::node_id nodeID, const char* componentName) {
+    }
+
+    void ExtendedCodec::configureVideoDecoder(
+        const sp<MetaData> &meta, const char* mime, sp<IOMX> OMXhandle,
+        const uint32_t flags, IOMX::node_id nodeID, const char* componentName) {
+    }
+
+    void ExtendedCodec::configureVideoDecoder(
+        const sp<AMessage> &msg, const char* mime,  sp<IOMX> OMXhandle,
+        const uint32_t flags, IOMX::node_id nodeID, const char* componentName) {
+    }
+
+    bool ExtendedCodec::useHWAACDecoder(const char *mime) {
+        return false;
+    }
+
+    void ExtendedCodec::enableSmoothStreaming(
+            const sp<IOMX> &omx, IOMX::node_id nodeID, bool* isEnabled,
+            const char* componentName) {
+        *isEnabled = false;
+        return;
+    }
+
+} //namespace android
+
+#endif //ENABLE_AV_ENHANCEMENTS
diff --git a/media/libstagefright/ExtendedExtractor.cpp b/media/libstagefright/ExtendedExtractor.cpp
new file mode 100644
index 0000000..952f542
--- /dev/null
+++ b/media/libstagefright/ExtendedExtractor.cpp
@@ -0,0 +1,143 @@
+/*Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials provided
+ *      with the distribution.
+ *     * Neither the name of The Linux Foundation nor the names of its
+ *      contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "ExtendedExtractor"
+#include <utils/Log.h>
+#include <dlfcn.h>  // for dlopen/dlclose
+#include "include/ExtendedExtractor.h"
+
+#ifdef ENABLE_AV_ENHANCEMENTS
+
+namespace android {
+
+static const char* EXTENDED_EXTRACTOR_LIB = "libExtendedExtractor.so";
+static const char* EXTENDED_EXTRACTOR_CREATE = "CreateExtractor";
+static const char* EXTENDED_EXTRACTOR_SNIFF = "SniffExtendedExtractor";
+
+typedef MediaExtractor* (*ExtendedExtractorCreate)
+                            (const sp<DataSource> &source, const char* mime);
+
+typedef bool (*ExtendedExtractorSniff)
+                 (const sp<DataSource> &source, String8 *mimeType,
+                 float *confidence,sp<AMessage> *meta);
+
+static void* loadExtendedExtractorLib() {
+    static void* extendedExtractorLib = NULL;
+    static bool alreadyTriedToLoadLib = false;
+
+    if(!alreadyTriedToLoadLib) {
+        alreadyTriedToLoadLib = true;
+
+        extendedExtractorLib = ::dlopen(EXTENDED_EXTRACTOR_LIB, RTLD_LAZY);
+
+        if(extendedExtractorLib == NULL) {
+            ALOGV("Failed to load %s, dlerror = %s \n",
+                EXTENDED_EXTRACTOR_LIB, dlerror());
+        }
+    }
+
+    return extendedExtractorLib;
+}
+
+MediaExtractor* ExtendedExtractor::Create (
+        const sp<DataSource> &source, const char *mime) {
+    static ExtendedExtractorCreate create = NULL;
+    static bool alreadyTriedToFindCreateFunction = false;
+    MediaExtractor* extractor = NULL;
+
+    if (!alreadyTriedToFindCreateFunction) {
+        void *extendedExtractorLib = loadExtendedExtractorLib();
+
+        if (extendedExtractorLib != NULL) {
+            create = (ExtendedExtractorCreate) dlsym (
+                    extendedExtractorLib, EXTENDED_EXTRACTOR_CREATE);
+            alreadyTriedToFindCreateFunction = true;
+        }
+    }
+
+    if (create == NULL) {
+        ALOGE ("Failed to find symbol : %s, dlerror = %s",
+            EXTENDED_EXTRACTOR_CREATE, dlerror());
+        return NULL;
+    }
+
+    extractor = create (source, mime);
+    if (extractor == NULL) {
+        ALOGE("Failed to instantiate extractor \n");
+    }
+
+    return extractor;
+}
+
+bool ExtendedExtractor::Sniff (
+        const sp<DataSource> &source, String8 *mimeType,
+        float *confidence,sp<AMessage> *meta) {
+    void *extendedExtractorLib = loadExtendedExtractorLib();
+    bool retVal = false;
+
+    if (extendedExtractorLib != NULL) {
+       ExtendedExtractorSniff sniff = (ExtendedExtractorSniff) dlsym (
+               extendedExtractorLib, EXTENDED_EXTRACTOR_SNIFF);
+
+        if (sniff == NULL) {
+            ALOGE ("Failed to find symbol : %s, dlerror = %s",
+                EXTENDED_EXTRACTOR_SNIFF, dlerror());
+            return retVal;
+        }
+
+       retVal = sniff (source, mimeType, confidence, meta);
+
+       if(!retVal) {
+           ALOGV("Sniff Failed");
+       }
+    }
+    return retVal;
+}
+
+}  // namespace android
+
+#else //ENABLE_AV_ENHANCEMENTS
+
+namespace android {
+
+MediaExtractor* ExtendedExtractor::Create (
+        const sp<DataSource> &source, const char *mime) {
+    return NULL;
+}
+bool ExtendedExtractor::Sniff (
+        const sp<DataSource> &source, String8 *mimeType,
+        float *confidence,sp<AMessage> *meta) {
+    *confidence = 0.0;
+    return false;
+}
+
+}  // namespace android
+
+#endif //ENABLE_AV_ENHANCEMENTS
+
diff --git a/media/libstagefright/ExtendedMediaDefs.cpp b/media/libstagefright/ExtendedMediaDefs.cpp
new file mode 100644
index 0000000..209db2b
--- /dev/null
+++ b/media/libstagefright/ExtendedMediaDefs.cpp
@@ -0,0 +1,66 @@
+/*Copyright (c) 2012 - 2013, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials provided
+ *      with the distribution.
+ *     * Neither the name of The Linux Foundation nor the names of its
+ *      contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <QCMediaDefs.h>
+
+namespace android {
+
+const char *MEDIA_MIMETYPE_AUDIO_EVRC = "audio/evrc";
+
+const char *MEDIA_MIMETYPE_VIDEO_WMV = "video/x-ms-wmv";
+const char *MEDIA_MIMETYPE_AUDIO_WMA = "audio/x-ms-wma";
+const char *MEDIA_MIMETYPE_CONTAINER_ASF = "video/x-ms-asf";
+const char *MEDIA_MIMETYPE_VIDEO_DIVX = "video/divx";
+const char *MEDIA_MIMETYPE_AUDIO_AC3 = "audio/ac3";
+const char *MEDIA_MIMETYPE_CONTAINER_AAC = "audio/aac";
+const char *MEDIA_MIMETYPE_CONTAINER_QCP = "audio/vnd.qcelp";
+const char *MEDIA_MIMETYPE_VIDEO_DIVX311 = "video/divx311";
+const char *MEDIA_MIMETYPE_VIDEO_DIVX4 = "video/divx4";
+
+const char *MEDIA_MIMETYPE_CONTAINER_MPEG2 = "video/mp2";
+
+const char *MEDIA_MIMETYPE_CONTAINER_3G2 = "video/3g2";
+const char *MEDIA_MIMETYPE_AUDIO_DTS = "audio/dts";
+
+const char *MEDIA_MIMETYPE_AUDIO_DTS_LBR = "audio/dts-lbr";
+const char *MEDIA_MIMETYPE_AUDIO_EAC3 = "audio/eac3";
+const char *MEDIA_MIMETYPE_AUDIO_AMR_WB_PLUS = "audio/amr-wb-plus";
+const char *MEDIA_MIMETYPE_VIDEO_HEVC = "video/hevc";
+const char *MEDIA_MIMETYPE_CONTAINER_QCAMR_NB = "audio/qc-amr";
+const char *MEDIA_MIMETYPE_CONTAINER_QCAMR_WB = "audio/qc-amr-wb";
+const char *MEDIA_MIMETYPE_CONTAINER_QCMPEG = "audio/qc-mpeg";
+const char *MEDIA_MIMETYPE_CONTAINER_QCWAV = "audio/qc-wav";
+const char *MEDIA_MIMETYPE_CONTAINER_QCMPEG2TS = "video/qc-mp2ts";
+const char *MEDIA_MIMETYPE_CONTAINER_QCMPEG2PS = "video/qc-mp2ps";
+const char *MEDIA_MIMETYPE_CONTAINER_QCMPEG4 = "video/qc-mp4";
+const char *MEDIA_MIMETYPE_CONTAINER_QCMATROSKA = "video/qc-matroska";
+const char *MEDIA_MIMETYPE_CONTAINER_QCOGG = "video/qc-ogg";
+const char *MEDIA_MIMETYPE_CONTAINER_QCFLV = "video/qc-flv";
+const char *MEDIA_MIMETYPE_VIDEO_VPX = "video/x-vnd.on2.vp8"; //backward compatibility
+
+}  // namespace android
diff --git a/media/libstagefright/ExtendedUtils.cpp b/media/libstagefright/ExtendedUtils.cpp
new file mode 100644
index 0000000..1799784
--- /dev/null
+++ b/media/libstagefright/ExtendedUtils.cpp
@@ -0,0 +1,649 @@
+/*Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials provided
+ *      with the distribution.
+ *     * Neither the name of The Linux Foundation nor the names of its
+ *      contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "ExtendedUtils"
+#include <utils/Log.h>
+
+#include <utils/Errors.h>
+#include <sys/types.h>
+#include <ctype.h>
+#include <unistd.h>
+
+#include <media/stagefright/MetaData.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/OMXCodec.h>
+#include <cutils/properties.h>
+#include <media/stagefright/MediaExtractor.h>
+
+#include "include/ExtendedUtils.h"
+
+static const int64_t kDefaultAVSyncLateMargin =  40000;
+static const int64_t kMaxAVSyncLateMargin     = 250000;
+
+#ifdef ENABLE_AV_ENHANCEMENTS
+
+#include <QCMetaData.h>
+#include <QCMediaDefs.h>
+
+#include "include/ExtendedExtractor.h"
+#include "include/avc_utils.h"
+
+namespace android {
+
+void ExtendedUtils::HFR::setHFRIfEnabled(
+        const CameraParameters& params,
+        sp<MetaData> &meta) {
+    const char *hfr_str = params.get("video-hfr");
+    int32_t hfr = -1;
+    if ( hfr_str != NULL ) {
+        hfr = atoi(hfr_str);
+    }
+    if (hfr < 0) {
+        ALOGW("Invalid hfr value(%d) set from app. Disabling HFR.", hfr);
+        hfr = 0;
+    }
+
+    meta->setInt32(kKeyHFR, hfr);
+}
+
+status_t ExtendedUtils::HFR::reCalculateFileDuration(
+        sp<MetaData> &meta, sp<MetaData> &enc_meta,
+        int64_t &maxFileDurationUs, int32_t frameRate,
+        video_encoder videoEncoder) {
+    status_t retVal = OK;
+    int32_t hfr = 0;
+
+    if (!meta->findInt32(kKeyHFR, &hfr)) {
+        ALOGW("hfr not found, default to 0");
+    }
+
+    if (hfr && frameRate) {
+        maxFileDurationUs = maxFileDurationUs * (hfr/frameRate);
+    }
+
+    enc_meta->setInt32(kKeyHFR, hfr);
+    int32_t width = 0, height = 0;
+
+    CHECK(meta->findInt32(kKeyWidth, &width));
+    CHECK(meta->findInt32(kKeyHeight, &height));
+
+    char mDeviceName[100];
+    property_get("ro.board.platform",mDeviceName,"0");
+    if (!strncmp(mDeviceName, "msm7627a", 8)) {
+        if (hfr && (width * height > 432*240)) {
+            ALOGE("HFR mode is supported only upto WQVGA resolution");
+            return INVALID_OPERATION;
+        }
+    } else if (!strncmp(mDeviceName, "msm8974", 7) ||
+               !strncmp(mDeviceName, "msm8610", 7)) {
+        if (hfr && (width * height > 1920*1088)) {
+            ALOGE("HFR mode is supported only upto 1080p resolution");
+            return INVALID_OPERATION;
+        }
+    } else {
+        if (hfr && ((videoEncoder != VIDEO_ENCODER_H264) || (width * height > 800*480))) {
+            ALOGE("HFR mode is supported only upto WVGA and H264 codec.");
+            return INVALID_OPERATION;
+        }
+    }
+    return retVal;
+}
+
+void ExtendedUtils::HFR::reCalculateTimeStamp(
+        sp<MetaData> &meta, int64_t &timestampUs) {
+    int32_t frameRate = 0, hfr = 0;
+    if (!(meta->findInt32(kKeyFrameRate, &frameRate))) {
+        return;
+    }
+
+    if (!(meta->findInt32(kKeyHFR, &hfr))) {
+        return;
+    }
+
+    if (hfr && frameRate) {
+        timestampUs = (hfr * timestampUs) / frameRate;
+    }
+}
+
+void ExtendedUtils::HFR::reCalculateHFRParams(
+        const sp<MetaData> &meta, int32_t &frameRate,
+        int32_t &bitRate) {
+    int32_t hfr = 0;
+    if (!(meta->findInt32(kKeyHFR, &hfr))) {
+        return;
+    }
+
+    if (hfr && frameRate) {
+        bitRate = (hfr * bitRate) / frameRate;
+        frameRate = hfr;
+    }
+}
+
+void ExtendedUtils::HFR::copyHFRParams(
+        const sp<MetaData> &inputFormat,
+        sp<MetaData> &outputFormat) {
+    int32_t frameRate = 0, hfr = 0;
+    inputFormat->findInt32(kKeyHFR, &hfr);
+    inputFormat->findInt32(kKeyFrameRate, &frameRate);
+    outputFormat->setInt32(kKeyHFR, hfr);
+    outputFormat->setInt32(kKeyFrameRate, frameRate);
+}
+
+bool ExtendedUtils::ShellProp::isAudioDisabled() {
+    bool retVal = false;
+    char disableAudio[PROPERTY_VALUE_MAX];
+    property_get("persist.debug.sf.noaudio", disableAudio, "0");
+    if (atoi(disableAudio) == 1) {
+        retVal = true;
+    }
+    return retVal;
+}
+
+void ExtendedUtils::ShellProp::setEncoderProfile(
+        video_encoder &videoEncoder, int32_t &videoEncoderProfile) {
+    char value[PROPERTY_VALUE_MAX];
+    bool customProfile = false;
+    if (!property_get("encoder.video.profile", value, NULL) > 0) {
+        return;
+    }
+
+    switch (videoEncoder) {
+        case VIDEO_ENCODER_H264:
+            if (strncmp("base", value, 4) == 0) {
+                videoEncoderProfile = OMX_VIDEO_AVCProfileBaseline;
+                ALOGI("H264 Baseline Profile");
+            } else if (strncmp("main", value, 4) == 0) {
+                videoEncoderProfile = OMX_VIDEO_AVCProfileMain;
+                ALOGI("H264 Main Profile");
+            } else if (strncmp("high", value, 4) == 0) {
+                videoEncoderProfile = OMX_VIDEO_AVCProfileHigh;
+                ALOGI("H264 High Profile");
+            } else {
+                ALOGW("Unsupported H264 Profile");
+            }
+            break;
+        case VIDEO_ENCODER_MPEG_4_SP:
+            if (strncmp("simple", value, 5) == 0 ) {
+                videoEncoderProfile = OMX_VIDEO_MPEG4ProfileSimple;
+                ALOGI("MPEG4 Simple profile");
+            } else if (strncmp("asp", value, 3) == 0 ) {
+                videoEncoderProfile = OMX_VIDEO_MPEG4ProfileAdvancedSimple;
+                ALOGI("MPEG4 Advanced Simple Profile");
+            } else {
+                ALOGW("Unsupported MPEG4 Profile");
+            }
+            break;
+        default:
+            ALOGW("No custom profile support for other codecs");
+            break;
+    }
+}
+
+int64_t ExtendedUtils::ShellProp::getMaxAVSyncLateMargin() {
+    char lateMarginMs[PROPERTY_VALUE_MAX] = {0};
+    property_get("media.sf.set.late.margin", lateMarginMs, "0");
+    int64_t newLateMarginUs = atoi(lateMarginMs)*1000;
+    int64_t maxLateMarginUs = newLateMarginUs;
+
+    if (newLateMarginUs > kDefaultAVSyncLateMargin
+            || newLateMarginUs < kDefaultAVSyncLateMargin) {
+        maxLateMarginUs = kDefaultAVSyncLateMargin;
+    }
+
+    ALOGI("AV Sync late margin : Intended=%lldms Using=%lldms",
+            maxLateMarginUs/1000, newLateMarginUs/1000);
+    return maxLateMarginUs;
+}
+
+bool ExtendedUtils::ShellProp::isSmoothStreamingEnabled() {
+    char prop[PROPERTY_VALUE_MAX] = {0};
+    property_get("mm.enable.smoothstreaming", prop, "0");
+    if (!strncmp(prop, "true", 4) || atoi(prop)) {
+        return true;
+    }
+    return false;
+}
+
+void ExtendedUtils::setBFrames(
+        OMX_VIDEO_PARAM_MPEG4TYPE &mpeg4type, int32_t &numBFrames,
+        const char* componentName) {
+    //ignore non QC components
+    if (strncmp(componentName, "OMX.qcom.", 9)) {
+        return;
+    }
+    if (mpeg4type.eProfile > OMX_VIDEO_MPEG4ProfileSimple) {
+        mpeg4type.nAllowedPictureTypes |= OMX_VIDEO_PictureTypeB;
+        mpeg4type.nBFrames = 1;
+        mpeg4type.nPFrames /= (mpeg4type.nBFrames + 1);
+        numBFrames = mpeg4type.nBFrames;
+    }
+    return;
+}
+
+void ExtendedUtils::setBFrames(
+        OMX_VIDEO_PARAM_AVCTYPE &h264type, int32_t &numBFrames,
+        int32_t iFramesInterval, int32_t frameRate, const char* componentName) {
+    //ignore non QC components
+    if (strncmp(componentName, "OMX.qcom.", 9)) {
+        return;
+    }
+    OMX_U32 val = 0;
+    if (iFramesInterval < 0) {
+        val =  0xFFFFFFFF;
+    } else if (iFramesInterval == 0) {
+        val = 0;
+    } else {
+        val  = frameRate * iFramesInterval - 1;
+        CHECK(val > 1);
+    }
+
+    h264type.nPFrames = val;
+
+    if (h264type.nPFrames == 0) {
+        h264type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI;
+    }
+
+    if (h264type.eProfile > OMX_VIDEO_AVCProfileBaseline) {
+        h264type.nAllowedPictureTypes |= OMX_VIDEO_PictureTypeB;
+        h264type.nBFrames = 1;
+        h264type.nPFrames /= (h264type.nBFrames + 1);
+        //enable CABAC as default entropy mode for Hihg/Main profiles
+        h264type.bEntropyCodingCABAC = OMX_TRUE;
+        h264type.nCabacInitIdc = 0;
+        numBFrames = h264type.nBFrames;
+    }
+    return;
+}
+
+/*
+QCOM HW AAC encoder allowed bitrates
+------------------------------------------------------------------------------------------------------------------
+Bitrate limit |AAC-LC(Mono)           | AAC-LC(Stereo)        |AAC+(Mono)            | AAC+(Stereo)            | eAAC+                      |
+Minimum     |Min(24000,0.5 * f_s)   |Min(24000,f_s)           | 24000                      |24000                        |  24000                       |
+Maximum    |Min(192000,6 * f_s)    |Min(192000,12 * f_s)  | Min(192000,6 * f_s)  | Min(192000,12 * f_s)  |  Min(192000,12 * f_s) |
+------------------------------------------------------------------------------------------------------------------
+*/
+bool ExtendedUtils::UseQCHWAACEncoder(audio_encoder Encoder,int32_t Channel,int32_t BitRate,int32_t SampleRate)
+{
+    bool ret = false;
+    int minBiteRate = -1;
+    int maxBiteRate = -1;
+    char propValue[PROPERTY_VALUE_MAX] = {0};
+
+    property_get("qcom.hw.aac.encoder",propValue,NULL);
+    if (!strncmp(propValue,"true",sizeof("true"))) {
+        //check for QCOM's HW AAC encoder only when qcom.aac.encoder =  true;
+        ALOGV("qcom.aac.encoder enabled, check AAC encoder(%d) allowed bitrates",Encoder);
+        switch (Encoder) {
+        case AUDIO_ENCODER_AAC:// for AAC-LC format
+            if (Channel == 1) {//mono
+                minBiteRate = MIN_BITERATE_AAC<(SampleRate/2)?MIN_BITERATE_AAC:(SampleRate/2);
+                maxBiteRate = MAX_BITERATE_AAC<(SampleRate*6)?MAX_BITERATE_AAC:(SampleRate*6);
+            } else if (Channel == 2) {//stereo
+                minBiteRate = MIN_BITERATE_AAC<SampleRate?MIN_BITERATE_AAC:SampleRate;
+                maxBiteRate = MAX_BITERATE_AAC<(SampleRate*12)?MAX_BITERATE_AAC:(SampleRate*12);
+            }
+            break;
+        case AUDIO_ENCODER_HE_AAC:// for AAC+ format
+            if (Channel == 1) {//mono
+                minBiteRate = MIN_BITERATE_AAC;
+                maxBiteRate = MAX_BITERATE_AAC<(SampleRate*6)?MAX_BITERATE_AAC:(SampleRate*6);
+            } else if (Channel == 2) {//stereo
+                minBiteRate = MIN_BITERATE_AAC;
+                maxBiteRate = MAX_BITERATE_AAC<(SampleRate*12)?MAX_BITERATE_AAC:(SampleRate*12);
+            }
+            break;
+        default:
+            ALOGV("encoder:%d not supported by QCOM HW AAC encoder",Encoder);
+
+        }
+
+        //return true only when 1. minBiteRate and maxBiteRate are updated(not -1) 2. minBiteRate <= SampleRate <= maxBiteRate
+        if (SampleRate >= minBiteRate && SampleRate <= maxBiteRate) {
+            ret = true;
+        }
+    }
+
+    return ret;
+}
+
+
+//- returns NULL if we dont really need a new extractor (or cannot),
+//  valid extractor is returned otherwise
+//- caller needs to check for NULL
+//  ----------------------------------------
+//  defaultExt - the existing extractor
+//  source - file source
+//  mime - container mime
+//  ----------------------------------------
+//  Note: defaultExt will be deleted in this function if the new parser is selected
+
+sp<MediaExtractor> ExtendedUtils::MediaExtractor_CreateIfNeeded(sp<MediaExtractor> defaultExt,
+                                                            const sp<DataSource> &source,
+                                                            const char *mime) {
+    bool bCheckExtendedExtractor = false;
+    bool videoTrackFound         = false;
+    bool audioTrackFound         = false;
+    bool amrwbAudio              = false;
+    int  numOfTrack              = 0;
+
+    if (defaultExt != NULL) {
+        for (size_t trackItt = 0; trackItt < defaultExt->countTracks(); ++trackItt) {
+            ++numOfTrack;
+            sp<MetaData> meta = defaultExt->getTrackMetaData(trackItt);
+            const char *_mime;
+            CHECK(meta->findCString(kKeyMIMEType, &_mime));
+
+            String8 mime = String8(_mime);
+
+            if (!strncasecmp(mime.string(), "audio/", 6)) {
+                audioTrackFound = true;
+
+                amrwbAudio = !strncasecmp(mime.string(),
+                                          MEDIA_MIMETYPE_AUDIO_AMR_WB,
+                                          strlen(MEDIA_MIMETYPE_AUDIO_AMR_WB));
+                if (amrwbAudio) {
+                    break;
+                }
+            }else if(!strncasecmp(mime.string(), "video/", 6)) {
+                videoTrackFound = true;
+            }
+        }
+
+        if(amrwbAudio) {
+            bCheckExtendedExtractor = true;
+        }else if (numOfTrack  == 0) {
+            bCheckExtendedExtractor = true;
+        } else if(numOfTrack == 1) {
+            if((videoTrackFound) ||
+                (!videoTrackFound && !audioTrackFound)){
+                bCheckExtendedExtractor = true;
+            }
+        } else if (numOfTrack >= 2){
+            if(videoTrackFound && audioTrackFound) {
+                if(amrwbAudio) {
+                    bCheckExtendedExtractor = true;
+                }
+            } else {
+                bCheckExtendedExtractor = true;
+            }
+        }
+    } else {
+        bCheckExtendedExtractor = true;
+    }
+
+    if (!bCheckExtendedExtractor) {
+        ALOGD("extended extractor not needed, return default");
+        return defaultExt;
+    }
+
+    //Create Extended Extractor only if default extractor is not selected
+    ALOGD("Try creating ExtendedExtractor");
+    sp<MediaExtractor>  retExtExtractor = ExtendedExtractor::Create(source, mime);
+
+    if (retExtExtractor == NULL) {
+        ALOGD("Couldn't create the extended extractor, return default one");
+        return defaultExt;
+    }
+
+    if (defaultExt == NULL) {
+        ALOGD("default extractor is NULL, return extended extractor");
+        return retExtExtractor;
+    }
+
+    //bCheckExtendedExtractor is true which means default extractor was found
+    //but we want to give preference to extended extractor based on certain
+    //conditions.
+
+    //needed to prevent a leak in case both extractors are valid
+    //but we still dont want to use the extended one. we need
+    //to delete the new one
+    bool bUseDefaultExtractor = true;
+
+    for (size_t trackItt = 0; (trackItt < retExtExtractor->countTracks()); ++trackItt) {
+        sp<MetaData> meta = retExtExtractor->getTrackMetaData(trackItt);
+        const char *mime;
+        bool success = meta->findCString(kKeyMIMEType, &mime);
+        if ((success == true) &&
+            (!strncasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_WB_PLUS,
+                                strlen(MEDIA_MIMETYPE_AUDIO_AMR_WB_PLUS)) ||
+             !strncasecmp(mime, MEDIA_MIMETYPE_VIDEO_HEVC,
+                                strlen(MEDIA_MIMETYPE_VIDEO_HEVC)) )) {
+
+            ALOGD("Discarding default extractor and using the extended one");
+            bUseDefaultExtractor = false;
+            break;
+        }
+    }
+
+    if (bUseDefaultExtractor) {
+        ALOGD("using default extractor inspite of having a new extractor");
+        retExtExtractor.clear();
+        return defaultExt;
+    } else {
+        defaultExt.clear();
+        return retExtExtractor;
+    }
+
+}
+
+
+void ExtendedUtils::helper_addMediaCodec(Vector<MediaCodecList::CodecInfo> &mCodecInfos,
+                                          KeyedVector<AString, size_t> &mTypes,
+                                          bool encoder, const char *name,
+                                          const char *type, uint32_t quirks) {
+    mCodecInfos.push();
+    MediaCodecList::CodecInfo *info = &mCodecInfos.editItemAt(mCodecInfos.size() - 1);
+    info->mName = name;
+    info->mIsEncoder = encoder;
+    ssize_t index = mTypes.indexOfKey(type);
+    uint32_t bit = mTypes.valueAt(index);
+    info->mTypes |= 1ul << bit;
+    info->mQuirks = quirks;
+}
+
+uint32_t ExtendedUtils::helper_getCodecSpecificQuirks(KeyedVector<AString, size_t> &mCodecQuirks,
+                                                       Vector<AString> quirks) {
+    size_t i = 0, numQuirks = quirks.size();
+    uint32_t bit = 0, value = 0;
+    for (i = 0; i < numQuirks; i++)
+    {
+        ssize_t index = mCodecQuirks.indexOfKey(quirks.itemAt(i));
+        bit = mCodecQuirks.valueAt(index);
+        value |= 1ul << bit;
+    }
+    return value;
+}
+
+bool ExtendedUtils::isAVCProfileSupported(int32_t  profile){
+   if(profile == OMX_VIDEO_AVCProfileMain || profile == OMX_VIDEO_AVCProfileHigh || profile == OMX_VIDEO_AVCProfileBaseline){
+      return true;
+   } else {
+      return false;
+   }
+}
+
+void ExtendedUtils::updateNativeWindowBufferGeometry(ANativeWindow* anw,
+        OMX_U32 width, OMX_U32 height, OMX_COLOR_FORMATTYPE colorFormat) {
+#if UPDATE_BUFFER_GEOMETRY_AVAILABLE
+    if (anw != NULL) {
+        ALOGI("Calling native window update buffer geometry [%lu x %lu]",
+                width, height);
+        status_t err = anw->perform(
+                anw, NATIVE_WINDOW_UPDATE_BUFFERS_GEOMETRY,
+                width, height, colorFormat);
+        if (err != OK) {
+            ALOGE("UPDATE_BUFFER_GEOMETRY failed %d", err);
+        }
+    }
+#endif
+}
+
+bool ExtendedUtils::checkIsThumbNailMode(const uint32_t flags, char* componentName) {
+    bool isInThumbnailMode = false;
+    if ((flags & OMXCodec::kClientNeedsFramebuffer) && !strncmp(componentName, "OMX.qcom.", 9)) {
+        isInThumbnailMode = true;
+    }
+    return isInThumbnailMode;
+}
+
+void ExtendedUtils::setArbitraryModeIfInterlaced(
+        const uint8_t *ptr, const sp<MetaData> &meta) {
+
+    if (ptr == NULL) {
+        return;
+    }
+    uint16_t spsSize = (((uint16_t)ptr[6]) << 8) + (uint16_t)(ptr[7]);
+    int32_t width = 0, height = 0, isInterlaced = 0;
+    const uint8_t *spsStart = &ptr[8];
+
+    sp<ABuffer> seqParamSet = new ABuffer(spsSize);
+    memcpy(seqParamSet->data(), spsStart, spsSize);
+    FindAVCDimensions(seqParamSet, &width, &height, NULL, NULL, &isInterlaced);
+
+    ALOGV("height is %d, width is %d, isInterlaced is %d\n", height, width, isInterlaced);
+    if (isInterlaced) {
+        meta->setInt32(kKeyUseArbitraryMode, 1);
+        meta->setInt32(kKeyInterlace, 1);
+    }
+    return;
+}
+
+int32_t ExtendedUtils::checkIsInterlace(sp<MetaData> &meta) {
+    int32_t isInterlaceFormat = 0;
+
+    if(meta->findInt32(kKeyInterlace, &isInterlaceFormat)) {
+        ALOGI("interlace format detected");
+    }
+
+    return isInterlaceFormat;
+}
+
+}
+#else //ENABLE_AV_ENHANCEMENTS
+
+namespace android {
+
+void ExtendedUtils::HFR::setHFRIfEnabled(
+        const CameraParameters& params, sp<MetaData> &meta) {
+}
+
+status_t ExtendedUtils::HFR::reCalculateFileDuration(
+        sp<MetaData> &meta, sp<MetaData> &enc_meta,
+        int64_t &maxFileDurationUs, int32_t frameRate,
+        video_encoder videoEncoder) {
+    return OK;
+}
+
+void ExtendedUtils::HFR::reCalculateTimeStamp(
+        sp<MetaData> &meta, int64_t &timestampUs) {
+}
+
+void ExtendedUtils::HFR::reCalculateHFRParams(
+        const sp<MetaData> &meta, int32_t &frameRate,
+        int32_t &bitrate) {
+}
+
+void ExtendedUtils::HFR::copyHFRParams(
+        const sp<MetaData> &inputFormat,
+        sp<MetaData> &outputFormat) {
+}
+
+bool ExtendedUtils::ShellProp::isAudioDisabled() {
+    return false;
+}
+
+void ExtendedUtils::ShellProp::setEncoderProfile(
+        video_encoder &videoEncoder, int32_t &videoEncoderProfile) {
+}
+
+int64_t ExtendedUtils::ShellProp::getMaxAVSyncLateMargin() {
+     return kDefaultAVSyncLateMargin;
+}
+
+bool ExtendedUtils::ShellProp::isSmoothStreamingEnabled() {
+    return false;
+}
+
+void ExtendedUtils::setBFrames(
+        OMX_VIDEO_PARAM_MPEG4TYPE &mpeg4type, int32_t &numBFrames,
+        const char* componentName) {
+}
+
+void ExtendedUtils::setBFrames(
+        OMX_VIDEO_PARAM_AVCTYPE &h264type, int32_t &numBFrames,
+        int32_t iFramesInterval, int32_t frameRate,
+        const char* componentName) {
+}
+
+bool ExtendedUtils::UseQCHWAACEncoder(audio_encoder Encoder,int32_t Channel,
+    int32_t BitRate,int32_t SampleRate) {
+    return false;
+}
+
+sp<MediaExtractor> ExtendedUtils::MediaExtractor_CreateIfNeeded(sp<MediaExtractor> defaultExt,
+                                                            const sp<DataSource> &source,
+                                                            const char *mime) {
+                   return defaultExt;
+}
+
+void ExtendedUtils::helper_addMediaCodec(Vector<MediaCodecList::CodecInfo> &mCodecInfos,
+                                          KeyedVector<AString, size_t> &mTypes,
+                                          bool encoder, const char *name,
+                                          const char *type, uint32_t quirks) {
+}
+
+uint32_t ExtendedUtils::helper_getCodecSpecificQuirks(KeyedVector<AString, size_t> &mCodecQuirks,
+                                                       Vector<AString> quirks) {
+    return 0;
+}
+
+bool ExtendedUtils::isAVCProfileSupported(int32_t  profile){
+     return false;
+}
+
+void ExtendedUtils::updateNativeWindowBufferGeometry(ANativeWindow* anw,
+        OMX_U32 width, OMX_U32 height, OMX_COLOR_FORMATTYPE colorFormat) {
+}
+
+bool ExtendedUtils::checkIsThumbNailMode(const uint32_t flags, char* componentName) {
+    return false;
+}
+
+void ExtendedUtils::setArbitraryModeIfInterlaced(
+        const uint8_t *ptr, const sp<MetaData> &meta) {
+}
+
+int32_t ExtendedUtils::checkIsInterlace(sp<MetaData> &meta) {
+    return false;
+}
+
+}
+#endif //ENABLE_AV_ENHANCEMENTS
diff --git a/media/libstagefright/ExtendedWriter.cpp b/media/libstagefright/ExtendedWriter.cpp
new file mode 100644
index 0000000..db5bb4a
--- /dev/null
+++ b/media/libstagefright/ExtendedWriter.cpp
@@ -0,0 +1,390 @@
+/*
+ * Copyright (c) 2012 - 2013, The Linux Foundation. All rights reserved.
+ *
+ * Not a Contribution.
+ *
+ * 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 <media/stagefright/ExtendedWriter.h>
+#include <media/stagefright/MediaBuffer.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MediaErrors.h>
+#include <media/stagefright/MediaSource.h>
+#include <media/stagefright/MetaData.h>
+#include <media/mediarecorder.h>
+#include <system/audio.h>
+
+#include <sys/prctl.h>
+#include <sys/resource.h>
+
+#include <arpa/inet.h>
+#include <QCMediaDefs.h>
+
+#undef LOG_TAG
+#define LOG_TAG "ExtendedWriter"
+
+namespace android {
+
+ExtendedWriter::ExtendedWriter(const char *filename)
+    : mFile(fopen(filename, "wb")),
+      mInitCheck(mFile != NULL ? OK : NO_INIT),
+      mStarted(false),
+      mPaused(false),
+      mResumed(false),
+      mOffset(0) {
+}
+
+ExtendedWriter::ExtendedWriter(int fd)
+    : mFile(fdopen(fd, "wb")),
+      mInitCheck(mFile != NULL ? OK : NO_INIT),
+      mStarted(false),
+      mPaused(false),
+      mResumed(false),
+      mOffset(0) {
+}
+
+ExtendedWriter::~ExtendedWriter() {
+    if (mStarted) {
+        stop();
+    }
+
+    if (mFile != NULL) {
+        fclose(mFile);
+        mFile = NULL;
+    }
+}
+
+status_t ExtendedWriter::initCheck() const {
+    return mInitCheck;
+}
+
+status_t ExtendedWriter::addSource(const sp<MediaSource> &source) {
+    if (mInitCheck != OK) {
+        ALOGE("Init Check not OK, return");
+        return mInitCheck;
+    }
+
+    if (mSource != NULL) {
+        ALOGE("A source already exists, return");
+        return UNKNOWN_ERROR;
+    }
+
+    sp<MetaData> meta = source->getFormat();
+
+    const char *mime;
+    CHECK(meta->findCString(kKeyMIMEType, &mime));
+
+    if ( !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_QCELP)) {
+        mFormat = AUDIO_FORMAT_QCELP;
+    } else if ( !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_EVRC)) {
+        mFormat = AUDIO_FORMAT_EVRC;
+    }
+    else {
+        return UNKNOWN_ERROR;
+    }
+
+    int32_t channelCount;
+    int32_t sampleRate;
+    CHECK(meta->findInt32(kKeyChannelCount, &channelCount));
+    CHECK_EQ(channelCount, 1);
+    CHECK(meta->findInt32(kKeySampleRate, &sampleRate));
+    CHECK_EQ(sampleRate, 8000);
+
+    mSource = source;
+
+    return OK;
+}
+
+status_t ExtendedWriter::start(MetaData *params) {
+    if (mInitCheck != OK) {
+        ALOGE("Init Check not OK, return");
+        return mInitCheck;
+    }
+
+    if (mSource == NULL) {
+        ALOGE("NULL Source");
+        return UNKNOWN_ERROR;
+    }
+
+    if (mStarted && mPaused) {
+        mPaused = false;
+        mResumed = true;
+        return OK;
+    } else if (mStarted) {
+        ALOGE("Already startd, return");
+        return OK;
+    }
+
+    //space for header;
+    size_t headerSize = sizeof( struct QCPEVRCHeader );
+    uint8_t * header = (uint8_t *)malloc(headerSize);
+    memset( header, '?', headerSize);
+    fwrite( header, 1, headerSize, mFile );
+    mOffset += headerSize;
+    delete header;
+
+    status_t err = mSource->start();
+
+    if (err != OK) {
+        return err;
+    }
+
+    pthread_attr_t attr;
+    pthread_attr_init(&attr);
+    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
+
+    mReachedEOS = false;
+    mDone = false;
+
+    pthread_create(&mThread, &attr, ThreadWrapper, this);
+    pthread_attr_destroy(&attr);
+
+    mStarted = true;
+
+    return OK;
+}
+
+status_t ExtendedWriter::pause() {
+    if (!mStarted) {
+        return OK;
+    }
+    mPaused = true;
+    return OK;
+}
+
+status_t ExtendedWriter::stop() {
+    if (!mStarted) {
+        return OK;
+    }
+
+    mDone = true;
+
+    void *dummy;
+    pthread_join(mThread, &dummy);
+
+    status_t err = (status_t) dummy;
+    {
+        status_t status = mSource->stop();
+        if (err == OK &&
+            (status != OK && status != ERROR_END_OF_STREAM)) {
+            err = status;
+        }
+    }
+
+    mStarted = false;
+    return err;
+}
+
+bool ExtendedWriter::exceedsFileSizeLimit() {
+    if (mMaxFileSizeLimitBytes == 0) {
+        return false;
+    }
+    return mEstimatedSizeBytes >= mMaxFileSizeLimitBytes;
+}
+
+bool ExtendedWriter::exceedsFileDurationLimit() {
+    if (mMaxFileDurationLimitUs == 0) {
+        return false;
+    }
+    return mEstimatedDurationUs >= mMaxFileDurationLimitUs;
+}
+
+// static
+void *ExtendedWriter::ThreadWrapper(void *me) {
+    return (void *) static_cast<ExtendedWriter *>(me)->threadFunc();
+}
+
+status_t ExtendedWriter::threadFunc() {
+    mEstimatedDurationUs = 0;
+    mEstimatedSizeBytes = 0;
+    bool stoppedPrematurely = true;
+    int64_t previousPausedDurationUs = 0;
+    int64_t maxTimestampUs = 0;
+    status_t err = OK;
+
+    pid_t tid  = gettid();
+    androidSetThreadPriority(tid, ANDROID_PRIORITY_AUDIO);
+    prctl(PR_SET_NAME, (unsigned long)"ExtendedWriter", 0, 0, 0);
+    while (!mDone) {
+        MediaBuffer *buffer;
+        err = mSource->read(&buffer);
+
+        if (err != OK) {
+            break;
+        }
+
+        if (mPaused) {
+            buffer->release();
+            buffer = NULL;
+            continue;
+        }
+
+        mEstimatedSizeBytes += buffer->range_length();
+        if (exceedsFileSizeLimit()) {
+            buffer->release();
+            buffer = NULL;
+            notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED, 0);
+            break;
+        }
+
+        int64_t timestampUs;
+        CHECK(buffer->meta_data()->findInt64(kKeyTime, &timestampUs));
+        if (timestampUs > mEstimatedDurationUs) {
+            mEstimatedDurationUs = timestampUs;
+        }
+        if (mResumed) {
+            previousPausedDurationUs += (timestampUs - maxTimestampUs - 20000);
+            mResumed = false;
+        }
+        timestampUs -= previousPausedDurationUs;
+        ALOGV("time stamp: %lld, previous paused duration: %lld",
+                timestampUs, previousPausedDurationUs);
+        if (timestampUs > maxTimestampUs) {
+            maxTimestampUs = timestampUs;
+        }
+
+        if (exceedsFileDurationLimit()) {
+            buffer->release();
+            buffer = NULL;
+            notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_DURATION_REACHED, 0);
+            break;
+        }
+        ssize_t n = fwrite(
+                (const uint8_t *)buffer->data() + buffer->range_offset(),
+                1,
+                buffer->range_length(),
+                mFile);
+        mOffset += n;
+
+        if (n < (ssize_t)buffer->range_length()) {
+            buffer->release();
+            buffer = NULL;
+
+            break;
+        }
+
+        // XXX: How to tell it is stopped prematurely?
+        if (stoppedPrematurely) {
+            stoppedPrematurely = false;
+        }
+
+        buffer->release();
+        buffer = NULL;
+    }
+
+    if (stoppedPrematurely) {
+        notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_TRACK_INFO_COMPLETION_STATUS, UNKNOWN_ERROR);
+    }
+
+    if ( mFormat == AUDIO_FORMAT_QCELP ) {
+        writeQCPHeader( );
+    }
+    else if ( mFormat == AUDIO_FORMAT_EVRC ) {
+        writeEVRCHeader( );
+    }
+
+    fflush(mFile);
+    fclose(mFile);
+    mFile = NULL;
+    mReachedEOS = true;
+    if (err == ERROR_END_OF_STREAM || (err == -ETIMEDOUT)) {
+        return OK;
+    }
+    return err;
+}
+
+bool ExtendedWriter::reachedEOS() {
+    return mReachedEOS;
+}
+
+status_t ExtendedWriter::writeQCPHeader() {
+    /* Common part */
+    struct QCPEVRCHeader header = {
+        {'R', 'I', 'F', 'F'}, 0, {'Q', 'L', 'C', 'M'}, /* Riff */
+        {'f', 'm', 't', ' '}, 150, 1, 0, 0, 0, 0,{0}, 0, {0},0,0,160,8000,16,0,{0},{0},{0}, /* Fmt */
+        {'v','r','a','t'}, 0, 0, 0, /* Vrat */
+        {'d','a','t','a'},0 /* Data */
+    };
+
+    fseeko(mFile, 0, SEEK_SET);
+    header.s_riff = (mOffset - 8);
+    header.data1 = (0x5E7F6D41);
+    header.data2 = (0xB115);
+    header.data3 = (0x11D0);
+    header.data4[0] = 0xBA;
+    header.data4[1] = 0x91;
+    header.data4[2] = 0x00;
+    header.data4[3] = 0x80;
+    header.data4[4] = 0x5F;
+    header.data4[5] = 0xB4;
+    header.data4[6] = 0xB9;
+    header.data4[7] = 0x7E;
+    header.ver = (0x0002);
+    memcpy(header.name, "Qcelp 13K", 9);
+    header.abps = (13000);
+    header.bytes_per_pkt = (35);
+    header.vr_num_of_rates = 5;
+    header.vr_bytes_per_pkt[0] = (0x0422);
+    header.vr_bytes_per_pkt[1] = (0x0310);
+    header.vr_bytes_per_pkt[2] = (0x0207);
+    header.vr_bytes_per_pkt[3] = (0x0103);
+    header.s_vrat = (0x00000008);
+    header.v_rate = (0x00000001);
+    header.size_in_pkts = (mOffset - sizeof( struct QCPEVRCHeader ))/ header.bytes_per_pkt;
+    header.s_data = mOffset - sizeof( struct QCPEVRCHeader );
+    fwrite( &header, 1, sizeof( struct QCPEVRCHeader ), mFile );
+    return OK;
+}
+
+status_t ExtendedWriter::writeEVRCHeader() {
+    /* Common part */
+    struct QCPEVRCHeader header = {
+        {'R', 'I', 'F', 'F'}, 0, {'Q', 'L', 'C', 'M'}, /* Riff */
+        {'f', 'm', 't', ' '}, 150, 1, 0, 0, 0, 0,{0}, 0, {0},0,0,160,8000,16,0,{0},{0},{0}, /* Fmt */
+        {'v','r','a','t'}, 0, 0, 0, /* Vrat */
+        {'d','a','t','a'},0 /* Data */
+    };
+
+    fseeko(mFile, 0, SEEK_SET);
+    header.s_riff = (mOffset - 8);
+    header.data1 = (0xe689d48d);
+    header.data2 = (0x9076);
+    header.data3 = (0x46b5);
+    header.data4[0] = 0x91;
+    header.data4[1] = 0xef;
+    header.data4[2] = 0x73;
+    header.data4[3] = 0x6a;
+    header.data4[4] = 0x51;
+    header.data4[5] = 0x00;
+    header.data4[6] = 0xce;
+    header.data4[7] = 0xb4;
+    header.ver = (0x0001);
+    memcpy(header.name, "TIA IS-127 Enhanced Variable Rate Codec, Speech Service Option 3", 64);
+    header.abps = (9600);
+    header.bytes_per_pkt = (23);
+    header.vr_num_of_rates = 4;
+    header.vr_bytes_per_pkt[0] = (0x0416);
+    header.vr_bytes_per_pkt[1] = (0x030a);
+    header.vr_bytes_per_pkt[2] = (0x0200);
+    header.vr_bytes_per_pkt[3] = (0x0102);
+    header.s_vrat = (0x00000008);
+    header.v_rate = (0x00000001);
+    header.size_in_pkts = (mOffset - sizeof( struct QCPEVRCHeader )) / header.bytes_per_pkt;
+    header.s_data = mOffset - sizeof( struct QCPEVRCHeader );
+    fwrite( &header, 1, sizeof( struct QCPEVRCHeader ), mFile );
+    return OK;
+}
+
+
+}  // namespace android
diff --git a/media/libstagefright/FLACExtractor.cpp b/media/libstagefright/FLACExtractor.cpp
index 098fcf9..1fb58c1 100644
--- a/media/libstagefright/FLACExtractor.cpp
+++ b/media/libstagefright/FLACExtractor.cpp
@@ -822,12 +822,14 @@
 {
     // first 4 is the signature word
     // second 4 is the sizeof STREAMINFO
+    // 1st bit of 2nd 4 bytes represent whether last block of metadata or not
     // 042 is the mandatory STREAMINFO
     // no need to read rest of the header, as a premature EOF will be caught later
     uint8_t header[4+4];
     if (source->readAt(0, header, sizeof(header)) != sizeof(header)
-            || memcmp("fLaC\0\0\0\042", header, 4+4))
-    {
+            || memcmp("fLaC", header, 4)
+            || !(header[4] == 0x80 || header[4] == 0x00)
+            || memcmp("\0\0\042", header + 5, 3))    {
         return false;
     }
 
diff --git a/media/libstagefright/LPAPlayer.cpp b/media/libstagefright/LPAPlayer.cpp
new file mode 100755
index 0000000..9941313
--- /dev/null
+++ b/media/libstagefright/LPAPlayer.cpp
@@ -0,0 +1,841 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ * Copyright (c) 2009-2013, 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
+ *
+ *      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_NDEBUG 0
+#define LOG_TAG "LPAPlayer"
+
+#include <utils/Log.h>
+#include <utils/threads.h>
+
+#include <signal.h>
+#include <sys/prctl.h>
+#include <sys/resource.h>
+#include <sys/poll.h>
+#include <sys/eventfd.h>
+#include <binder/IPCThreadState.h>
+#include <media/AudioTrack.h>
+
+#include <media/stagefright/LPAPlayerLegacy.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/ALooper.h>
+#include <media/stagefright/MediaErrors.h>
+#include <media/stagefright/MediaSource.h>
+#include <media/stagefright/MetaData.h>
+#include <media/stagefright/MediaErrors.h>
+
+#include <hardware_legacy/power.h>
+
+#include <linux/unistd.h>
+
+#include "include/AwesomePlayer.h"
+#include <powermanager/PowerManager.h>
+
+static const char   mName[] = "LPAPlayer";
+
+#define MEM_BUFFER_SIZE 524288
+#define MEM_BUFFER_COUNT 2
+
+#define PCM_FORMAT 2
+#define NUM_FDS 2
+namespace android {
+int LPAPlayer::mObjectsAlive = 0;
+bool LPAPlayer::mLpaInProgress = false;
+
+LPAPlayer::LPAPlayer(
+                    const sp<MediaPlayerBase::AudioSink> &audioSink, bool &initCheck,
+                    AwesomePlayer *observer)
+ :AudioPlayer(audioSink,0, observer),
+mPositionTimeMediaUs(-1),
+mPositionTimeRealUs(-1),
+mInternalSeeking(false),
+mStarted(false),
+mA2DPEnabled(false),
+mSampleRate(0),
+mLatencyUs(0),
+mFrameSize(0),
+mNumFramesPlayed(0),
+mNumFramesPlayedSysTimeUs(0),
+mInputBuffer(NULL),
+mSeeking(false),
+mReachedEOS(false),
+mReachedOutputEOS(false),
+mFinalStatus(OK),
+mSeekTimeUs(0),
+mPauseTime(0),
+mIsFirstBuffer(false),
+mFirstBufferResult(OK),
+mFirstBuffer(NULL),
+mAudioSink(audioSink),
+mObserver(observer),
+mTrackType(TRACK_NONE){
+    ALOGV("LPAPlayer::LPAPlayer() ctor");
+    mObjectsAlive++;
+    mLpaInProgress = true;
+    mTimeStarted = 0;
+    mTimePlayed = 0;
+    numChannels =0;
+    mPaused = false;
+    mIsA2DPEnabled = false;
+    mAudioFlinger = NULL;
+    AudioFlingerClient = NULL;
+    /* Initialize Suspend/Resume related variables */
+    mQueue.start();
+    mQueueStarted      = true;
+    mPauseEvent        = new TimedEvent(this, &LPAPlayer::onPauseTimeOut);
+    mPauseEventPending = false;
+    getAudioFlinger();
+    ALOGV("Registering client with AudioFlinger");
+    mAudioFlinger->registerClient(AudioFlingerClient);
+
+    mIsAudioRouted = false;
+
+    initCheck = true;
+
+}
+
+LPAPlayer::~LPAPlayer() {
+    ALOGV("LPAPlayer::~LPAPlayer()");
+    if (mQueueStarted) {
+        mQueue.stop();
+    }
+
+    reset();
+#if 0
+    if (mAudioFlinger != NULL) {
+        mAudioFlinger->deregisterClient(AudioFlingerClient);
+    }
+#endif
+    mObjectsAlive--;
+    mLpaInProgress = false;
+
+}
+
+void LPAPlayer::getAudioFlinger() {
+    Mutex::Autolock _l(AudioFlingerLock);
+
+    if ( mAudioFlinger.get() == 0 ) {
+        sp<IServiceManager> sm = defaultServiceManager();
+        sp<IBinder> binder;
+        do {
+            binder = sm->getService(String16("media.audio_flinger"));
+            if ( binder != 0 )
+                break;
+            ALOGW("AudioFlinger not published, waiting...");
+            usleep(500000); // 0.5 s
+        } while ( true );
+        if ( AudioFlingerClient == NULL ) {
+            AudioFlingerClient = new AudioFlingerLPAdecodeClient(this);
+        }
+
+        binder->linkToDeath(AudioFlingerClient);
+        mAudioFlinger = interface_cast<IAudioFlinger>(binder);
+    }
+    ALOGE_IF(mAudioFlinger==0, "no AudioFlinger!?");
+}
+
+LPAPlayer::AudioFlingerLPAdecodeClient::AudioFlingerLPAdecodeClient(void *obj)
+{
+    ALOGV("LPAPlayer::AudioFlingerLPAdecodeClient::AudioFlingerLPAdecodeClient");
+    pBaseClass = (LPAPlayer*)obj;
+}
+
+void LPAPlayer::AudioFlingerLPAdecodeClient::binderDied(const wp<IBinder>& who) {
+    Mutex::Autolock _l(pBaseClass->AudioFlingerLock);
+
+    pBaseClass->mAudioFlinger.clear();
+    ALOGW("AudioFlinger server died!");
+}
+
+void LPAPlayer::AudioFlingerLPAdecodeClient::ioConfigChanged(int event, audio_io_handle_t ioHandle, const void *param2) {
+    ALOGV("ioConfigChanged() event %d", event);
+
+#if 0
+    if (event != AudioSystem::A2DP_OUTPUT_STATE) {
+        return;
+    }
+
+    switch ( event ) {
+    case AudioSystem::A2DP_OUTPUT_STATE:
+        {
+            ALOGV("ioConfigChanged() A2DP_OUTPUT_STATE iohandle is %d with A2DPEnabled in %d", ioHandle, pBaseClass->mIsA2DPEnabled);
+            if ( -1 == ioHandle ) {
+                if ( pBaseClass->mIsA2DPEnabled ) {
+                    pBaseClass->mIsA2DPEnabled = false;
+                    if (pBaseClass->mStarted) {
+                        pBaseClass->handleA2DPSwitch();
+                    }
+                    ALOGV("ioConfigChanged:: A2DP Disabled");
+                }
+            } else {
+                if ( !pBaseClass->mIsA2DPEnabled ) {
+
+                    pBaseClass->mIsA2DPEnabled = true;
+                    if (pBaseClass->mStarted) {
+                        pBaseClass->handleA2DPSwitch();
+                    }
+
+                    ALOGV("ioConfigChanged:: A2DP Enabled");
+                }
+            }
+        }
+        break;
+    }
+#endif
+    ALOGV("ioConfigChanged Out");
+
+}
+
+void LPAPlayer::handleA2DPSwitch() {
+    pthread_cond_signal(&decoder_cv);
+}
+
+void LPAPlayer::setSource(const sp<MediaSource> &source) {
+    CHECK(mSource == NULL);
+    ALOGV("Setting source from LPA Player");
+    mSource = source;
+}
+
+status_t LPAPlayer::start(bool sourceAlreadyStarted) {
+    CHECK(!mStarted);
+    CHECK(mSource != NULL);
+
+    ALOGV("start: sourceAlreadyStarted %d", sourceAlreadyStarted);
+    //Check if the source is started, start it
+    status_t err;
+    if (!sourceAlreadyStarted) {
+        err = mSource->start();
+
+        if (err != OK) {
+            return err;
+        }
+    }
+
+    //Create decoder and a2dp notification thread and initialize all the
+    //mutexes and coditional variables
+    createThreads();
+    ALOGV("All Threads Created.");
+
+    // We allow an optional INFO_FORMAT_CHANGED at the very beginning
+    // of playback, if there is one, getFormat below will retrieve the
+    // updated format, if there isn't, we'll stash away the valid buffer
+    // of data to be used on the first audio callback.
+
+    CHECK(mFirstBuffer == NULL);
+
+    MediaSource::ReadOptions options;
+    if (mSeeking) {
+        options.setSeekTo(mSeekTimeUs);
+        mSeeking = false;
+    }
+
+    mFirstBufferResult = mSource->read(&mFirstBuffer, &options);
+    if (mFirstBufferResult == INFO_FORMAT_CHANGED) {
+        ALOGV("INFO_FORMAT_CHANGED!!!");
+        CHECK(mFirstBuffer == NULL);
+        mFirstBufferResult = OK;
+        mIsFirstBuffer = false;
+    } else {
+        mIsFirstBuffer = true;
+    }
+
+    sp<MetaData> format = mSource->getFormat();
+    const char *mime;
+
+    bool success = format->findCString(kKeyMIMEType, &mime);
+    CHECK(success);
+    CHECK(!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW));
+
+    success = format->findInt32(kKeySampleRate, &mSampleRate);
+    CHECK(success);
+
+    success = format->findInt32(kKeyChannelCount, &numChannels);
+    CHECK(success);
+
+    if(!format->findInt32(kKeyChannelMask, &mChannelMask)) {
+        // log only when there's a risk of ambiguity of channel mask selection
+        ALOGI_IF(numChannels > 2,
+                "source format didn't specify channel mask, using (%d) channel order", numChannels);
+        mChannelMask = CHANNEL_MASK_USE_CHANNEL_ORDER;
+    }
+
+    err = setupAudioSink();
+
+    if (err != OK) {
+        if (mFirstBuffer != NULL) {
+            mFirstBuffer->release();
+            mFirstBuffer = NULL;
+        }
+
+        if (!sourceAlreadyStarted) {
+            mSource->stop();
+        }
+
+        ALOGE("Opening a routing session failed");
+        return err;
+    }
+
+    mIsAudioRouted = true;
+    mStarted = true;
+    mAudioSink->start();
+    mTimeStarted = nanoseconds_to_microseconds(systemTime(SYSTEM_TIME_MONOTONIC));
+    ALOGV("Waking up decoder thread");
+    pthread_cond_signal(&decoder_cv);
+
+    return OK;
+}
+
+status_t LPAPlayer::seekTo(int64_t time_us) {
+    Mutex::Autolock autoLock(mLock);
+    ALOGV("seekTo: time_us %lld", time_us);
+    if ( mReachedEOS ) {
+        mReachedEOS = false;
+        mReachedOutputEOS = false;
+    }
+    mSeeking = true;
+    mSeekTimeUs = time_us;
+    mTimePlayed = time_us;
+    mTimeStarted = 0;
+    ALOGV("In seekTo(), mSeekTimeUs %lld",mSeekTimeUs);
+    mAudioSink->flush();
+    pthread_cond_signal(&decoder_cv);
+    //TODO: Update the mPauseTime
+    return OK;
+}
+
+void LPAPlayer::pause(bool playPendingSamples) {
+    CHECK(mStarted);
+    if (mPaused) {
+        return;
+    }
+    ALOGV("pause: playPendingSamples %d", playPendingSamples);
+    mPaused = true;
+    if (playPendingSamples) {
+        if (!mIsA2DPEnabled) {
+            if (!mPauseEventPending) {
+                ALOGV("Posting an event for Pause timeout");
+                mQueue.postEventWithDelay(mPauseEvent, LPA_PAUSE_TIMEOUT_USEC);
+                mPauseEventPending = true;
+            }
+            if (mAudioSink.get() != NULL)
+                mAudioSink->pause();
+        }
+        else {
+            if (mAudioSink.get() != NULL)
+                mAudioSink->stop();
+
+        }
+    } else {
+        if (!mIsA2DPEnabled) {
+            if(!mPauseEventPending) {
+                ALOGV("Posting an event for Pause timeout");
+                mQueue.postEventWithDelay(mPauseEvent, LPA_PAUSE_TIMEOUT_USEC);
+                mPauseEventPending = true;
+            }
+            if (mAudioSink.get() != NULL)
+                mAudioSink->pause();
+            } else {
+            if (mAudioSink.get() != NULL) {
+                mAudioSink->pause();
+            }
+        }
+    }
+    if(mTimeStarted != 0) {
+        mTimePlayed += (nanoseconds_to_microseconds(systemTime(SYSTEM_TIME_MONOTONIC)) - mTimeStarted);
+    }
+}
+
+status_t LPAPlayer::resume() {
+    ALOGV("resume: mPaused %d",mPaused);
+    if ( mPaused) {
+        CHECK(mStarted);
+        if (!mIsA2DPEnabled) {
+            if(mPauseEventPending) {
+                ALOGV("Resume(): Cancelling the puaseTimeout event");
+                mPauseEventPending = false;
+                mQueue.cancelEvent(mPauseEvent->eventID());
+            }
+
+        }
+
+        setupAudioSink();
+
+        mPaused = false;
+        mIsAudioRouted = true;
+        mAudioSink->start();
+        mTimeStarted = nanoseconds_to_microseconds(systemTime(SYSTEM_TIME_MONOTONIC));
+        pthread_cond_signal(&decoder_cv);
+    }
+    return NO_ERROR;
+}
+
+//static
+size_t LPAPlayer::AudioSinkCallback(
+        MediaPlayerBase::AudioSink *audioSink,
+        void *buffer, size_t size, void *cookie,
+        MediaPlayerBase::AudioSink::cb_event_t event) {
+    if (buffer == NULL && size == AudioTrack::EVENT_UNDERRUN) {
+        LPAPlayer *me = (LPAPlayer *)cookie;
+        me->mReachedEOS = true;
+        me->mReachedOutputEOS = true;
+        ALOGV("postAudioEOS");
+        me->mObserver->postAudioEOS(0);
+    }
+    return 1;
+}
+
+void LPAPlayer::reset() {
+
+    // Close the audiosink after all the threads exited to make sure
+    ALOGV("Reset called!!!!!");
+    mReachedEOS = true;
+    //TODO: Release Wake lock
+
+    // make sure Decoder thread has exited
+    requestAndWaitForDecoderThreadExit();
+    requestAndWaitForA2DPNotificationThreadExit();
+    if (mIsAudioRouted) {
+        mAudioSink->stop();
+        mAudioSink->close();
+    }
+    mAudioSink.clear();
+    // Make sure to release any buffer we hold onto so that the
+    // source is able to stop().
+    if (mFirstBuffer != NULL) {
+        mFirstBuffer->release();
+        mFirstBuffer = NULL;
+    }
+
+    if (mInputBuffer != NULL) {
+        ALOGV("AudioPlayer releasing input buffer.");
+        mInputBuffer->release();
+        mInputBuffer = NULL;
+    }
+
+    mSource->stop();
+
+    // The following hack is necessary to ensure that the OMX
+    // component is completely released by the time we may try
+    // to instantiate it again.
+    wp<MediaSource> tmp = mSource;
+    mSource.clear();
+    while (tmp.promote() != NULL) {
+        usleep(1000);
+    }
+
+    mPositionTimeMediaUs = -1;
+    mPositionTimeRealUs = -1;
+    mSeeking = false;
+    mReachedEOS = false;
+    mReachedOutputEOS = false;
+    mFinalStatus = OK;
+    mStarted = false;
+}
+
+
+bool LPAPlayer::isSeeking() {
+    Mutex::Autolock autoLock(mLock);
+    return mSeeking;
+}
+
+bool LPAPlayer::reachedEOS(status_t *finalStatus) {
+    *finalStatus = OK;
+    Mutex::Autolock autoLock(mLock);
+    *finalStatus = mFinalStatus;
+    return mReachedOutputEOS;
+}
+
+
+void *LPAPlayer::decoderThreadWrapper(void *me) {
+    static_cast<LPAPlayer *>(me)->decoderThreadEntry();
+    return NULL;
+}
+
+
+void LPAPlayer::decoderThreadEntry() {
+
+    pthread_mutex_lock(&decoder_mutex);
+
+    pid_t tid  = gettid();
+    androidSetThreadPriority(tid, ANDROID_PRIORITY_AUDIO);
+    prctl(PR_SET_NAME, (unsigned long)"LPA DecodeThread", 0, 0, 0);
+
+    ALOGV("decoderThreadEntry wait for signal \n");
+    if (!mStarted) {
+        pthread_cond_wait(&decoder_cv, &decoder_mutex);
+    }
+    ALOGV("decoderThreadEntry ready to work \n");
+    pthread_mutex_unlock(&decoder_mutex);
+    if (killDecoderThread) {
+        return;
+    }
+    void* local_buf = malloc(MEM_BUFFER_SIZE);
+    int bytesWritten = 0;
+    while (!killDecoderThread) {
+
+        setupAudioSink();
+        if (mTimeStarted == 0) {
+            mTimeStarted = nanoseconds_to_microseconds(systemTime(SYSTEM_TIME_MONOTONIC));
+        }
+
+        if (mReachedEOS || mPaused || !mIsAudioRouted || mIsA2DPEnabled) {
+            ALOGD("DecoderThread taking mutex mReachedEOS %d mPaused %d mIsAudioRouted %d mIsA2DPEnabled %d"
+                       , mReachedEOS, mPaused, mIsAudioRouted, mIsA2DPEnabled);
+            pthread_mutex_lock(&decoder_mutex);
+            pthread_cond_wait(&decoder_cv, &decoder_mutex);
+            pthread_mutex_unlock(&decoder_mutex);
+            ALOGD("DecoderThread woken up ");
+            continue;
+        }
+
+        if (!mIsA2DPEnabled) {
+            ALOGV("FillBuffer: MemBuffer size %d", MEM_BUFFER_SIZE);
+            ALOGV("Fillbuffer started");
+            //TODO: Add memset
+            bytesWritten = fillBuffer(local_buf, MEM_BUFFER_SIZE);
+            ALOGV("FillBuffer completed bytesToWrite %d", bytesWritten);
+
+            if(!killDecoderThread) {
+                mAudioSink->write(local_buf, bytesWritten);
+            }
+        }
+    }
+
+    free(local_buf);
+
+    //TODO: Call fillbuffer with different size and write to mAudioSink()
+}
+
+void LPAPlayer::createThreads() {
+
+    //Initialize all the Mutexes and Condition Variables
+    pthread_mutex_init(&decoder_mutex, NULL);
+    pthread_mutex_init(&audio_sink_setup_mutex, NULL);
+    pthread_cond_init (&decoder_cv, NULL);
+
+    // Create 4 threads Effect, decoder, event and A2dp
+    pthread_attr_t attr;
+    pthread_attr_init(&attr);
+    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
+
+    killDecoderThread = false;
+    killA2DPNotificationThread = false;
+
+    decoderThreadAlive = true;
+
+    ALOGV("Creating decoder Thread");
+    pthread_create(&decoderThread, &attr, decoderThreadWrapper, this);
+
+    pthread_attr_destroy(&attr);
+}
+
+size_t LPAPlayer::fillBuffer(void *data, size_t size) {
+
+    if (mReachedEOS) {
+        return 0;
+    }
+
+    bool postSeekComplete = false;
+
+    size_t size_done = 0;
+    size_t size_remaining = size;
+    while (size_remaining > 0) {
+        MediaSource::ReadOptions options;
+
+        {
+            Mutex::Autolock autoLock(mLock);
+
+            if (mSeeking) {
+                mInternalSeeking = false;
+            }
+            if (mSeeking || mInternalSeeking) {
+                if (mIsFirstBuffer) {
+                    if (mFirstBuffer != NULL) {
+                        mFirstBuffer->release();
+                        mFirstBuffer = NULL;
+                    }
+                    mIsFirstBuffer = false;
+                }
+
+                options.setSeekTo(mSeekTimeUs);
+
+                if (mInputBuffer != NULL) {
+                    mInputBuffer->release();
+                    mInputBuffer = NULL;
+                }
+
+                mSeeking = false;
+                if (mObserver && !mInternalSeeking) {
+                    ALOGV("fillBuffer: Posting audio seek complete event");
+                    postSeekComplete = true;
+                }
+                mInternalSeeking = false;
+            }
+        }
+
+        if (mInputBuffer == NULL) {
+            status_t err;
+
+            if (mIsFirstBuffer) {
+                mInputBuffer = mFirstBuffer;
+                mFirstBuffer = NULL;
+                err = mFirstBufferResult;
+
+                mIsFirstBuffer = false;
+            } else {
+                err = mSource->read(&mInputBuffer, &options);
+            }
+
+            CHECK((err == OK && mInputBuffer != NULL)
+                   || (err != OK && mInputBuffer == NULL));
+
+            Mutex::Autolock autoLock(mLock);
+
+            if (err != OK) {
+                mReachedEOS = true;
+                mFinalStatus = err;
+                break;
+            }
+
+            CHECK(mInputBuffer->meta_data()->findInt64(
+                        kKeyTime, &mPositionTimeMediaUs));
+            mFrameSize = mAudioSink->frameSize();
+            mPositionTimeRealUs =
+                ((mNumFramesPlayed + size_done / mFrameSize) * 1000000)
+                    / mSampleRate;
+        }
+        if (mInputBuffer->range_length() == 0) {
+            mInputBuffer->release();
+            mInputBuffer = NULL;
+
+            continue;
+        }
+
+        size_t copy = size_remaining;
+        if (copy > mInputBuffer->range_length()) {
+            copy = mInputBuffer->range_length();
+        }
+
+        memcpy((char *)data + size_done,
+               (const char *)mInputBuffer->data() + mInputBuffer->range_offset(),
+               copy);
+
+        mInputBuffer->set_range(mInputBuffer->range_offset() + copy,
+                                mInputBuffer->range_length() - copy);
+
+        size_done += copy;
+        size_remaining -= copy;
+    }
+
+    if (postSeekComplete) {
+        mObserver->postAudioSeekComplete();
+    }
+
+    return size_done;
+}
+
+int64_t LPAPlayer::getRealTimeUs() {
+    Mutex::Autolock autoLock(mLock);
+    return getRealTimeUsLocked();
+}
+
+
+int64_t LPAPlayer::getRealTimeUsLocked(){
+    //Used for AV sync: irrelevant API for LPA.
+    return 0;
+}
+
+
+int64_t LPAPlayer::getMediaTimeUs() {
+    Mutex::Autolock autoLock(mLock);
+    ALOGV("getMediaTimeUs() mPaused %d mSeekTimeUs %lld", mPaused, mSeekTimeUs);
+    if(mPaused || mTimeStarted == 0) {
+       return mTimePlayed;
+    } else {
+       return nanoseconds_to_microseconds(systemTime(SYSTEM_TIME_MONOTONIC)) - mTimeStarted + mTimePlayed;
+    }
+}
+
+bool LPAPlayer::getMediaTimeMapping(
+                                   int64_t *realtime_us, int64_t *mediatime_us) {
+    Mutex::Autolock autoLock(mLock);
+
+    *realtime_us = mPositionTimeRealUs;
+    *mediatime_us = mPositionTimeMediaUs;
+
+    return mPositionTimeRealUs != -1 && mPositionTimeMediaUs != -1;
+}
+
+void LPAPlayer::requestAndWaitForDecoderThreadExit() {
+
+    if (!decoderThreadAlive)
+        return;
+    killDecoderThread = true;
+    if (mIsAudioRouted)
+        mAudioSink->flush();
+    pthread_cond_signal(&decoder_cv);
+    pthread_join(decoderThread,NULL);
+    ALOGV("decoder thread killed");
+
+}
+
+void LPAPlayer::requestAndWaitForA2DPNotificationThreadExit() {
+    if (!a2dpNotificationThreadAlive)
+        return;
+    killA2DPNotificationThread = true;
+    pthread_cond_signal(&a2dp_notification_cv);
+    pthread_join(A2DPNotificationThread,NULL);
+    ALOGV("a2dp notification thread killed");
+}
+
+void LPAPlayer::onPauseTimeOut() {
+    ALOGV("onPauseTimeOut");
+    if (!mPauseEventPending) {
+        return;
+    }
+    mPauseEventPending = false;
+    if(!mIsA2DPEnabled) {
+        // 1.) Set seek flags
+        mReachedEOS = false;
+        mReachedOutputEOS = false;
+        mSeekTimeUs = mTimePlayed;
+
+        // 2.) Close routing Session
+        mAudioSink->close();
+        mIsAudioRouted = false;
+        mTrackType = TRACK_NONE;
+    }
+}
+
+status_t  LPAPlayer::setupAudioSink()
+{
+    status_t err = NO_ERROR;
+
+    ALOGD("setupAudioSink with A2DP(%d) tracktype(%d)", mIsA2DPEnabled, mTrackType);
+    pthread_mutex_lock(&audio_sink_setup_mutex);
+
+    if(true == mIsA2DPEnabled) {
+        ALOGE("setupAudioSink:dIRECT track --> rEGULAR track");
+
+        if(mTrackType == TRACK_REGULAR) {
+            ALOGD("setupAudioSink:rEGULAR Track already opened");
+            pthread_mutex_unlock(&audio_sink_setup_mutex);
+            return err;
+        }
+
+        if(mTrackType == TRACK_DIRECT) {
+            ALOGD("setupAudioSink:Close dIRECT track");
+            mAudioSink->stop();
+            mAudioSink->close();
+        }
+
+        ALOGD("setupAudioSink:Open rEGULAR track");
+
+        ALOGD("setupAudioSink:mAudiosink->open() mSampleRate %d, numChannels %d, mChannelMask %d, flags %d",
+                mSampleRate, numChannels, mChannelMask, 0);
+
+        err = mAudioSink->open(
+            mSampleRate, numChannels, mChannelMask, AUDIO_FORMAT_PCM_16_BIT,
+            DEFAULT_AUDIOSINK_BUFFERCOUNT,
+            &LPAPlayer::AudioSinkCallback,
+            this,
+            (audio_output_flags_t)0,
+            NULL);
+        if (err != NO_ERROR){
+            ALOGE("setupAudioSink:Audio sink open failed.");
+        }
+
+        ALOGD("setupAudioSink:Start rEGULAR track");
+        mAudioSink->start();
+
+        ALOGD("setupAudioSink:rEGULAR track opened");
+        mTrackType = TRACK_REGULAR;
+
+    } else if (false == mIsA2DPEnabled){
+        ALOGE("setupAudioSink:rEGULAR track --> dIRECT track");
+
+        if(mTrackType == TRACK_DIRECT) {
+            ALOGD("setupAudioSink:Direct Track already opened");
+            pthread_mutex_unlock(&audio_sink_setup_mutex);
+            return err;
+        }
+
+        if(mTrackType == TRACK_REGULAR) {
+            ALOGD("setupAudioSink:Close rEGULAR track");
+            mAudioSink->stop();
+            mAudioSink->close();
+        }
+
+        ALOGD("setupAudioSink:Open dIRECT track");
+
+        ALOGD("setupAudioSink:mAudiosink->open() mSampleRate %d, numChannels %d, mChannelMask %d, flags %d",
+                mSampleRate, numChannels, mChannelMask, (AUDIO_OUTPUT_FLAG_LPA | AUDIO_OUTPUT_FLAG_DIRECT));
+
+        err = mAudioSink->open(
+            mSampleRate, numChannels, mChannelMask, AUDIO_FORMAT_PCM_16_BIT,
+            DEFAULT_AUDIOSINK_BUFFERCOUNT,
+            &LPAPlayer::AudioSinkCallback,
+            this,
+            (audio_output_flags_t)(AUDIO_OUTPUT_FLAG_LPA | AUDIO_OUTPUT_FLAG_DIRECT),
+            NULL);
+        if (err != NO_ERROR){
+            ALOGE("setupAudioSink:Audio sink open failed.");
+        }
+
+        mTrackType = TRACK_DIRECT;
+        ALOGD("setupAudioSink:dIRECT track opened");
+    }
+    pthread_mutex_unlock(&audio_sink_setup_mutex);
+
+    return err;
+
+}
+
+
+size_t LPAPlayer::AudioCallback(
+        MediaPlayerBase::AudioSink *audioSink,
+        void *buffer, size_t size, void *cookie) {
+
+    return (static_cast<LPAPlayer *>(cookie)->AudioCallback(cookie, buffer, size));
+}
+
+size_t LPAPlayer::AudioCallback(void *cookie, void *buffer, size_t size) {
+    size_t size_done = 0;
+    uint32_t numFramesPlayedOut;
+    LPAPlayer *me = (LPAPlayer *)cookie;
+
+    if(me->mReachedOutputEOS)
+        return 0;
+
+    if (buffer == NULL && size == AudioTrack::EVENT_UNDERRUN) {
+        ALOGE("Underrun");
+        return 0;
+     } else {
+        size_done = fillBuffer(buffer, size);
+        ALOGD("RegularTrack:fillbuffersize %d %d", size_done, size);
+        if(mReachedEOS) {
+            me->mReachedOutputEOS = true;
+            me->mObserver->postAudioEOS();
+            ALOGE("postEOSDelayUs ");
+        }
+        return size_done;
+    }
+}
+
+} //namespace android
diff --git a/media/libstagefright/LPAPlayerALSA.cpp b/media/libstagefright/LPAPlayerALSA.cpp
new file mode 100644
index 0000000..b18028c
--- /dev/null
+++ b/media/libstagefright/LPAPlayerALSA.cpp
@@ -0,0 +1,753 @@
+/*
+ * Copyright (c) 2009-2013, The Linux Foundation. All rights reserved.
+ * Not a Contribution.
+ * Copyright (C) 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_NDDEBUG 0
+//#define LOG_NDEBUG 0
+#define LOG_TAG "LPAPlayerALSA"
+
+#include <utils/Log.h>
+#include <utils/threads.h>
+
+#include <signal.h>
+#include <sys/prctl.h>
+#include <binder/IPCThreadState.h>
+#include <media/AudioTrack.h>
+
+#include <media/stagefright/LPAPlayer.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/ALooper.h>
+#include <media/stagefright/MediaErrors.h>
+#include <media/stagefright/MediaSource.h>
+#include <media/stagefright/MetaData.h>
+#include <media/stagefright/MediaErrors.h>
+#include "include/AwesomePlayer.h"
+
+static const char   mName[] = "LPAPlayer";
+
+#define MEM_METADATA_SIZE 64
+#ifndef LPA_DEFAULT_BUFFER_SIZE
+#define LPA_DEFAULT_BUFFER_SIZE 256
+#endif
+#define MEM_BUFFER_SIZE ((LPA_DEFAULT_BUFFER_SIZE*1024) - MEM_METADATA_SIZE)
+#define MEM_BUFFER_COUNT 4
+#define LPA_BUFFER_TIME 1500000
+
+namespace android {
+int LPAPlayer::mObjectsAlive = 0;
+
+LPAPlayer::LPAPlayer(
+                    const sp<MediaPlayerBase::AudioSink> &audioSink, bool &initCheck,
+                    AwesomePlayer *observer)
+:AudioPlayer(audioSink, 0, observer),
+mPositionTimeMediaUs(-1),
+mPositionTimeRealUs(-1),
+mInternalSeeking(false),
+mStarted(false),
+mSampleRate(0),
+mLatencyUs(0),
+mFrameSize(0),
+mNumFramesPlayed(0),
+mNumFramesPlayedSysTimeUs(0),
+mInputBuffer(NULL),
+mSeeking(false),
+mReachedEOS(false),
+mReachedOutputEOS(false),
+mFinalStatus(OK),
+mSeekTimeUs(0),
+mPauseTime(0),
+mIsFirstBuffer(false),
+mFirstBufferResult(OK),
+mFirstBuffer(NULL),
+mAudioSink(audioSink),
+mObserver(observer) {
+    ALOGV("LPAPlayer::LPAPlayer() ctor");
+    mObjectsAlive++;
+    mNumOutputChannels =0;
+    mNumInputChannels = 0;
+    mPaused = false;
+    /* Initialize Suspend/Resume related variables */
+    mQueue.start();
+    mQueueStarted      = true;
+    mPauseEvent        = new TimedEvent(this, &LPAPlayer::onPauseTimeOut);
+    mPauseEventPending = false;
+    ALOGV("Registering client with AudioFlinger");
+
+    mIsAudioRouted = false;
+
+    initCheck = true;
+
+}
+
+LPAPlayer::~LPAPlayer() {
+    ALOGV("LPAPlayer::~LPAPlayer()");
+    if (mQueueStarted) {
+        mQueue.stop();
+    }
+
+    reset();
+
+    mObjectsAlive--;
+}
+
+void LPAPlayer::setSource(const sp<MediaSource> &source) {
+    CHECK(mSource == NULL);
+    ALOGV("Setting source from LPA Player");
+    mSource = source;
+}
+
+status_t LPAPlayer::start(bool sourceAlreadyStarted) {
+    CHECK(!mStarted);
+    CHECK(mSource != NULL);
+
+    ALOGV("start: sourceAlreadyStarted %d", sourceAlreadyStarted);
+    //Check if the source is started, start it
+    status_t err;
+    if (!sourceAlreadyStarted) {
+        err = mSource->start();
+
+        if (err != OK) {
+            return err;
+        }
+    }
+
+    //Create decoder thread and initialize all the
+    //mutexes and coditional variables
+    createThreads();
+    ALOGV("All Threads Created.");
+
+    // We allow an optional INFO_FORMAT_CHANGED at the very beginning
+    // of playback, if there is one, getFormat below will retrieve the
+    // updated format, if there isn't, we'll stash away the valid buffer
+    // of data to be used on the first audio callback.
+
+    CHECK(mFirstBuffer == NULL);
+
+    MediaSource::ReadOptions options;
+    if (mSeeking) {
+        options.setSeekTo(mSeekTimeUs);
+        mSeeking = false;
+    }
+
+    mFirstBufferResult = mSource->read(&mFirstBuffer, &options);
+    if (mFirstBufferResult == INFO_FORMAT_CHANGED) {
+        ALOGV("INFO_FORMAT_CHANGED!!!");
+        CHECK(mFirstBuffer == NULL);
+        mFirstBufferResult = OK;
+        mIsFirstBuffer = false;
+    } else {
+        mIsFirstBuffer = true;
+    }
+
+    sp<MetaData> format = mSource->getFormat();
+    const char *mime;
+
+    bool success = format->findCString(kKeyMIMEType, &mime);
+    CHECK(success);
+    CHECK(!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW));
+
+    success = format->findInt32(kKeySampleRate, &mSampleRate);
+    CHECK(success);
+
+    success = format->findInt32(kKeyChannelCount, &mNumInputChannels);
+    CHECK(success);
+
+    // Always produce stereo output
+    mNumOutputChannels = 2;
+
+    if(!format->findInt32(kKeyChannelMask, &mChannelMask)) {
+        // log only when there's a risk of ambiguity of channel mask selection
+        ALOGI_IF(mNumInputChannels > 2,
+                "source format didn't specify channel mask, using (%d) channel order", mNumInputChannels);
+        mChannelMask = CHANNEL_MASK_USE_CHANNEL_ORDER;
+    }
+    audio_output_flags_t flags = (audio_output_flags_t) (AUDIO_OUTPUT_FLAG_LPA |
+                                                         AUDIO_OUTPUT_FLAG_DIRECT);
+    ALOGV("mAudiosink->open() mSampleRate %d, numOutputChannels %d, mChannelMask %d, flags %d",mSampleRate,
+          mNumOutputChannels, mChannelMask, flags);
+    err = mAudioSink->open(
+        mSampleRate, mNumOutputChannels, mChannelMask, AUDIO_FORMAT_PCM_16_BIT,
+        DEFAULT_AUDIOSINK_BUFFERCOUNT,
+        &LPAPlayer::AudioSinkCallback,
+        this,
+        flags,
+        NULL);
+
+    if (err != OK) {
+        if (mFirstBuffer != NULL) {
+            mFirstBuffer->release();
+            mFirstBuffer = NULL;
+        }
+
+        if (!sourceAlreadyStarted) {
+            mSource->stop();
+        }
+
+        ALOGE("Opening a routing session failed");
+        return err;
+    }
+
+    mIsAudioRouted = true;
+    mStarted = true;
+    mAudioSink->start();
+    ALOGV("Waking up decoder thread");
+    mLock.lock();
+    mDecoderCv.signal();
+    mLock.unlock();
+
+    return OK;
+}
+
+status_t LPAPlayer::seekTo(int64_t time_us) {
+    Mutex::Autolock autoLock(mLock);
+    ALOGV("seekTo: time_us %lld", time_us);
+
+    if (seekTooClose(time_us)) {
+        mLock.unlock();
+        mObserver->postAudioSeekComplete();
+        mLock.lock();
+        return OK;
+    }
+
+    mSeeking = true;
+    mSeekTimeUs = time_us;
+    mPauseTime = mSeekTimeUs;
+    ALOGV("In seekTo(), mSeekTimeUs %lld",mSeekTimeUs);
+
+    if (mIsAudioRouted) {
+        mAudioSink->flush();
+    }
+
+    if (mReachedEOS) {
+        mReachedEOS = false;
+        mReachedOutputEOS = false;
+        if(mPaused == false) {
+            ALOGV("Going to signal decoder thread since playback is already going on ");
+            mDecoderCv.signal();
+            ALOGV("Signalled extractor thread.");
+        }
+    }
+    ALOGV("seek done.");
+    return OK;
+}
+
+void LPAPlayer::pause(bool playPendingSamples) {
+    CHECK(mStarted);
+    if (mPaused) {
+        return;
+    }
+    ALOGV("pause: playPendingSamples %d", playPendingSamples);
+    mPaused = true;
+    if (!mPauseEventPending) {
+        ALOGV("Posting an event for Pause timeout");
+        mQueue.postEventWithDelay(mPauseEvent, LPA_PAUSE_TIMEOUT_USEC);
+        mPauseEventPending = true;
+    }
+    mPauseTime = mSeekTimeUs + getTimeStamp();
+
+    if (mAudioSink.get() != NULL) {
+        ALOGV("AudioSink pause");
+        mAudioSink->pause();
+    }
+}
+
+status_t LPAPlayer::resume() {
+    ALOGV("resume: mPaused %d",mPaused);
+    status_t err = NO_ERROR;
+    Mutex::Autolock autoLock(mLock);
+    if ( mPaused) {
+        CHECK(mStarted);
+        if(mPauseEventPending) {
+            ALOGV("Resume(): Cancelling the puaseTimeout event");
+            mPauseEventPending = false;
+            mQueue.cancelEvent(mPauseEvent->eventID());
+        }
+
+        if (!mIsAudioRouted) {
+            audio_output_flags_t flags = (audio_output_flags_t) (AUDIO_OUTPUT_FLAG_LPA |
+                                                                AUDIO_OUTPUT_FLAG_DIRECT);
+            err = mAudioSink->open(
+                mSampleRate, mNumOutputChannels, mChannelMask, AUDIO_FORMAT_PCM_16_BIT,
+                DEFAULT_AUDIOSINK_BUFFERCOUNT,
+                &LPAPlayer::AudioSinkCallback,
+                this,
+                flags,
+                NULL);
+            if (err != NO_ERROR) {
+                ALOGE("Audio sink open failed.");
+            }
+            mIsAudioRouted = true;
+        }
+        mPaused = false;
+        mAudioSink->start();
+        mDecoderCv.signal();
+
+    }
+    return err;
+}
+
+//static
+size_t LPAPlayer::AudioSinkCallback(
+        MediaPlayerBase::AudioSink *audioSink,
+        void *buffer, size_t size, void *cookie,
+        MediaPlayerBase::AudioSink::cb_event_t event) {
+    if (buffer == NULL && size == AudioTrack::EVENT_UNDERRUN) {
+        LPAPlayer *me = (LPAPlayer *)cookie;
+        if(me->mReachedEOS == true) {
+            //in the case of seek all these flags will be reset
+            me->mReachedOutputEOS = true;
+            ALOGV("postAudioEOS mSeeking %d", me->mSeeking);
+            me->mObserver->postAudioEOS(0);
+        }else {
+            ALOGV("postAudioEOS ignored since %d", me->mSeeking);
+        }
+    }
+    return 1;
+}
+
+void LPAPlayer::reset() {
+    ALOGD("Reset");
+
+    Mutex::Autolock _l(mLock); //to sync w/ onpausetimeout
+
+    //cancel any pending onpause timeout events
+    //doesnt matter if the event is really present or not
+    mPauseEventPending = false;
+    mQueue.cancelEvent(mPauseEvent->eventID());
+
+    // Close the audiosink after all the threads exited to make sure
+    mReachedEOS = true;
+
+    // make sure Decoder thread has exited
+    ALOGD("Closing all the threads");
+    requestAndWaitForDecoderThreadExit_l();
+
+    ALOGD("Close the Sink");
+    if (mIsAudioRouted) {
+        mAudioSink->stop();
+        mAudioSink->close();
+        mAudioSink.clear();
+        mIsAudioRouted = false;
+    }
+    // Make sure to release any buffer we hold onto so that the
+    // source is able to stop().
+    if (mFirstBuffer != NULL) {
+        mFirstBuffer->release();
+        mFirstBuffer = NULL;
+    }
+
+    if (mInputBuffer != NULL) {
+        ALOGV("AudioPlayer releasing input buffer.");
+        mInputBuffer->release();
+        mInputBuffer = NULL;
+    }
+
+    mSource->stop();
+
+    // The following hack is necessary to ensure that the OMX
+    // component is completely released by the time we may try
+    // to instantiate it again.
+    wp<MediaSource> tmp = mSource;
+    mSource.clear();
+    while (tmp.promote() != NULL) {
+        usleep(1000);
+    }
+
+    mPositionTimeMediaUs = -1;
+    mPositionTimeRealUs = -1;
+    mSeeking = false;
+    mReachedEOS = false;
+    mReachedOutputEOS = false;
+    mFinalStatus = OK;
+    mStarted = false;
+}
+
+
+bool LPAPlayer::isSeeking() {
+    Mutex::Autolock autoLock(mLock);
+    return mSeeking;
+}
+
+bool LPAPlayer::reachedEOS(status_t *finalStatus) {
+    *finalStatus = OK;
+    Mutex::Autolock autoLock(mLock);
+    *finalStatus = mFinalStatus;
+    return mReachedOutputEOS;
+}
+
+
+void *LPAPlayer::decoderThreadWrapper(void *me) {
+    static_cast<LPAPlayer *>(me)->decoderThreadEntry();
+    return NULL;
+}
+
+
+void LPAPlayer::decoderThreadEntry() {
+
+    mLock.lock();
+    pid_t tid  = gettid();
+    androidSetThreadPriority(tid, ANDROID_PRIORITY_AUDIO);
+    prctl(PR_SET_NAME, (unsigned long)"LPA DecodeThread", 0, 0, 0);
+
+    ALOGV("mDecoderThreadEntry wait for signal \n");
+    if (!mStarted) {
+        mDecoderCv.wait(mLock);
+    }
+    ALOGV("decoderThreadEntry ready to work \n");
+    mLock.unlock();
+    if (mKillDecoderThread) {
+        return;
+    }
+    void* local_buf = malloc(MEM_BUFFER_SIZE);
+    if(local_buf == (void*) NULL) {
+        mKillDecoderThread = true;
+        ALOGE("Malloc failed");
+        return;
+    }
+    int *lptr = ((int*)local_buf);
+    int bytesWritten = 0;
+
+    if (!local_buf) {
+      ALOGE("Failed to allocate temporary buffer for mDecoderThread");
+      return;
+    }
+
+    bool lSeeking = false;
+    bool lPaused = false;
+
+    while (!mKillDecoderThread) {
+
+        if (mReachedEOS || mPaused || !mIsAudioRouted) {
+            ALOGV("Going to sleep before write since "
+                  "mReachedEOS %d, mPaused %d, mIsAudioRouted %d",
+                  mReachedEOS, mPaused, mIsAudioRouted);
+            mDecoderMutex.lock();
+            mDecoderCv.wait(mDecoderMutex);
+            mDecoderMutex.unlock();
+            ALOGV("Woke up from sleep before write since "
+                  "mReachedEOS %d, mPaused %d, mIsAudioRouted %d",
+                  mReachedEOS, mPaused, mIsAudioRouted);
+            continue;
+        }
+
+        ALOGV("FillBuffer: MemBuffer size %d", MEM_BUFFER_SIZE);
+        ALOGV("Fillbuffer started");
+        if (mNumInputChannels == 1) {
+            bytesWritten = fillBuffer(local_buf, MEM_BUFFER_SIZE/2);
+            CHECK(bytesWritten <= MEM_BUFFER_SIZE/2);
+
+            convertMonoToStereo((int16_t*)local_buf, bytesWritten);
+            bytesWritten *= 2;
+        } else {
+            bytesWritten = fillBuffer(local_buf, MEM_BUFFER_SIZE);
+            CHECK(bytesWritten <= MEM_BUFFER_SIZE);
+        }
+
+        ALOGV("FillBuffer completed bytesToWrite %d", bytesWritten);
+        if(!mKillDecoderThread) {
+            mLock.lock();
+            lPaused = mPaused;
+            mLock.unlock();
+
+            if(lPaused == true) {
+                //write only if player is not in paused state. Sleep on lock
+                // resume is called
+                ALOGV("Going to sleep in decodethreadiwrite since sink is paused");
+                mDecoderMutex.lock();
+                mDecoderCv.wait(mDecoderMutex);
+                ALOGV("Going to unlock n decodethreadwrite since sink "
+                      "resumed mPaused %d, mIsAudioRouted %d, mReachedEOS %d",
+                      mPaused, mIsAudioRouted, mReachedEOS);
+                mDecoderMutex.unlock();
+            }
+            mLock.lock();
+            lSeeking = mSeeking||mInternalSeeking;
+            mLock.unlock();
+
+            if(lSeeking == false && (mKillDecoderThread == false)){
+                //if we are seeking, ignore write, otherwise write
+                ALOGV("Fillbuffer before seeling flag %d", mSeeking);
+                int lWrittenBytes = mAudioSink->write(local_buf, bytesWritten);
+                ALOGV("Fillbuffer after write, written bytes %d and seek flag %d", lWrittenBytes, mSeeking);
+            } else {
+                ALOGV("Fillbuffer ignored since we seeked after fillBuffer was set %d", mSeeking);
+            }
+        }
+    }
+
+    free(local_buf);
+
+    //TODO: Call fillbuffer with different size and write to mAudioSink()
+}
+
+void LPAPlayer::createThreads() {
+
+    // Create 4 threads Effect, decoder, event and A2dp
+    pthread_attr_t attr;
+    pthread_attr_init(&attr);
+    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
+
+    mKillDecoderThread = false;
+
+    mDecoderThreadAlive = true;
+
+    ALOGV("Creating decoder Thread");
+    pthread_create(&mDecoderThread, &attr, decoderThreadWrapper, this);
+
+    pthread_attr_destroy(&attr);
+}
+
+size_t LPAPlayer::fillBuffer(void *data, size_t size) {
+
+    if (mReachedEOS) {
+        return 0;
+    }
+
+    if ((data == (void*) NULL) || size > MEM_BUFFER_SIZE) {
+        ALOGE("fillBuffer given wrong buffer");
+        return 0;
+    }
+
+    bool postSeekComplete = false;
+
+    size_t size_done = 0;
+    size_t size_remaining = size;
+    ALOGV("fillBuffer: Clearing seek flag in fill buffer");
+
+    while (size_remaining > 0) {
+        MediaSource::ReadOptions options;
+
+        {
+            Mutex::Autolock autoLock(mLock);
+
+            if(mSeeking) {
+                mInternalSeeking = false;
+            }
+
+            if (mSeeking || mInternalSeeking) {
+                if (mIsFirstBuffer) {
+                    if (mFirstBuffer != NULL) {
+                        mFirstBuffer->release();
+                        mFirstBuffer = NULL;
+                    }
+                    mIsFirstBuffer = false;
+                }
+
+                options.setSeekTo(mSeekTimeUs);
+
+                if (mInputBuffer != NULL) {
+                    mInputBuffer->release();
+                    mInputBuffer = NULL;
+                }
+
+                // This is to ignore the data already filled in the output buffer
+                size_done = 0;
+                size_remaining = size;
+
+                mSeeking = false;
+                if (mObserver && !mInternalSeeking) {
+                    ALOGV("fillBuffer: Posting audio seek complete event");
+                    postSeekComplete = true;
+                }
+                mInternalSeeking = false;
+                ALOGV("fillBuffer: Setting seek flag in fill buffer");
+            }
+        }
+
+        if (mInputBuffer == NULL) {
+            status_t err;
+
+            if (mIsFirstBuffer) {
+                mInputBuffer = mFirstBuffer;
+                mFirstBuffer = NULL;
+                err = mFirstBufferResult;
+
+                mIsFirstBuffer = false;
+            } else {
+                err = mSource->read(&mInputBuffer, &options);
+            }
+
+            CHECK((err == OK && mInputBuffer != NULL)
+                  || (err != OK && mInputBuffer == NULL));
+            {
+                Mutex::Autolock autoLock(mLock);
+
+                if (err != OK) {
+                    ALOGD("fill buffer - reached eos true");
+                    mReachedEOS = true;
+                    mFinalStatus = err;
+                    break;
+                }
+            }
+
+            CHECK(mInputBuffer->meta_data()->findInt64(
+                        kKeyTime, &mPositionTimeMediaUs));
+            mFrameSize = mAudioSink->frameSize();
+            mPositionTimeRealUs =
+                ((mNumFramesPlayed + size_done / mFrameSize) * 1000000)
+                    / mSampleRate;
+        }
+        if (mInputBuffer->range_length() == 0) {
+            mInputBuffer->release();
+            mInputBuffer = NULL;
+
+            continue;
+        }
+
+        size_t copy = size_remaining;
+        if (copy > mInputBuffer->range_length()) {
+            copy = mInputBuffer->range_length();
+        } //is size_remaining < range_length impossible?
+
+        memcpy((char *)data + size_done,
+               (const char *)mInputBuffer->data() + mInputBuffer->range_offset(),
+               copy);
+
+        mInputBuffer->set_range(mInputBuffer->range_offset() + copy,
+                                mInputBuffer->range_length() - copy);
+
+        size_done += copy;
+        size_remaining -= copy;
+    }
+
+    if (postSeekComplete) {
+        mObserver->postAudioSeekComplete();
+    }
+
+    return size_done;
+}
+
+int64_t LPAPlayer::getRealTimeUs() {
+    Mutex::Autolock autoLock(mLock);
+    return getRealTimeUsLocked();
+}
+
+
+int64_t LPAPlayer::getRealTimeUsLocked(){
+    //Used for AV sync: irrelevant API for LPA.
+    return 0;
+}
+
+int64_t LPAPlayer::getTimeStamp() {
+    uint64_t timestamp = 0;
+    mAudioSink->getTimeStamp(&timestamp);
+    ALOGV("timestamp %lld ", timestamp);
+    return timestamp;
+}
+
+int64_t LPAPlayer::getMediaTimeUs_l() {
+    if (mPaused) {
+        return mPauseTime;
+    } else {
+        return (mSeekTimeUs + getTimeStamp());
+    }
+}
+
+int64_t LPAPlayer::getMediaTimeUs() {
+    Mutex::Autolock autoLock(mLock);
+    ALOGV("getMediaTimeUs() mPaused %d mSeekTimeUs %lld mPauseTime %lld", mPaused, mSeekTimeUs, mPauseTime);
+    return getMediaTimeUs_l();
+}
+
+bool LPAPlayer::getMediaTimeMapping(
+                                   int64_t *realtime_us, int64_t *mediatime_us) {
+    ALOGE("getMediaTimeMapping is invalid for LPA Player");
+    *realtime_us = -1;
+    *mediatime_us = -1;
+    return false;
+}
+
+bool LPAPlayer::seekTooClose(int64_t time_us) {
+    int64_t t1 = getMediaTimeUs_l();
+    /*
+     * empirical
+     * -----------
+     * This constant signifies how much data (in Us) has been rendered by the
+     * DSP in the interval between the moment flush is issued on AudioSink to
+     * after ioctl(PAUSE) returns in Audio HAL. (flush triggers an implicit
+     * pause in audio HAL)
+     *
+     */
+     const int64_t kDeltaUs = 60000LL; /* 60-70ms on msm8974, must be measured for other targets */
+     t1 += kDeltaUs;
+     return (time_us > t1) && ((time_us - t1) <= LPA_BUFFER_TIME);
+}
+
+//lock taken in reset()
+void LPAPlayer::requestAndWaitForDecoderThreadExit_l() {
+
+    if (!mDecoderThreadAlive)
+        return;
+    mKillDecoderThread = true;
+
+    /* Flush the audio sink to unblock the decoder thread
+       if any write to audio HAL is blocked */
+    if (!mReachedOutputEOS && mIsAudioRouted)
+        mAudioSink->flush();
+
+    mDecoderCv.signal();
+    mLock.unlock();
+    pthread_join(mDecoderThread,NULL);
+    mLock.lock();
+    ALOGD("decoder thread killed");
+
+}
+
+void LPAPlayer::onPauseTimeOut() {
+    ALOGV("onPauseTimeOut");
+    Mutex::Autolock autoLock(mLock);
+    if (!mPauseEventPending) {
+        return;
+    }
+    mPauseEventPending = false;
+    // 1.) Set seek flags
+    mReachedEOS = false;
+    mReachedOutputEOS = false;
+    if(mSeeking == false) {
+        mSeekTimeUs += getTimeStamp();
+        mInternalSeeking = true;
+    } else {
+        //do not update seek time if user has already seeked
+        // to a new position
+        // also seek has to be posted back to player,
+        // so do not set mInternalSeeking flag
+        ALOGV("do not update seek time %lld ", mSeekTimeUs);
+    }
+    ALOGV("newseek time = %lld ", mSeekTimeUs);
+    // 2.) Close routing Session
+    mAudioSink->flush();
+    mAudioSink->stop();
+    mAudioSink->close();
+    mIsAudioRouted = false;
+}
+
+//dup each mono frame
+void LPAPlayer::convertMonoToStereo(int16_t *data, size_t size)
+{
+    int i =0;
+    int16_t *start_pointer = data;
+    int monoFrameCount = (size) / (sizeof(int16_t));
+
+    for (i = monoFrameCount; i > 0 ; i--) {
+      int16_t temp_sample = *(start_pointer + i - 1);
+      *(start_pointer + (i*2) - 1) = temp_sample;
+      *(start_pointer + (i*2) - 2) = temp_sample;
+    }
+}
+
+} //namespace android
diff --git a/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/MPEG4Extractor.cpp
index 4926c1d..2394b79 100644
--- a/media/libstagefright/MPEG4Extractor.cpp
+++ b/media/libstagefright/MPEG4Extractor.cpp
@@ -37,6 +37,10 @@
 #include <media/stagefright/MediaSource.h>
 #include <media/stagefright/MetaData.h>
 #include <utils/String8.h>
+#ifdef ENABLE_AV_ENHANCEMENTS
+#include <QCMediaDefs.h>
+#include "include/ExtendedUtils.h"
+#endif
 
 namespace android {
 
@@ -186,6 +190,11 @@
       mCachedOffset(0),
       mCachedSize(0),
       mCache(NULL) {
+      #ifdef DOLBY_UDC
+      #if defined (DEBUG_LOG_DDP_DECODER_EXTRA)
+      ALOGE("@DDP MPEG4DataSource::MPEG4DataSource");
+      #endif
+      #endif //DOLBY_UDC
 }
 
 MPEG4DataSource::~MPEG4DataSource() {
@@ -293,9 +302,18 @@
 }
 
 static const char *FourCC2MIME(uint32_t fourcc) {
+    #ifdef DOLBY_UDC
+    #if defined (DEBUG_LOG_DDP_DECODER_EXTRA)
+    ALOGE("@DDP FourCC2MIME");
+    #endif
+    #endif //DOLBY_UDC
     switch (fourcc) {
         case FOURCC('m', 'p', '4', 'a'):
             return MEDIA_MIMETYPE_AUDIO_AAC;
+#ifdef QCOM_HARDWARE
+        case FOURCC('.', 'm', 'p', '3'):
+            return MEDIA_MIMETYPE_AUDIO_MPEG;
+#endif
 
         case FOURCC('s', 'a', 'm', 'r'):
             return MEDIA_MIMETYPE_AUDIO_AMR_NB;
@@ -314,8 +332,29 @@
         case FOURCC('a', 'v', 'c', '1'):
             return MEDIA_MIMETYPE_VIDEO_AVC;
 
+#ifdef ENABLE_AV_ENHANCEMENTS
+        case FOURCC('s', 'q', 'c', 'p'):
+            return MEDIA_MIMETYPE_AUDIO_QCELP;
+        case FOURCC('s', 'e', 'v', 'c'):
+            return MEDIA_MIMETYPE_AUDIO_EVRC;
+        case FOURCC('d', 't', 's', 'c'):
+        case FOURCC('d', 't', 's', 'h'):
+        case FOURCC('d', 't', 's', 'l'):
+            return MEDIA_MIMETYPE_AUDIO_DTS;
+        case FOURCC('d', 't', 's', 'e'):
+            return MEDIA_MIMETYPE_AUDIO_DTS_LBR;
+        case FOURCC('a', 'c', '-', '3'):
+            return MEDIA_MIMETYPE_AUDIO_AC3;
+        case FOURCC('e', 'c', '-', '3'):
+            return MEDIA_MIMETYPE_AUDIO_EAC3;
+#endif
         default:
             CHECK(!"should not be here.");
+            #ifdef DOLBY_UDC
+            #if defined (DEBUG_LOG_DDP_DECODER_EXTRA)
+            ALOGE("@DDP FourCC2Mime default (not found)");
+            #endif
+            #endif //DOLBY_UDC
             return NULL;
     }
 }
@@ -347,6 +386,11 @@
       mFileMetaData(new MetaData),
       mFirstSINF(NULL),
       mIsDrm(false) {
+      #ifdef DOLBY_UDC
+      #if defined (DEBUG_LOG_DDP_DECODER_EXTRA)
+      ALOGE("@DDP MPEG4Extractor::MPEG4Extractor");
+      #endif
+      #endif //DOLBY_UDC
 }
 
 MPEG4Extractor::~MPEG4Extractor() {
@@ -443,14 +487,14 @@
                 }
             } else {
                 uint32_t sampleIndex;
-                uint32_t sampleTime;
+                uint64_t sampleTime;
                 if (track->sampleTable->findThumbnailSample(&sampleIndex) == OK
                         && track->sampleTable->getMetaDataForSample(
                             sampleIndex, NULL /* offset */, NULL /* size */,
                             &sampleTime) == OK) {
                     track->meta->setInt64(
                             kKeyThumbnailTime,
-                            ((int64_t)sampleTime * 1000000) / track->timescale);
+                            (sampleTime * 1000000) / track->timescale);
                 }
             }
         }
@@ -1226,8 +1270,21 @@
 
         case FOURCC('m', 'p', '4', 'a'):
         case FOURCC('e', 'n', 'c', 'a'):
+#ifdef QCOM_HARDWARE
+        case FOURCC('.', 'm', 'p', '3'):
+#endif
         case FOURCC('s', 'a', 'm', 'r'):
         case FOURCC('s', 'a', 'w', 'b'):
+#ifdef QCOM_HARDWARE
+        case FOURCC('s', 'e', 'v', 'c'):
+        case FOURCC('s', 'q', 'c', 'p'):
+        case FOURCC('d', 't', 's', 'c'):
+        case FOURCC('d', 't', 's', 'h'):
+        case FOURCC('d', 't', 's', 'l'):
+        case FOURCC('d', 't', 's', 'e'):
+        case FOURCC('a', 'c', '-', '3'):
+        case FOURCC('e', 'c', '-', '3'):
+#endif
         {
             uint8_t buffer[8 + 20];
             if (chunk_data_size < (ssize_t)sizeof(buffer)) {
@@ -1251,13 +1308,27 @@
                 mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(chunk_type));
                 AdjustChannelsAndRate(chunk_type, &num_channels, &sample_rate);
             }
+            #ifdef DOLBY_UDC
+            #if defined (DEBUG_LOG_DDP_DECODER_EXTRA)
+            ALOGE("@DDP FourCC:'%s'", FourCC2MIME(chunk_type));
+            #endif
+            #endif //DOLBY_UDC
             ALOGV("*** coding='%s' %d channels, size %d, rate %d\n",
                    chunk, num_channels, sample_size, sample_rate);
             mLastTrack->meta->setInt32(kKeyChannelCount, num_channels);
             mLastTrack->meta->setInt32(kKeySampleRate, sample_rate);
 
             off64_t stop_offset = *offset + chunk_size;
+#ifdef QCOM_HARDWARE
+            if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_MPEG, FourCC2MIME(chunk_type)) ||
+                !strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, FourCC2MIME(chunk_type))) {
+               *offset = stop_offset;
+            } else {
+#endif
             *offset = data_offset + sizeof(buffer);
+#ifdef QCOM_HARDWARE
+            }
+#endif
             while (*offset < stop_offset) {
                 status_t err = parseChunk(offset, depth + 1);
                 if (err != OK) {
@@ -1545,6 +1616,16 @@
             break;
         }
 
+#ifdef QCOM_HARDWARE
+        case FOURCC('d', 'd', 't', 's'):
+        case FOURCC('d', 'a', 'c', '3'):
+        case FOURCC('d', 'e', 'c', '3'):
+        {
+            ALOGV("ddts/dac3/dec3 pass from mpeg4 extractor");
+            *offset += chunk_size;
+            break;
+        }
+#endif
         case FOURCC('a', 'v', 'c', 'C'):
         {
             sp<ABuffer> buffer = new ABuffer(chunk_data_size);
@@ -2253,12 +2334,27 @@
         return ERROR_MALFORMED;
     }
 
+#ifdef ENABLE_AV_ENHANCEMENTS
+    if (objectTypeIndication == 0xA0) {
+       mLastTrack->meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_EVRC);
+       return OK;
+    }
+#endif
     if (objectTypeIndication == 0xe1) {
         // This isn't MPEG4 audio at all, it's QCELP 14k...
         mLastTrack->meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_QCELP);
         return OK;
     }
 
+#ifdef QCOM_HARDWARE
+    if (objectTypeIndication  == 0x6b
+         || objectTypeIndication  == 0x69) {
+        // Our software MP3 audio decoder may not be able to handle
+         mLastTrack->meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_MPEG);
+         ALOGD("objectTypeIndication:0x%x, set mimetype to mpeg ",objectTypeIndication);
+         return OK;
+    }
+#else
     if (objectTypeIndication  == 0x6b) {
         // The media subtype is MP3 audio
         // Our software MP3 audio decoder may not be able to handle
@@ -2266,6 +2362,7 @@
         ALOGE("MP3 track in MP4/3GPP file is not supported");
         return ERROR_UNSUPPORTED;
     }
+#endif
 
     const uint8_t *csd;
     size_t csd_size;
@@ -2401,6 +2498,11 @@
       mBuffer(NULL),
       mWantsNALFragments(false),
       mSrcBuffer(NULL) {
+      #ifdef DOLBY_UDC
+      #if defined (DEBUG_LOG_DDP_DECODER_EXTRA)
+      ALOGE("@DDP MPEG4Source::MPEG4Source");
+      #endif
+      #endif //DOLBY_UDC
 
     mFormat->findInt32(kKeyCryptoMode, &mCryptoMode);
     mDefaultIVSize = 0;
@@ -3100,7 +3202,7 @@
                     sampleIndex, &syncSampleIndex, findFlags);
         }
 
-        uint32_t sampleTime;
+        uint64_t sampleTime;
         if (err == OK) {
             err = mSampleTable->getMetaDataForSample(
                     sampleIndex, NULL, NULL, &sampleTime);
@@ -3124,7 +3226,7 @@
         }
 
 #if 0
-        uint32_t syncSampleTime;
+        uint64_t syncSampleTime;
         CHECK_EQ(OK, mSampleTable->getMetaDataForSample(
                     syncSampleIndex, NULL, NULL, &syncSampleTime));
 
@@ -3146,7 +3248,7 @@
 
     off64_t offset;
     size_t size;
-    uint32_t cts;
+    uint64_t cts;
     bool isSyncSample;
     bool newBuffer = false;
     if (mBuffer == NULL) {
@@ -3179,12 +3281,11 @@
 
                 return ERROR_IO;
             }
-
             CHECK(mBuffer != NULL);
             mBuffer->set_range(0, size);
             mBuffer->meta_data()->clear();
             mBuffer->meta_data()->setInt64(
-                    kKeyTime, ((int64_t)cts * 1000000) / mTimescale);
+                    kKeyTime, (cts * 1000000) / mTimescale);
 
             if (targetSampleTimeUs >= 0) {
                 mBuffer->meta_data()->setInt64(
@@ -3306,7 +3407,7 @@
 
         mBuffer->meta_data()->clear();
         mBuffer->meta_data()->setInt64(
-                kKeyTime, ((int64_t)cts * 1000000) / mTimescale);
+                kKeyTime, (cts * 1000000) / mTimescale);
 
         if (targetSampleTimeUs >= 0) {
             mBuffer->meta_data()->setInt64(
@@ -3612,6 +3713,9 @@
     }
 
     if (!memcmp(header, "ftyp3gp", 7) || !memcmp(header, "ftypmp42", 8)
+#ifdef QCOM_HARDWARE
+        || !memcmp(header, "ftyp3g2a", 8) || !memcmp(header, "ftyp3g2b", 8) || !memcmp(header, "ftyp3g2c", 8)
+#endif
         || !memcmp(header, "ftyp3gr6", 8) || !memcmp(header, "ftyp3gs6", 8)
         || !memcmp(header, "ftyp3ge6", 8) || !memcmp(header, "ftyp3gg6", 8)
         || !memcmp(header, "ftypisom", 8) || !memcmp(header, "ftypM4V ", 8)
diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp
index 42885dd..48ad607 100644
--- a/media/libstagefright/MPEG4Writer.cpp
+++ b/media/libstagefright/MPEG4Writer.cpp
@@ -40,12 +40,15 @@
 
 #include "include/ESDS.h"
 
+#include "include/ExtendedUtils.h"
+
 namespace android {
 
 static const int64_t kMinStreamableFileSizeInBytes = 5 * 1024 * 1024;
 static const int64_t kMax32BitFileSize = 0x00ffffffffLL; // 2^32-1 : max FAT32
                                                          // filesystem file size
                                                          // used by most SD cards
+static const int64_t kMax64BitFileSize = 0x00ffffffffLL; //fat32 max size limited to 4GB
 static const uint8_t kNalUnitTypeSeqParamSet = 0x07;
 static const uint8_t kNalUnitTypePicParamSet = 0x08;
 static const int64_t kInitialDelayTimeUs     = 700000LL;
@@ -442,7 +445,8 @@
 
     // A track of type other than video or audio is not supported.
     const char *mime;
-    source->getFormat()->findCString(kKeyMIMEType, &mime);
+    sp<MetaData> meta = source->getFormat();
+    CHECK(meta->findCString(kKeyMIMEType, &mime));
     bool isAudio = !strncasecmp(mime, "audio/", 6);
     bool isVideo = !strncasecmp(mime, "video/", 6);
     if (!isAudio && !isVideo) {
@@ -510,7 +514,7 @@
 
     // If the estimation is wrong, we will pay the price of wasting
     // some reserved space. This should not happen so often statistically.
-    static const int32_t factor = mUse32BitOffset? 1: 2;
+    int32_t factor = mUse32BitOffset? 1: 2;
     static const int64_t MIN_MOOV_BOX_SIZE = 3 * 1024;  // 3 KB
     static const int64_t MAX_MOOV_BOX_SIZE = (180 * 3000000 * 6LL / 8000);
     int64_t size = MIN_MOOV_BOX_SIZE;
@@ -569,11 +573,14 @@
         mIsFileSizeLimitExplicitlyRequested = true;
     }
 
-    int32_t use64BitOffset;
+    int32_t use64BitOffset = 0;
     if (param &&
         param->findInt32(kKey64BitFileOffset, &use64BitOffset) &&
         use64BitOffset) {
         mUse32BitOffset = false;
+        if (mMaxFileSizeLimitBytes == 0) {
+            mMaxFileSizeLimitBytes = kMax64BitFileSize;
+        }
     }
 
     if (mUse32BitOffset) {
@@ -2144,6 +2151,83 @@
             mGotAllCodecSpecificData = true;
             continue;
         }
+#if defined(OMAP_ENHANCEMENT) && defined(TARGET_OMAP3)
+        else if (mIsAvc && count < 3) {
+            size_t size = buffer->range_length();
+
+            switch (count) {
+                case 1:
+                {
+                    CHECK_EQ(mCodecSpecificData, (void *)NULL);
+                    mCodecSpecificData = malloc(size + 8);
+                    uint8_t *header = (uint8_t *)mCodecSpecificData;
+                    header[0] = 1;
+                    header[1] = 0x42;  // profile
+                    header[2] = 0x80;
+                    header[3] = 0x1e;  // level
+                    header[4] = 0xfc | 3;
+                    header[5] = 0xe0 | 1;
+                    header[6] = size >> 8;
+                    header[7] = size & 0xff;
+                    memcpy(&header[8],
+                            (const uint8_t *)buffer->data() + buffer->range_offset(),
+                            size);
+
+                    mCodecSpecificDataSize = size + 8;
+                    break;
+                }
+
+                case 2:
+                {
+                    size_t offset = mCodecSpecificDataSize;
+                    mCodecSpecificDataSize += size + 3;
+                    mCodecSpecificData = realloc(mCodecSpecificData, mCodecSpecificDataSize);
+                    uint8_t *header = (uint8_t *)mCodecSpecificData;
+                    header[offset] = 1;
+                    header[offset + 1] = size >> 8;
+                    header[offset + 2] = size & 0xff;
+                    memcpy(&header[offset + 3],
+                            (const uint8_t *)buffer->data() + buffer->range_offset(),
+                            size);
+                    break;
+                }
+            }
+
+            buffer->release();
+            buffer = NULL;
+
+            continue;
+
+        } else if (mCodecSpecificData == NULL && mIsMPEG4) {
+            const uint8_t *data =
+                (const uint8_t *)buffer->data() + buffer->range_offset();
+
+            const size_t size = buffer->range_length();
+
+            size_t offset = 0;
+            while (offset + 3 < size) {
+                if (data[offset] == 0x00 && data[offset + 1] == 0x00
+                    && data[offset + 2] == 0x01 && data[offset + 3] == 0xb6) {
+                    break;
+                }
+
+                ++offset;
+            }
+
+            // CHECK(offset + 3 < size);
+            if (offset + 3 >= size) {
+                // XXX assume the entire first chunk of data is the codec specific
+                // data.
+                offset = size;
+            }
+
+            mCodecSpecificDataSize = offset;
+            mCodecSpecificData = malloc(offset);
+            memcpy(mCodecSpecificData, data, offset);
+
+            buffer->set_range(buffer->range_offset() + offset, size - offset);
+        }
+#endif
 
         // Make a deep copy of the MediaBuffer and Metadata and release
         // the original as soon as we can
@@ -2184,6 +2268,10 @@
         meta_data->findInt32(kKeyIsSyncFrame, &isSync);
         CHECK(meta_data->findInt64(kKeyTime, &timestampUs));
 
+        if (!mIsAudio) {
+            ExtendedUtils::HFR::reCalculateTimeStamp(mMeta, timestampUs);
+        }
+
 ////////////////////////////////////////////////////////////////////////////////
         if (mStszTableEntries->count() == 0) {
             mFirstSampleTimeRealUs = systemTime() / 1000;
@@ -2202,19 +2290,26 @@
         }
 
         timestampUs -= previousPausedDurationUs;
+#ifndef OMAP_ENHANCEMENT
         CHECK_GE(timestampUs, 0ll);
+#endif
         if (!mIsAudio) {
             /*
              * Composition time: timestampUs
              * Decoding time: decodingTimeUs
              * Composition time offset = composition time - decoding time
              */
+            int64_t tmpCttsOffsetTimeUs;
             int64_t decodingTimeUs;
             CHECK(meta_data->findInt64(kKeyDecodingTime, &decodingTimeUs));
+            ExtendedUtils::HFR::reCalculateTimeStamp(mMeta, decodingTimeUs);
+
             decodingTimeUs -= previousPausedDurationUs;
             cttsOffsetTimeUs =
-                    timestampUs + kMaxCttsOffsetTimeUs - decodingTimeUs;
-            CHECK_GE(cttsOffsetTimeUs, 0ll);
+                    timestampUs - decodingTimeUs;
+            tmpCttsOffsetTimeUs = kMaxCttsOffsetTimeUs;
+            ExtendedUtils::HFR::reCalculateTimeStamp(mMeta, tmpCttsOffsetTimeUs);
+            CHECK_GE(tmpCttsOffsetTimeUs, decodingTimeUs - timestampUs);
             timestampUs = decodingTimeUs;
             ALOGV("decoding time: %lld and ctts offset time: %lld",
                 timestampUs, cttsOffsetTimeUs);
diff --git a/media/libstagefright/MediaBuffer.cpp b/media/libstagefright/MediaBuffer.cpp
index 11b80bf..b470e43 100644
--- a/media/libstagefright/MediaBuffer.cpp
+++ b/media/libstagefright/MediaBuffer.cpp
@@ -136,6 +136,7 @@
 void MediaBuffer::set_range(size_t offset, size_t length) {
     if ((mGraphicBuffer == NULL) && (offset + length > mSize)) {
         ALOGE("offset = %d, length = %d, mSize = %d", offset, length, mSize);
+        offset = 0;
     }
     CHECK((mGraphicBuffer != NULL) || (offset + length <= mSize));
 
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
old mode 100644
new mode 100755
index c36dd7c..49683f7
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -35,6 +35,9 @@
 #include <media/stagefright/MediaDefs.h>
 #include <media/stagefright/MediaErrors.h>
 #include <media/stagefright/MetaData.h>
+#ifdef QCOM_HARDWARE
+#include <media/stagefright/ExtendedCodec.h>
+#endif
 #include <media/stagefright/NativeWindowWrapper.h>
 
 #include "include/avc_utils.h"
@@ -1415,6 +1418,20 @@
         ++i;
     }
 
+#ifdef QCOM_HARDWARE
+    sp<ABuffer> extendedCSD = ExtendedCodec::getRawCodecSpecificData(format);
+    if (extendedCSD != NULL) {
+        ALOGV("pushing extended CSD of size %d", extendedCSD->size());
+        mCSD.push_back(extendedCSD);
+    }
+
+    sp<ABuffer> aacCSD = ExtendedCodec::getAacCodecSpecificData(format);
+    if (aacCSD != NULL) {
+        ALOGV("pushing AAC CSD of size %d", aacCSD->size());
+        mCSD.push_back(aacCSD);
+    }
+#endif
+
     ALOGV("Found %u pieces of codec specific data.", mCSD.size());
 }
 
diff --git a/media/libstagefright/MediaCodecList.cpp b/media/libstagefright/MediaCodecList.cpp
index 6248e90..60e8ea8 100644
--- a/media/libstagefright/MediaCodecList.cpp
+++ b/media/libstagefright/MediaCodecList.cpp
@@ -27,6 +27,9 @@
 #include <utils/threads.h>
 
 #include <libexpat/expat.h>
+#ifdef QCOM_HARDWARE
+#include "include/ExtendedUtils.h"
+#endif
 
 namespace android {
 
@@ -63,7 +66,15 @@
         addMediaCodec(true /* encoder */, "AACEncoder", "audio/mp4a-latm");
 
         addMediaCodec(
-                false /* encoder */, "OMX.google.raw.decoder", "audio/raw");
+                     false /* encoder */, "OMX.google.raw.decoder", "audio/raw");
+
+#ifdef QCOM_HARDWARE
+        Vector<AString> QcomAACQuirks;
+        QcomAACQuirks.push(AString("requires-allocate-on-input-ports"));
+        QcomAACQuirks.push(AString("requires-allocate-on-output-ports"));
+        ExtendedUtils::helper_addMediaCodec(mCodecInfos, mTypes, false, "OMX.qcom.audio.decoder.multiaac",
+            "audio/mp4a-latm", ExtendedUtils::helper_getCodecSpecificQuirks(mCodecQuirks, QcomAACQuirks));
+#endif
     }
 
 #if 0
diff --git a/media/libstagefright/MediaExtractor.cpp b/media/libstagefright/MediaExtractor.cpp
old mode 100644
new mode 100755
index 9ab6611..5ebf160
--- a/media/libstagefright/MediaExtractor.cpp
+++ b/media/libstagefright/MediaExtractor.cpp
@@ -39,6 +39,10 @@
 #include <media/stagefright/MetaData.h>
 #include <utils/String8.h>
 
+#ifdef QCOM_HARDWARE
+#include "include/ExtendedUtils.h"
+#endif
+
 namespace android {
 
 sp<MetaData> MediaExtractor::getMetaData() {
@@ -126,7 +130,11 @@
        }
     }
 
+#ifdef QCOM_HARDWARE
+    return ExtendedUtils::MediaExtractor_CreateIfNeeded(ret, source, mime);
+#else
     return ret;
+#endif
 }
 
 }  // namespace android
diff --git a/media/libstagefright/NOTICE b/media/libstagefright/NOTICE
index c5b1efa..1c3f344 100644
--- a/media/libstagefright/NOTICE
+++ b/media/libstagefright/NOTICE
@@ -188,3 +188,31 @@
 
    END OF TERMS AND CONDITIONS
 
+Copyright (c) 2013, The Linux Foundation. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+    * Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+     with the distribution.
+  * Neither the name of The Linux Foundation nor the names of its
+     contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index 43736ad..1562574 100644
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -1,5 +1,8 @@
 /*
  * Copyright (C) 2009 The Android Open Source Project
+ * Copyright (c) 2010 - 2013, The Linux Foundation. All rights reserved.
+ *
+ * Not a Contribution
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -19,6 +22,9 @@
 #include <utils/Log.h>
 
 #include "include/AACEncoder.h"
+#ifdef QCOM_HARDWARE
+#include "include/MP3Decoder.h"
+#endif
 
 #include "include/ESDS.h"
 
@@ -41,11 +47,50 @@
 
 #include <OMX_Audio.h>
 #include <OMX_Component.h>
-
+#ifdef QCOM_HARDWARE
+#include <media/stagefright/ExtendedCodec.h>
+#include "include/ExtendedUtils.h"
+#endif
 #include "include/avc_utils.h"
 
+#ifdef ENABLE_AV_ENHANCEMENTS
+#include <QCMediaDefs.h>
+#include <QCMetaData.h>
+#include <QOMX_AudioExtensions.h>
+#endif
+
+#ifdef USE_SAMSUNG_COLORFORMAT
+#include <sec_format.h>
+#endif
+
+#ifdef USE_TI_CUSTOM_DOMX
+#include <OMX_TI_Video.h>
+#include <OMX_TI_Index.h>
+#include <OMX_TI_IVCommon.h>
+#include <ctype.h>
+#endif
+
 namespace android {
 
+#ifdef USE_SAMSUNG_COLORFORMAT
+static const int OMX_SEC_COLOR_FormatNV12TPhysicalAddress = 0x7F000001;
+static const int OMX_SEC_COLOR_FormatNV12LPhysicalAddress = 0x7F000002;
+static const int OMX_SEC_COLOR_FormatNV12LVirtualAddress = 0x7F000003;
+static const int OMX_SEC_COLOR_FormatNV12Tiled = 0x7FC00002;
+static int calc_plane(int width, int height)
+{
+    int mbX, mbY;
+
+    mbX = (width + 15)/16;
+    mbY = (height + 15)/16;
+
+    /* Alignment for interlaced processing */
+    mbY = (mbY + 1) / 2 * 2;
+
+    return (mbX * 16) * (mbY * 16);
+}
+#endif // USE_SAMSUNG_COLORFORMAT
+
 // Treat time out as an error if we have not received any output
 // buffers after 3 seconds.
 const static int64_t kBufferFilledEventTimeOutNs = 3000000000LL;
@@ -57,6 +102,11 @@
 // component in question is buggy or not.
 const static uint32_t kMaxColorFormatSupported = 1000;
 
+#define FACTORY_CREATE(name) \
+static sp<MediaSource> Make##name(const sp<MediaSource> &source) { \
+    return new name(source); \
+}
+
 #define FACTORY_CREATE_ENCODER(name) \
 static sp<MediaSource> Make##name(const sp<MediaSource> &source, const sp<MetaData> &meta) { \
     return new name(source, meta); \
@@ -64,6 +114,9 @@
 
 #define FACTORY_REF(name) { #name, Make##name },
 
+#ifdef QCOM_HARDWARE
+FACTORY_CREATE(MP3Decoder)
+#endif
 FACTORY_CREATE_ENCODER(AACEncoder)
 
 static sp<MediaSource> InstantiateSoftwareEncoder(
@@ -87,8 +140,28 @@
     return NULL;
 }
 
+#ifdef QCOM_HARDWARE
+static sp<MediaSource> InstantiateSoftwareDecoder(
+        const char *name, const sp<MediaSource> &source) {
+    struct FactoryInfo {
+        const char *name;
+        sp<MediaSource> (*CreateFunc)(const sp<MediaSource> &);
+    };
+    static const FactoryInfo kFactoryInfo[] = {
+        FACTORY_REF(MP3Decoder)
+    };
+    for (size_t i = 0;
+         i < sizeof(kFactoryInfo) / sizeof(kFactoryInfo[0]); ++i) {
+        if (!strcmp(name, kFactoryInfo[i].name)) {
+            return (*kFactoryInfo[i].CreateFunc)(source);
+        }
+    }
+    return NULL;
+}
+#endif
 #undef FACTORY_CREATE_ENCODER
 #undef FACTORY_REF
+#undef FACTORY_CREATE
 
 #define CODEC_LOGI(x, ...) ALOGI("[%s] "x, mComponentName, ##__VA_ARGS__)
 #define CODEC_LOGV(x, ...) ALOGV("[%s] "x, mComponentName, ##__VA_ARGS__)
@@ -133,7 +206,13 @@
 }
 
 static bool IsSoftwareCodec(const char *componentName) {
-    if (!strncmp("OMX.google.", componentName, 11)) {
+#ifdef DOLBY_UDC
+    if (!strncmp("OMX.dolby.", componentName, 10)) {
+        return true;
+    }
+#endif // DOLBY_UDC
+    if (!strncmp("OMX.google.", componentName, 11)
+        || !strncmp("OMX.PV.", componentName, 7)) {
         return true;
     }
 
@@ -192,6 +271,16 @@
     }
 
     size_t index = 0;
+
+#ifdef ENABLE_AV_ENHANCEMENTS
+    if (matchComponentName && !strcmp("OMX.qcom.audio.encoder.aac", matchComponentName)) {
+        matchingCodecs->add();
+        CodecNameAndQuirks *entry = &matchingCodecs->editItemAt(index);
+        entry->mName = String8("OMX.qcom.audio.encoder.aac");
+        entry->mQuirks = 0;
+        return;
+    }
+#endif
     for (;;) {
         ssize_t matchIndex =
             list->findCodecByType(mime, createEncoder, index);
@@ -205,6 +294,7 @@
         const char *componentName = list->getCodecName(matchIndex);
 
         // If a specific codec is requested, skip the non-matching ones.
+        ALOGV("matchComponentName %s ",matchComponentName);
         if (matchComponentName && strcmp(componentName, matchComponentName)) {
             continue;
         }
@@ -236,6 +326,23 @@
 uint32_t OMXCodec::getComponentQuirks(
         const MediaCodecList *list, size_t index) {
     uint32_t quirks = 0;
+
+    if (list->codecHasQuirk(
+                index, "needs-flush-before-disable")) {
+        quirks |= kNeedsFlushBeforeDisable;
+    }
+    if (list->codecHasQuirk(
+                index, "requires-flush-complete-emulation")) {
+        quirks |= kRequiresFlushCompleteEmulation;
+    }
+    if (list->codecHasQuirk(
+                index, "supports-multiple-frames-per-input-buffer")) {
+        quirks |= kSupportsMultipleFramesPerInputBuffer;
+    }
+    if (list->codecHasQuirk(
+                index, "requires-larger-encoder-output-buffer")) {
+        quirks |= kRequiresLargerEncoderOutputBuffer;
+    }
     if (list->codecHasQuirk(
                 index, "requires-allocate-on-input-ports")) {
         quirks |= kRequiresAllocateBufferOnInputPorts;
@@ -245,9 +352,51 @@
         quirks |= kRequiresAllocateBufferOnOutputPorts;
     }
     if (list->codecHasQuirk(
+                index, "requires-flush-before-shutdown")) {
+        quirks |= kRequiresFlushBeforeShutdown;
+    }
+    if (list->codecHasQuirk(
                 index, "output-buffers-are-unreadable")) {
         quirks |= kOutputBuffersAreUnreadable;
     }
+#ifdef QCOM_HARDWARE
+    if (list->codecHasQuirk(
+                index, "requies-loaded-to-idle-after-allocation")) {
+        quirks |= kRequiresLoadedToIdleAfterAllocation;
+    }
+    if (list->codecHasQuirk(
+                index, "requires-global-flush")) {
+        quirks |= kRequiresGlobalFlush;
+    }
+    if (list->codecHasQuirk(
+                index, "defers-output-buffer-allocation")) {
+        quirks |= kDefersOutputBufferAllocation;
+    }
+#ifdef DOLBY_UDC
+    if (list->codecHasQuirk(
+                index, "needs-flush-before-disable")) {
+        quirks |= kNeedsFlushBeforeDisable;
+    }
+    if (list->codecHasQuirk(
+                index, "requires-flush-complete-emulation")) {
+        quirks |= kRequiresFlushCompleteEmulation;
+    }
+#endif // DOLBY_UDC
+#endif
+#ifdef OMAP_ENHANCEMENT
+    if (list->codecHasQuirk(
+                index, "avoid-memcopy-input-recording-frames")) {
+      quirks |= kAvoidMemcopyInputRecordingFrames;
+    }
+    if (list->codecHasQuirk(
+                index, "input-buffer-sizes-are-bogus")) {
+      quirks |= kInputBufferSizesAreBogus;
+    }
+#endif
+
+#ifdef QCOM_HARDWARE
+    quirks |= ExtendedCodec::getComponentQuirks(list,index);
+#endif
 
     return quirks;
 }
@@ -259,6 +408,12 @@
     if (list == NULL) {
         return false;
     }
+#ifdef ENABLE_AV_ENHANCEMENTS
+    if (componentName && !strcmp("OMX.qcom.audio.encoder.aac", componentName)) {
+        *quirks = 0;
+        return true;
+    }
+#endif
 
     ssize_t index = list->findCodecByName(componentName);
 
@@ -293,8 +448,18 @@
     CHECK(success);
 
     Vector<CodecNameAndQuirks> matchingCodecs;
-    findMatchingCodecs(
+
+#ifdef QCOM_HARDWARE
+    if (ExtendedCodec::useHWAACDecoder(mime)) {
+        findMatchingCodecs(mime, createEncoder,
+            "OMX.qcom.audio.decoder.multiaac", flags, &matchingCodecs);
+    } else {
+#endif
+        findMatchingCodecs(
             mime, createEncoder, matchComponentName, flags, &matchingCodecs);
+#ifdef QCOM_HARDWARE
+    }
+#endif
 
     if (matchingCodecs.isEmpty()) {
         ALOGV("No matching codecs! (mime: %s, createEncoder: %s, "
@@ -319,15 +484,25 @@
             componentName = tmp.c_str();
         }
 
+        sp<MediaSource> softwareCodec;
         if (createEncoder) {
-            sp<MediaSource> softwareCodec =
-                InstantiateSoftwareEncoder(componentName, source, meta);
-
+            softwareCodec = InstantiateSoftwareEncoder(componentName, source, meta);
+#ifdef QCOM_HARDWARE
+        } else {
+            softwareCodec = InstantiateSoftwareDecoder(componentName, source);
+        }
+#endif
             if (softwareCodec != NULL) {
                 ALOGV("Successfully allocated software codec '%s'", componentName);
 
                 return softwareCodec;
             }
+
+#ifdef QCOM_HARDWARE
+        const char* ext_componentName = ExtendedCodec::overrideComponentName(quirks, meta);
+        if(ext_componentName != NULL) {
+          componentName = ext_componentName;
+#endif
         }
 
         ALOGV("Attempting to allocate OMX node '%s'", componentName);
@@ -466,8 +641,18 @@
             esds.getCodecSpecificInfo(
                     &codec_specific_data, &codec_specific_data_size);
 
+#ifdef QCOM_HARDWARE
+            const char * mime_type;
+            meta->findCString(kKeyMIMEType, &mime_type);
+            if (strncmp(mime_type,
+                        MEDIA_MIMETYPE_AUDIO_MPEG,
+                        strlen(MEDIA_MIMETYPE_AUDIO_MPEG))) {
+#endif
             addCodecSpecificData(
                     codec_specific_data, codec_specific_data_size);
+#ifdef QCOM_HARDWARE
+            }
+#endif
         } else if (meta->findData(kKeyAVCC, &type, &data, &size)) {
             // Parse the AVCDecoderConfigurationRecord
 
@@ -479,6 +664,10 @@
                 return err;
             }
 
+#ifdef QCOM_HARDWARE
+            ExtendedUtils::setArbitraryModeIfInterlaced((const uint8_t *)data, meta);
+#endif
+
             CODEC_LOGI(
                     "AVC profile = %u (%s), level = %u",
                     profile, AVCProfileToString(profile), level);
@@ -487,6 +676,18 @@
 
             CHECK(meta->findData(kKeyVorbisBooks, &type, &data, &size));
             addCodecSpecificData(data, size);
+#ifdef QCOM_HARDWARE
+#ifdef ENABLE_AV_ENHANCEMENTS
+        } else if (meta->findData(kKeyRawCodecSpecificData, &type, &data, &size)) {
+            ALOGV("OMXCodec::configureCodec found kKeyRawCodecSpecificData of size %d\n", size);
+            addCodecSpecificData(data, size);
+#endif
+        } else {
+            ExtendedCodec::getRawCodecSpecificData(meta, data, size);
+            if (size) {
+                addCodecSpecificData(data, size);
+            }
+#endif
         }
     }
 
@@ -517,6 +718,15 @@
             CODEC_LOGE("setAACFormat() failed (err = %d)", err);
             return err;
         }
+#ifdef ENABLE_AV_ENHANCEMENTS
+        uint32_t type;
+        const void *data;
+        size_t size;
+        if (meta->findData(kKeyAacCodecSpecificData, &type, &data, &size)) {
+            ALOGV("OMXCodec:: configureCodec found kKeyAacCodecSpecificData of size %d\n", size);
+            addCodecSpecificData(data, size);
+        }
+#endif
     } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_MPEG, mMIME)) {
         int32_t numChannels, sampleRate;
         if (meta->findInt32(kKeyChannelCount, &numChannels)
@@ -545,12 +755,29 @@
         CHECK(meta->findInt32(kKeySampleRate, &sampleRate));
 
         setRawAudioFormat(kPortIndexInput, sampleRate, numChannels);
+#ifdef QCOM_HARDWARE
+    } else {
+        if (mIsEncoder && !mIsVideo) {
+            int32_t numChannels, sampleRate;
+            CHECK(meta->findInt32(kKeyChannelCount, &numChannels));
+            CHECK(meta->findInt32(kKeySampleRate, &sampleRate));
+            setRawAudioFormat(kPortIndexInput, sampleRate, numChannels);
+        }
+        status_t err = ExtendedCodec::setAudioFormat(
+                meta, mMIME, mOMX, mNode, mIsEncoder);
+        if(OK != err) {
+            return err;
+        }
+#endif
     }
 
     if (!strncasecmp(mMIME, "video/", 6)) {
 
         if (mIsEncoder) {
-            setVideoInputFormat(mMIME, meta);
+            status_t err = setVideoInputFormat(mMIME, meta);
+            if (err != OK) {
+                return err;
+            }
         } else {
             status_t err = setVideoOutputFormat(
                     mMIME, meta);
@@ -558,6 +785,15 @@
             if (err != OK) {
                 return err;
             }
+
+#ifdef QCOM_HARDWARE
+            ExtendedCodec::configureVideoDecoder(
+                    meta, mMIME, mOMX, mFlags, mNode, mComponentName);
+            ExtendedCodec::configureFramePackingFormat(
+                    meta, mOMX, mNode, mComponentName);
+            ExtendedCodec::enableSmoothStreaming(
+                    mOMX, mNode, &mInSmoothStreamingMode, mComponentName);
+#endif
         }
     }
 
@@ -671,6 +907,22 @@
              index, format.eCompressionFormat, format.eColorFormat);
 #endif
 
+        if (!strcmp("OMX.TI.Video.encoder", mComponentName) ||
+            !strcmp("OMX.TI.720P.Encoder", mComponentName)) {
+            if (portIndex == kPortIndexInput
+                    && colorFormat == format.eColorFormat) {
+                // eCompressionFormat does not seem right.
+                found = true;
+                break;
+            }
+            if (portIndex == kPortIndexOutput
+                    && compressionFormat == format.eCompressionFormat) {
+                // eColorFormat does not seem right.
+                found = true;
+                break;
+            }
+        }
+
         if (format.eCompressionFormat == compressionFormat
                 && format.eColorFormat == colorFormat) {
             found = true;
@@ -697,6 +949,13 @@
     return err;
 }
 
+#ifdef USE_SAMSUNG_COLORFORMAT
+#define ALIGN_TO_8KB(x)   ((((x) + (1 << 13) - 1) >> 13) << 13)
+#define ALIGN_TO_32B(x)   ((((x) + (1 <<  5) - 1) >>  5) <<  5)
+#define ALIGN_TO_128B(x)  ((((x) + (1 <<  7) - 1) >>  7) <<  7)
+#define ALIGN(x, a)       (((x) + (a) - 1) & ~((a) - 1))
+#endif
+
 static size_t getFrameSize(
         OMX_COLOR_FORMATTYPE colorFormat, int32_t width, int32_t height) {
     switch (colorFormat) {
@@ -716,8 +975,19 @@
         * this part in the future
         */
         case OMX_COLOR_FormatAndroidOpaque:
+#ifdef USE_SAMSUNG_COLORFORMAT
+        case OMX_SEC_COLOR_FormatNV12TPhysicalAddress:
+        case OMX_SEC_COLOR_FormatNV12LPhysicalAddress:
+#endif
             return (width * height * 3) / 2;
-
+#ifdef USE_SAMSUNG_COLORFORMAT
+        case OMX_SEC_COLOR_FormatNV12LVirtualAddress:
+            return ALIGN((ALIGN(width, 16) * ALIGN(height, 16)), 2048) + ALIGN((ALIGN(width, 16) * ALIGN(height >> 1, 8)), 2048);
+        case OMX_SEC_COLOR_FormatNV12Tiled:
+            static unsigned int frameBufferYSise = ALIGN_TO_8KB(ALIGN_TO_128B(width) * ALIGN_TO_32B(height));
+            static unsigned int frameBufferUVSise = ALIGN_TO_8KB(ALIGN_TO_128B(width) * ALIGN_TO_32B(height/2));
+            return (frameBufferYSise + frameBufferUVSise);
+#endif
         default:
             CHECK(!"Should not be here. Unsupported color format.");
             break;
@@ -761,7 +1031,7 @@
         // the incremented index (bug 2897413).
         CHECK_EQ(index, portFormat.nIndex);
         if (portFormat.eColorFormat == colorFormat) {
-            CODEC_LOGV("Found supported color format: %d", portFormat.eColorFormat);
+            CODEC_LOGE("Found supported color format: %d", portFormat.eColorFormat);
             return OK;  // colorFormat is supported!
         }
         ++index;
@@ -777,7 +1047,7 @@
     return UNKNOWN_ERROR;
 }
 
-void OMXCodec::setVideoInputFormat(
+status_t OMXCodec::setVideoInputFormat(
         const char *mime, const sp<MetaData>& meta) {
 
     int32_t width, height, frameRate, bitRate, stride, sliceHeight;
@@ -790,6 +1060,10 @@
     CHECK(success);
     CHECK(stride != 0);
 
+#ifdef QCOM_HARDWARE
+    ExtendedUtils::HFR::reCalculateHFRParams(meta, frameRate, bitRate);
+#endif
+
     OMX_VIDEO_CODINGTYPE compressionFormat = OMX_VIDEO_CodingUnused;
     if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
         compressionFormat = OMX_VIDEO_CodingAVC;
@@ -798,8 +1072,15 @@
     } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) {
         compressionFormat = OMX_VIDEO_CodingH263;
     } else {
+#ifdef QCOM_HARDWARE
+        status_t err = ExtendedCodec::setVideoInputFormat(mime, &compressionFormat);
+        if(err != OK) {
+#endif
         ALOGE("Not a supported video mime type: %s", mime);
         CHECK(!"Should not be here. Not a supported video mime type.");
+#ifdef QCOM_HARDWARE
+        }
+#endif
     }
 
     OMX_COLOR_FORMATTYPE colorFormat;
@@ -810,21 +1091,30 @@
     OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
 
     //////////////////////// Input port /////////////////////////
-    CHECK_EQ(setVideoPortFormatType(
-            kPortIndexInput, OMX_VIDEO_CodingUnused,
-            colorFormat), (status_t)OK);
+    err = setVideoPortFormatType(
+            kPortIndexInput, OMX_VIDEO_CodingUnused, colorFormat);
+    if(err != OK) {
+        ALOGE("Setting OMX_VIDEO_CodingUnused failed");
+        return err;
+    }
 
     InitOMXParams(&def);
     def.nPortIndex = kPortIndexInput;
 
     err = mOMX->getParameter(
             mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
-    CHECK_EQ(err, (status_t)OK);
+    if(err != OK) {
+        ALOGE("Getting OMX_IndexParamPortDefinition failed");
+        return err;
+    }
 
     def.nBufferSize = getFrameSize(colorFormat,
             stride > 0? stride: -stride, sliceHeight);
 
-    CHECK_EQ((int)def.eDomain, (int)OMX_PortDomainVideo);
+    if((int)def.eDomain != (int)OMX_PortDomainVideo) {
+        ALOGE("Input port: Not a Video Domain!!");
+        return UNKNOWN_ERROR;
+    }
 
     video_def->nFrameWidth = width;
     video_def->nFrameHeight = height;
@@ -836,20 +1126,33 @@
 
     err = mOMX->setParameter(
             mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
-    CHECK_EQ(err, (status_t)OK);
+    if(err != OK) {
+        ALOGE("Setting Video InPort Definition failed");
+        return err;
+    }
 
     //////////////////////// Output port /////////////////////////
-    CHECK_EQ(setVideoPortFormatType(
-            kPortIndexOutput, compressionFormat, OMX_COLOR_FormatUnused),
-            (status_t)OK);
+    err = setVideoPortFormatType(
+            kPortIndexOutput, compressionFormat, OMX_COLOR_FormatUnused);
+    if(err != OK) {
+        ALOGE("Setting compressionFormat failed");
+        return err;
+    }
+
     InitOMXParams(&def);
     def.nPortIndex = kPortIndexOutput;
 
     err = mOMX->getParameter(
             mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
+    if(err != OK) {
+        ALOGE("Getting Video InPort Definition failed");
+        return err;
+    }
 
-    CHECK_EQ(err, (status_t)OK);
-    CHECK_EQ((int)def.eDomain, (int)OMX_PortDomainVideo);
+    if((int)def.eDomain != (int)OMX_PortDomainVideo) {
+        ALOGE("Output port: Not a Video Domain");
+        return UNKNOWN_ERROR;
+    }
 
     video_def->nFrameWidth = width;
     video_def->nFrameHeight = height;
@@ -864,7 +1167,10 @@
 
     err = mOMX->setParameter(
             mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
-    CHECK_EQ(err, (status_t)OK);
+    if(err != OK) {
+        ALOGE("Setting Video OutPort Definition failed");
+        return err;
+    }
 
     /////////////////// Codec-specific ////////////////////////
     switch (compressionFormat) {
@@ -888,6 +1194,7 @@
             CHECK(!"Support for this compressionFormat to be implemented.");
             break;
     }
+    return OK;
 }
 
 static OMX_U32 setPFramesSpacing(int32_t iFramesInterval, int32_t frameRate) {
@@ -1017,6 +1324,10 @@
     h263type.nAllowedPictureTypes =
         OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
 
+#ifdef QCOM_HARDWARE
+    ExtendedUtils::HFR::reCalculateHFRParams(meta, frameRate, bitRate);
+#endif
+
     h263type.nPFrames = setPFramesSpacing(iFramesInterval, frameRate);
     if (h263type.nPFrames == 0) {
         h263type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI;
@@ -1068,6 +1379,10 @@
     mpeg4type.nAllowedPictureTypes =
         OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
 
+#ifdef QCOM_HARDWARE
+    ExtendedUtils::HFR::reCalculateHFRParams(meta, frameRate, bitRate);
+#endif
+
     mpeg4type.nPFrames = setPFramesSpacing(iFramesInterval, frameRate);
     if (mpeg4type.nPFrames == 0) {
         mpeg4type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI;
@@ -1089,6 +1404,9 @@
     mpeg4type.eProfile = static_cast<OMX_VIDEO_MPEG4PROFILETYPE>(profileLevel.mProfile);
     mpeg4type.eLevel = static_cast<OMX_VIDEO_MPEG4LEVELTYPE>(profileLevel.mLevel);
 
+#ifdef QCOM_HARDWARE
+    ExtendedUtils::setBFrames(mpeg4type, mNumBFrames, mComponentName);
+#endif
     err = mOMX->setParameter(
             mNode, OMX_IndexParamVideoMpeg4, &mpeg4type, sizeof(mpeg4type));
     CHECK_EQ(err, (status_t)OK);
@@ -1126,8 +1444,21 @@
     h264type.eProfile = static_cast<OMX_VIDEO_AVCPROFILETYPE>(profileLevel.mProfile);
     h264type.eLevel = static_cast<OMX_VIDEO_AVCLEVELTYPE>(profileLevel.mLevel);
 
+#ifdef QCOM_HARDWARE
+    ExtendedUtils::HFR::reCalculateHFRParams(meta, frameRate, bitRate);
+#endif
+
     // XXX
+#ifdef USE_TI_DUCATI_H264_PROFILE
+    if ((strncmp(mComponentName, "OMX.TI.DUCATI1", 14) != 0)
+            && (h264type.eProfile != OMX_VIDEO_AVCProfileBaseline)) {
+#elif defined (QCOM_HARDWARE)
+    if (ExtendedUtils::isAVCProfileSupported(h264type.eProfile)){
+        ALOGI("Profile type is  %d ",h264type.eProfile);
+    } else if (h264type.eProfile != OMX_VIDEO_AVCProfileBaseline) {
+#else
     if (h264type.eProfile != OMX_VIDEO_AVCProfileBaseline) {
+#endif
         ALOGW("Use baseline profile instead of %d for AVC recording",
             h264type.eProfile);
         h264type.eProfile = OMX_VIDEO_AVCProfileBaseline;
@@ -1152,6 +1483,10 @@
         h264type.nCabacInitIdc = 0;
     }
 
+#ifdef QCOM_HARDWARE
+    ExtendedUtils::setBFrames(
+            h264type, mNumBFrames, iFramesInterval, frameRate, mComponentName);
+#endif
     if (h264type.nBFrames != 0) {
         h264type.nAllowedPictureTypes |= OMX_VIDEO_PictureTypeB;
     }
@@ -1197,8 +1532,16 @@
     } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG2, mime)) {
         compressionFormat = OMX_VIDEO_CodingMPEG2;
     } else {
+#ifdef QCOM_HARDWARE
+        status_t err = ExtendedCodec::setVideoOutputFormat(mime,&compressionFormat);
+
+        if(err != OK) {
+#endif
         ALOGE("Not a supported video mime type: %s", mime);
         CHECK(!"Should not be here. Not a supported video mime type.");
+#ifdef QCOM_HARDWARE
+        }
+#endif
     }
 
     status_t err = setVideoPortFormatType(
@@ -1221,6 +1564,30 @@
         CHECK_EQ(err, (status_t)OK);
         CHECK_EQ((int)format.eCompressionFormat, (int)OMX_VIDEO_CodingUnused);
 
+#if 0
+        CHECK(format.eColorFormat == OMX_COLOR_FormatYUV420Planar
+               || format.eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar
+               || format.eColorFormat == OMX_COLOR_FormatCbYCrY
+               || format.eColorFormat == OMX_TI_COLOR_FormatYUV420PackedSemiPlanar
+               || format.eColorFormat == OMX_QCOM_COLOR_FormatYVU420SemiPlanar
+               || format.eColorFormat == OMX_QCOM_COLOR_FormatYUV420PackedSemiPlanar64x32Tile2m8ka
+#ifdef USE_SAMSUNG_COLORFORMAT
+               || format.eColorFormat == OMX_SEC_COLOR_FormatNV12TPhysicalAddress
+               || format.eColorFormat == OMX_SEC_COLOR_FormatNV12Tiled
+#endif
+               );
+
+#ifdef USE_SAMSUNG_COLORFORMAT
+        if (!strncmp("OMX.SEC.", mComponentName, 8)) {
+            if (mNativeWindow == NULL)
+                format.eColorFormat = OMX_COLOR_FormatYUV420Planar;
+            else
+                format.eColorFormat = OMX_COLOR_FormatYUV420SemiPlanar;
+        }
+#endif
+
+#endif
+
         int32_t colorFormat;
         if (meta->findInt32(kKeyColorFormat, &colorFormat)
                 && colorFormat != OMX_COLOR_FormatUnused
@@ -1264,7 +1631,11 @@
 
 #if 1
     // XXX Need a (much) better heuristic to compute input buffer sizes.
+#ifdef USE_SAMSUNG_COLORFORMAT
+    const size_t X = 64 * 8 * 1024;
+#else
     const size_t X = 64 * 1024;
+#endif
     if (def.nBufferSize < X) {
         def.nBufferSize = X;
     }
@@ -1331,6 +1702,9 @@
       mState(LOADED),
       mInitialBufferSubmit(true),
       mSignalledEOS(false),
+#ifdef QCOM_HARDWARE
+      mFinalStatus(OK),
+#endif
       mNoMoreOutputData(false),
       mOutputPortSettingsHaveChanged(false),
       mSeekTimeUs(-1),
@@ -1342,7 +1716,13 @@
       mPaused(false),
       mNativeWindow(
               (!strncmp(componentName, "OMX.google.", 11))
+#ifdef QCOM_HARDWARE
+                        ? NULL : nativeWindow),
+      mNumBFrames(0),
+      mInSmoothStreamingMode(false) {
+#else
                         ? NULL : nativeWindow) {
+#endif
     mPortStatus[kPortIndexInput] = ENABLED;
     mPortStatus[kPortIndexOutput] = ENABLED;
 
@@ -1370,6 +1750,10 @@
             "audio_decoder.amrnb", "audio_encoder.amrnb" },
         { MEDIA_MIMETYPE_AUDIO_AMR_WB,
             "audio_decoder.amrwb", "audio_encoder.amrwb" },
+#ifdef ENABLE_AV_ENHANCEMENTS
+        { MEDIA_MIMETYPE_AUDIO_AMR_WB_PLUS,
+            "audio_decoder.amrwbplus", "audio_encoder.amrwbplus" },
+#endif
         { MEDIA_MIMETYPE_AUDIO_AAC,
             "audio_decoder.aac", "audio_encoder.aac" },
         { MEDIA_MIMETYPE_AUDIO_VORBIS,
@@ -1378,6 +1762,12 @@
             "audio_decoder.g711mlaw", "audio_encoder.g711mlaw" },
         { MEDIA_MIMETYPE_AUDIO_G711_ALAW,
             "audio_decoder.g711alaw", "audio_encoder.g711alaw" },
+#ifdef ENABLE_AV_ENHANCEMENTS
+        { MEDIA_MIMETYPE_AUDIO_EVRC,
+            "audio_decoder.evrchw", "audio_encoder.evrc" },
+        { MEDIA_MIMETYPE_AUDIO_QCELP,
+            "audio_decoder,qcelp13Hw", "audio_encoder.qcelp13" },
+#endif
         { MEDIA_MIMETYPE_VIDEO_AVC,
             "video_decoder.avc", "video_encoder.avc" },
         { MEDIA_MIMETYPE_VIDEO_MPEG4,
@@ -1394,6 +1784,16 @@
             "audio_decoder.flac", "audio_encoder.flac" },
         { MEDIA_MIMETYPE_AUDIO_MSGSM,
             "audio_decoder.gsm", "audio_encoder.gsm" },
+#ifdef ENABLE_AV_ENHANCEMENTS
+        { MEDIA_MIMETYPE_VIDEO_DIVX,
+            "video_decoder.divx", NULL },
+        { MEDIA_MIMETYPE_AUDIO_AC3,
+            "audio_decoder.ac3", NULL },
+        { MEDIA_MIMETYPE_AUDIO_EAC3,
+            "audio_decoder.eac3", NULL },
+        { MEDIA_MIMETYPE_VIDEO_DIVX311,
+            "video_decoder.divx", NULL },
+#endif
     };
 
     static const size_t kNumMimeToRole =
@@ -1407,6 +1807,9 @@
     }
 
     if (i == kNumMimeToRole) {
+#ifdef QCOM_HARDWARE
+        ExtendedCodec::setSupportedRole(omx, node, isEncoder, mime);
+#endif
         return;
     }
 
@@ -1493,6 +1896,10 @@
     return state == LOADED_TO_IDLE
         || state == IDLE_TO_EXECUTING
         || state == EXECUTING_TO_IDLE
+#ifdef QCOM_HARDWARE
+        || state == PAUSING
+        || state == FLUSHING
+#endif
         || state == IDLE_TO_LOADED
         || state == RECONFIGURING;
 }
@@ -1713,11 +2120,34 @@
         return err;
     }
 
+#ifndef USE_SAMSUNG_COLORFORMAT
     err = native_window_set_buffers_geometry(
             mNativeWindow.get(),
             def.format.video.nFrameWidth,
             def.format.video.nFrameHeight,
             def.format.video.eColorFormat);
+#else
+    OMX_COLOR_FORMATTYPE eColorFormat;
+
+    switch (def.format.video.eColorFormat) {
+    case OMX_SEC_COLOR_FormatNV12TPhysicalAddress:
+        eColorFormat = (OMX_COLOR_FORMATTYPE)HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_SP_TILED;
+        break;
+    case OMX_COLOR_FormatYUV420SemiPlanar:
+        eColorFormat = (OMX_COLOR_FORMATTYPE)HAL_PIXEL_FORMAT_YCbCr_420_SP;
+        break;
+    case OMX_COLOR_FormatYUV420Planar:
+    default:
+        eColorFormat = (OMX_COLOR_FORMATTYPE)HAL_PIXEL_FORMAT_YCbCr_420_P;
+        break;
+    }
+
+    err = native_window_set_buffers_geometry(
+            mNativeWindow.get(),
+            def.format.video.nFrameWidth,
+            def.format.video.nFrameHeight,
+            eColorFormat);
+#endif
 
     if (err != 0) {
         ALOGE("native_window_set_buffers_geometry failed: %s (%d)",
@@ -1762,8 +2192,10 @@
     }
 
     ALOGV("native_window_set_usage usage=0x%lx", usage);
+
     err = native_window_set_usage(
             mNativeWindow.get(), usage | GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_EXTERNAL_DISP);
+
     if (err != 0) {
         ALOGE("native_window_set_usage failed: %s (%d)", strerror(-err), -err);
         return err;
@@ -1778,12 +2210,23 @@
         return err;
     }
 
+#ifdef QCOM_HARDWARE
+    //add an extra buffer to display queue to get around dequeue+wait
+    //blocking too long (more than 1 Vsync) in case BufferQeuue is in
+    //sync-mode and advertizes only 1 buffer
+    //NOTE: This is not necessary for 30fps content, but adding a buffer
+    //      regardless this root-cause is identified in SF
+    minUndequeuedBufs++;
+    ALOGI("NOTE: Overriding minUndequeuedBufs to %d",minUndequeuedBufs);
+#endif
+
     // XXX: Is this the right logic to use?  It's not clear to me what the OMX
     // buffer counts refer to - how do they account for the renderer holding on
     // to buffers?
     if (def.nBufferCountActual < def.nBufferCountMin + minUndequeuedBufs) {
         OMX_U32 newBufferCount = def.nBufferCountMin + minUndequeuedBufs;
         def.nBufferCountActual = newBufferCount;
+        ALOGI("NOTE: Allocating %lu buffers on output port",def.nBufferCountActual);
         err = mOMX->setParameter(
                 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
         if (err != OK) {
@@ -1801,6 +2244,15 @@
         return err;
     }
 
+#ifdef QCOM_HARDWARE
+    err = mNativeWindow.get()->perform(mNativeWindow.get(),
+                             NATIVE_WINDOW_SET_BUFFERS_SIZE, def.nBufferSize);
+    if (err != 0) {
+        ALOGE("native_window_set_buffers_size failed: %s (%d)", strerror(-err),
+                -err);
+        return err;
+    }
+#endif
     CODEC_LOGV("allocating %lu buffers from a native window of size %lu on "
             "output port", def.nBufferCountActual, def.nBufferSize);
 
@@ -1851,9 +2303,15 @@
         cancelEnd = def.nBufferCountActual;
     }
 
-    for (OMX_U32 i = cancelStart; i < cancelEnd; i++) {
-        BufferInfo *info = &mPortBuffers[kPortIndexOutput].editItemAt(i);
-        cancelBufferToNativeWindow(info);
+
+    if (err != 0 &&
+        ((mState == LOADED) || (mState == LOADED_TO_IDLE))) {
+        freeBuffersOnPort(kPortIndexOutput);
+    } else {
+        for (OMX_U32 i = cancelStart; i < cancelEnd; i++) {
+            BufferInfo *info = &mPortBuffers[kPortIndexOutput].editItemAt(i);
+            cancelBufferToNativeWindow(info);
+        }
     }
 
     return err;
@@ -2118,6 +2576,14 @@
 
             // Buffer could not be released until empty buffer done is called.
             if (info->mMediaBuffer != NULL) {
+#ifdef OMAP_ENHANCEMENT
+                if (mIsEncoder &&
+                    (mQuirks & kAvoidMemcopyInputRecordingFrames)) {
+                    // If zero-copy mode is enabled this will send the
+                    // input buffer back to the upstream source.
+                    restorePatchedDataPointer(info);
+                }
+#endif
                 info->mMediaBuffer->release();
                 info->mMediaBuffer = NULL;
             }
@@ -2547,11 +3013,22 @@
 
             CODEC_LOGV("FLUSH_DONE(%ld)", portIndex);
 
+#ifdef QCOM_HARDWARE
+            if (portIndex == (OMX_U32) -1) {
+                CHECK_EQ((int)mPortStatus[kPortIndexInput], (int)SHUTTING_DOWN);
+                mPortStatus[kPortIndexInput] = ENABLED;
+                CHECK_EQ((int)mPortStatus[kPortIndexOutput], (int)SHUTTING_DOWN);
+                mPortStatus[kPortIndexOutput] = ENABLED;
+            } else {
+#endif
             CHECK_EQ((int)mPortStatus[portIndex], (int)SHUTTING_DOWN);
             mPortStatus[portIndex] = ENABLED;
 
             CHECK_EQ(countBuffersWeOwn(mPortBuffers[portIndex]),
                      mPortBuffers[portIndex].size());
+#ifdef QCOM_HARDWARE
+            }
+#endif
 
             if (mSkipCutBuffer != NULL && mPortStatus[kPortIndexOutput] == ENABLED) {
                 mSkipCutBuffer->clear();
@@ -2658,14 +3135,34 @@
                 mPortStatus[kPortIndexInput] = ENABLED;
                 mPortStatus[kPortIndexOutput] = ENABLED;
 
-                if ((mFlags & kEnableGrallocUsageProtected) &&
-                        mNativeWindow != NULL) {
-                    // We push enough 1x1 blank buffers to ensure that one of
-                    // them has made it to the display.  This allows the OMX
-                    // component teardown to zero out any protected buffers
-                    // without the risk of scanning out one of those buffers.
-                    pushBlankBuffersToNativeWindow();
+#ifdef QCOM_HARDWARE
+                if (mNativeWindow != NULL) {
+                    /*
+                     * reset buffer size field with SurfaceTexture
+                     * back to 0. This will ensure proper size
+                     * buffers are allocated if the same SurfaceTexture
+                     * is re-used in a different decode session
+                     */
+                    int err =
+                        mNativeWindow.get()->perform(mNativeWindow.get(),
+                                                     NATIVE_WINDOW_SET_BUFFERS_SIZE,
+                                                     0);
+                    if (err != 0) {
+                        ALOGE("set_buffers_size failed: %s (%d)", strerror(-err),
+                             -err);
+                    }
+#endif
+
+                    if (mFlags & kEnableGrallocUsageProtected) {
+                        // We push enough 1x1 blank buffers to ensure that one of
+                        // them has made it to the display.  This allows the OMX
+                        // component teardown to zero out any protected buffers
+                        // without the risk of scanning out one of those buffers.
+                        pushBlankBuffersToNativeWindow();
+                    }
+#ifdef QCOM_HARDWARE
                 }
+#endif
 
                 setState(IDLE_TO_LOADED);
             }
@@ -2700,6 +3197,16 @@
             break;
         }
 
+#ifdef QCOM_HARDWARE
+        case OMX_StatePause:
+        {
+            CODEC_LOGV("Now paused.");
+            CHECK_EQ((int)mState, (int)PAUSING);
+            setState(PAUSED);
+            break;
+        }
+#endif
+
         case OMX_StateInvalid:
         {
             setState(ERROR);
@@ -2814,8 +3321,18 @@
 
 bool OMXCodec::flushPortAsync(OMX_U32 portIndex) {
     CHECK(mState == EXECUTING || mState == RECONFIGURING
+#ifdef QCOM_HARDWARE
+            || mState == EXECUTING_TO_IDLE || mState == FLUSHING);
+#else
             || mState == EXECUTING_TO_IDLE);
+#endif
 
+#ifdef QCOM_HARDWARE
+    if (portIndex == (OMX_U32) -1 ) {
+        mPortStatus[kPortIndexInput] = SHUTTING_DOWN;
+        mPortStatus[kPortIndexOutput] = SHUTTING_DOWN;
+    } else {
+#endif
     CODEC_LOGV("flushPortAsync(%ld): we own %d out of %d buffers already.",
          portIndex, countBuffersWeOwn(mPortBuffers[portIndex]),
          mPortBuffers[portIndex].size());
@@ -2831,6 +3348,9 @@
 
         return false;
     }
+#ifdef QCOM_HARDWARE
+    }
+#endif
 
     status_t err =
         mOMX->sendCommand(mNode, OMX_CommandFlush, portIndex);
@@ -2864,13 +3384,26 @@
 }
 
 void OMXCodec::fillOutputBuffers() {
+#ifdef QCOM_HARDWARE
+    CHECK(mState == EXECUTING || mState == FLUSHING);
+#else
     CHECK_EQ((int)mState, (int)EXECUTING);
+#endif
 
     // This is a workaround for some decoders not properly reporting
     // end-of-output-stream. If we own all input buffers and also own
     // all output buffers and we already signalled end-of-input-stream,
     // the end-of-output-stream is implied.
-    if (mSignalledEOS
+
+    // NOTE: Thumbnail mode needs a call to fillOutputBuffer in order
+    // to get the decoded frame from the component. Currently,
+    // thumbnail mode calls emptyBuffer with an EOS flag on its first
+    // frame and sets mSignalledEOS to true, so without the check for
+    // !mThumbnailMode, fillOutputBuffer will never be called.
+#ifdef QCOM_HARDWARE
+    if(!ExtendedUtils::checkIsThumbNailMode(mFlags, mComponentName)) {
+#endif
+        if (mSignalledEOS
             && countBuffersWeOwn(mPortBuffers[kPortIndexInput])
                 == mPortBuffers[kPortIndexInput].size()
             && countBuffersWeOwn(mPortBuffers[kPortIndexOutput])
@@ -2878,8 +3411,11 @@
         mNoMoreOutputData = true;
         mBufferFilled.signal();
 
-        return;
+            return;
+        }
+#ifdef QCOM_HARDWARE
     }
+#endif
 
     Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexOutput];
     for (size_t i = 0; i < buffers->size(); ++i) {
@@ -2891,7 +3427,11 @@
 }
 
 void OMXCodec::drainInputBuffers() {
+#ifdef QCOM_HARDWARE
+    CHECK(mState == EXECUTING || mState == RECONFIGURING || mState == FLUSHING);
+#else
     CHECK(mState == EXECUTING || mState == RECONFIGURING);
+#endif
 
     if (mFlags & kUseSecureInputBuffers) {
         Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexInput];
@@ -2914,7 +3454,12 @@
                 break;
             }
 
+#ifdef QCOM_HARDWARE
+            if ((mFlags & kOnlySubmitOneInputBufferAtOneTime)
+                    && (i == mNumBFrames)) {
+#else
             if (mFlags & kOnlySubmitOneInputBufferAtOneTime) {
+#endif
                 break;
             }
         }
@@ -3017,6 +3562,10 @@
 
     size_t offset = 0;
     int32_t n = 0;
+#ifdef QCOM_HARDWARE
+    int32_t InterlaceFormatDetected = false;
+    int32_t InterlaceFrameCount = 0;
+#endif
 
 
     for (;;) {
@@ -3064,6 +3613,11 @@
             break;
         }
 
+#ifdef QCOM_HARDWARE
+        sp<MetaData> metaData = mSource->getFormat();
+        InterlaceFormatDetected = ExtendedUtils::checkIsInterlace(metaData);
+#endif
+
         if (mFlags & kUseSecureInputBuffers) {
             info = findInputBufferByDataPointer(srcBuffer->data());
             CHECK(info != NULL);
@@ -3090,6 +3644,23 @@
         }
 
         bool releaseBuffer = true;
+#ifdef OMAP_ENHANCEMENT
+        if (mIsEncoder && (mQuirks & kAvoidMemcopyInputRecordingFrames)) {
+            CHECK(mOMXLivesLocally && offset == 0);
+
+            OMX_BUFFERHEADERTYPE *header =
+                (OMX_BUFFERHEADERTYPE *)info->mBuffer;
+
+            CHECK(header->pBuffer == info->mData);
+
+            header->pBuffer =
+                (OMX_U8 *)srcBuffer->data() + srcBuffer->range_offset();
+
+            releaseBuffer = false;
+            info->mMediaBuffer = srcBuffer;
+        } else {
+#endif
+
         if (mFlags & kStoreMetaDataInVideoBuffers) {
                 releaseBuffer = false;
                 info->mMediaBuffer = srcBuffer;
@@ -3103,13 +3674,53 @@
                 CHECK(info->mMediaBuffer == NULL);
                 info->mMediaBuffer = srcBuffer;
         } else {
+#ifdef USE_SAMSUNG_COLORFORMAT
+            OMX_PARAM_PORTDEFINITIONTYPE def;
+            InitOMXParams(&def);
+            def.nPortIndex = kPortIndexInput;
+
+            status_t err = mOMX->getParameter(mNode, OMX_IndexParamPortDefinition,
+            &def, sizeof(def));
+            CHECK_EQ(err, (status_t)OK);
+
+            if (def.eDomain == OMX_PortDomainVideo) {
+                OMX_VIDEO_PORTDEFINITIONTYPE *videoDef = &def.format.video;
+                switch (videoDef->eColorFormat) {
+                    case OMX_SEC_COLOR_FormatNV12LVirtualAddress: {
+                        CHECK(srcBuffer->data() != NULL);
+                        void *pSharedMem = (void *)(srcBuffer->data());
+                        memcpy((uint8_t *)info->mData + offset,
+                        (const void *)&pSharedMem, sizeof(void *));
+                        break;
+                    }
+                    default:
+                        CHECK(srcBuffer->data() != NULL);
+                        memcpy((uint8_t *)info->mData + offset,
+                        (const uint8_t *)srcBuffer->data()
+                        + srcBuffer->range_offset(),
+                        srcBuffer->range_length());
+                        break;
+                    }
+            } else {
+                CHECK(srcBuffer->data() != NULL);
+                memcpy((uint8_t *)info->mData + offset,
+                        (const uint8_t *)srcBuffer->data()
+                            + srcBuffer->range_offset(),
+                        srcBuffer->range_length());
+            }
+#else
             CHECK(srcBuffer->data() != NULL) ;
             memcpy((uint8_t *)info->mData + offset,
                     (const uint8_t *)srcBuffer->data()
                         + srcBuffer->range_offset(),
                     srcBuffer->range_length());
+#endif // USE_SAMSUNG_COLORFORMAT
         }
 
+#ifdef OMAP_ENHANCEMENT
+	}
+#endif
+
         int64_t lastBufferTimeUs;
         CHECK(srcBuffer->meta_data()->findInt64(kKeyTime, &lastBufferTimeUs));
         CHECK(lastBufferTimeUs >= 0);
@@ -3165,8 +3776,29 @@
 
     OMX_U32 flags = OMX_BUFFERFLAG_ENDOFFRAME;
 
+#ifdef QCOM_HARDWARE
+    if(InterlaceFormatDetected) {
+        InterlaceFrameCount++;
+    }
+#endif
+
     if (signalEOS) {
         flags |= OMX_BUFFERFLAG_EOS;
+#ifdef QCOM_HARDWARE
+    } else if(ExtendedUtils::checkIsThumbNailMode(mFlags, mComponentName)
+                   && (!InterlaceFormatDetected || InterlaceFrameCount>= 2)) {
+        // Because we don't get an EOS after getting the first frame, we
+        // need to notify the component with OMX_BUFFERFLAG_EOS, set
+        // mNoMoreOutputData to false so fillOutputBuffer gets called on
+        // the first output buffer (see comment in fillOutputBuffer), and
+        // mSignalledEOS must be true so drainInputBuffer is not executed
+        // on extra frames. Setting mFinalStatus to ERROR_END_OF_STREAM as
+        // we dont want to return OK and NULL buffer in read.
+        flags |= OMX_BUFFERFLAG_EOS;
+        mNoMoreOutputData = false;
+        mSignalledEOS = true;
+        mFinalStatus = ERROR_END_OF_STREAM;
+#endif
     } else {
         mNoMoreOutputData = false;
     }
@@ -3195,6 +3827,14 @@
         return false;
     }
 
+    // This component does not ever signal the EOS flag on output buffers,
+    // Thanks for nothing.
+    if (mSignalledEOS && (!strcmp(mComponentName, "OMX.TI.Video.encoder") || 
+                          !strcmp(mComponentName, "OMX.TI.720P.Encoder"))) {
+        mNoMoreOutputData = true;
+        mBufferFilled.signal();
+    }
+
     info->mStatus = OWNED_BY_COMPONENT;
 
     return true;
@@ -3265,6 +3905,11 @@
         return mBufferFilled.wait(mLock);
     }
     status_t err = mBufferFilled.waitRelative(mLock, kBufferFilledEventTimeOutNs);
+#ifdef QCOM_HARDWARE
+    if ((err == -ETIMEDOUT) && (mPaused == true)){
+        err = OK;
+    }
+#endif
     if (err != OK) {
         CODEC_LOGE("Timed out waiting for output buffers: %d/%d",
             countBuffersWeOwn(mPortBuffers[kPortIndexInput]),
@@ -3280,6 +3925,9 @@
     OMX_PARAM_PORTDEFINITIONTYPE def;
     InitOMXParams(&def);
     def.nPortIndex = portIndex;
+#ifdef QCOM_HARDWARE
+    def.format.audio.cMIMEType = NULL;
+#endif
     status_t err = mOMX->getParameter(
             mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
     CHECK_EQ(err, (status_t)OK);
@@ -3612,6 +4260,29 @@
 status_t OMXCodec::start(MetaData *meta) {
     Mutex::Autolock autoLock(mLock);
 
+#ifdef QCOM_HARDWARE
+    if (mPaused) {
+        if (!strncmp(mComponentName, "OMX.qcom.", 9)) {
+            while (isIntermediateState(mState)) {
+                mAsyncCompletion.wait(mLock);
+            }
+            CHECK_EQ(mState, (status_t)PAUSED);
+            status_t err = mOMX->sendCommand(mNode,OMX_CommandStateSet, OMX_StateExecuting);
+            CHECK_EQ(err, (status_t)OK);
+            setState(IDLE_TO_EXECUTING);
+            mPaused = false;
+            while (mState != EXECUTING && mState != ERROR) {
+                mAsyncCompletion.wait(mLock);
+            }
+            drainInputBuffers();
+            return mState == ERROR ? UNKNOWN_ERROR : OK;
+        } else {   // SW Codec
+            mPaused = false;
+            return OK;
+        }
+    }
+#endif
+
     if (mState != LOADED) {
         CODEC_LOGE("called start in the unexpected state: %d", mState);
         return UNKNOWN_ERROR;
@@ -3722,6 +4393,9 @@
             isError = true;
         }
 
+#ifdef QCOM_HARDWARE
+        case PAUSED:
+#endif
         case EXECUTING:
         {
             setState(EXECUTING_TO_IDLE);
@@ -3730,6 +4404,16 @@
                 CODEC_LOGV("This component requires a flush before transitioning "
                      "from EXECUTING to IDLE...");
 
+#ifdef QCOM_HARDWARE
+                //DSP supports flushing of ports simultaneously.
+                //Flushing individual port is not supported.
+                if(mQuirks & kRequiresGlobalFlush) {
+                    bool emulateFlushCompletion = !flushPortAsync(kPortIndexBoth);
+                    if (emulateFlushCompletion) {
+                        onCmdComplete(OMX_CommandFlush, kPortIndexBoth);
+                    }
+                } else {
+#endif
                 bool emulateInputFlushCompletion =
                     !flushPortAsync(kPortIndexInput);
 
@@ -3743,6 +4427,9 @@
                 if (emulateOutputFlushCompletion) {
                     onCmdComplete(OMX_CommandFlush, kPortIndexOutput);
                 }
+#ifdef QCOM_HARDWARE
+                }
+#endif
             } else {
                 mPortStatus[kPortIndexInput] = SHUTTING_DOWN;
                 mPortStatus[kPortIndexOutput] = SHUTTING_DOWN;
@@ -3849,7 +4536,24 @@
         mFilledBuffers.clear();
 
         CHECK_EQ((int)mState, (int)EXECUTING);
+#ifdef QCOM_HARDWARE
+        setState(FLUSHING);
 
+        if(mQuirks & kRequiresGlobalFlush) {
+            bool emulateFlushCompletion = !flushPortAsync(kPortIndexBoth);
+            if (emulateFlushCompletion) {
+                onCmdComplete(OMX_CommandFlush, kPortIndexBoth);
+            }
+        } else {
+        //DSP supports flushing of ports simultaneously.
+        //Flushing individual port is not supported.
+        if(mQuirks & kRequiresGlobalFlush) {
+            bool emulateFlushCompletion = !flushPortAsync(kPortIndexBoth);
+            if (emulateFlushCompletion) {
+                onCmdComplete(OMX_CommandFlush, kPortIndexBoth);
+            }
+        } else {
+#endif
         bool emulateInputFlushCompletion = !flushPortAsync(kPortIndexInput);
         bool emulateOutputFlushCompletion = !flushPortAsync(kPortIndexOutput);
 
@@ -3860,6 +4564,10 @@
         if (emulateOutputFlushCompletion) {
             onCmdComplete(OMX_CommandFlush, kPortIndexOutput);
         }
+#ifdef QCOM_HARDWARE
+        }
+        }
+#endif
 
         while (mSeekTimeUs >= 0) {
             if ((err = waitForBufferFilled_l()) != OK) {
@@ -3870,6 +4578,15 @@
 
     while (mState != ERROR && !mNoMoreOutputData && mFilledBuffers.empty()) {
         if ((err = waitForBufferFilled_l()) != OK) {
+#ifdef QCOM_HARDWARE
+            if ((err == -ETIMEDOUT) && (mPaused == true) && !mIsVideo) {
+                // When the audio playback is paused, the fill buffer maybe timed out
+                // if input data is not available to decode. Hence, considering the
+                // timed out as a valid case.
+                ALOGV("returned OK instead of timedout from read() as mPaused is true");
+                err = OK;
+            }
+#endif
             return err;
         }
     }
@@ -3878,6 +4595,13 @@
         return UNKNOWN_ERROR;
     }
 
+#ifdef QCOM_HARDWARE
+    if (seeking) {
+        CHECK_EQ((int)mState, (int)FLUSHING);
+        setState(EXECUTING);
+    }
+#endif
+
     if (mFilledBuffers.empty()) {
         return mSignalledEOS ? mFinalStatus : ERROR_END_OF_STREAM;
     }
@@ -4025,7 +4749,22 @@
 
     if (type == OMX_TI_COLOR_FormatYUV420PackedSemiPlanar) {
         return "OMX_TI_COLOR_FormatYUV420PackedSemiPlanar";
-    } else if (type == OMX_QCOM_COLOR_FormatYVU420SemiPlanar) {
+    }
+#ifdef USE_SAMSUNG_COLORFORMAT
+    if (type == OMX_SEC_COLOR_FormatNV12TPhysicalAddress) {
+        return "OMX_SEC_COLOR_FormatNV12TPhysicalAddress";
+    }
+    if (type == OMX_SEC_COLOR_FormatNV12LPhysicalAddress) {
+        return "OMX_SEC_COLOR_FormatNV12LPhysicalAddress";
+    }
+    if (type == OMX_SEC_COLOR_FormatNV12LVirtualAddress) {
+        return "OMX_SEC_COLOR_FormatNV12LVirtualAddress";
+    }
+    if (type == OMX_SEC_COLOR_FormatNV12Tiled) {
+        return "OMX_SEC_COLOR_FormatNV12Tiled";
+    }
+#endif // USE_SAMSUNG_COLORFORMAT
+    else if (type == OMX_QCOM_COLOR_FormatYVU420SemiPlanar) {
         return "OMX_QCOM_COLOR_FormatYVU420SemiPlanar";
     } else if (type < 0 || (size_t)type >= numNames) {
         return "UNKNOWN";
@@ -4086,6 +4825,9 @@
         "OMX_AUDIO_CodingWMA",
         "OMX_AUDIO_CodingRA",
         "OMX_AUDIO_CodingMIDI",
+#ifdef DOLBY_UDC
+        "OMX_AUDIO_CodingDDP",
+#endif // DOLBY_UDC
     };
 
     size_t numNames = sizeof(kNames) / sizeof(kNames[0]);
@@ -4423,7 +5165,25 @@
                 mOutputFormat->setInt32(kKeySampleRate, sampleRate);
                 mOutputFormat->setInt32(kKeyBitRate, bitRate);
             } else {
+#ifdef QCOM_HARDWARE
+                AString mimeType;
+                if (OK == ExtendedCodec::handleSupportedAudioFormats(
+                        audio_def->eEncoding, &mimeType)) {
+                    mOutputFormat->setCString(
+                            kKeyMIMEType, mimeType.c_str());
+                    int32_t numChannels, sampleRate, bitRate;
+                    inputFormat->findInt32(kKeyChannelCount, &numChannels);
+                    inputFormat->findInt32(kKeySampleRate, &sampleRate);
+                    inputFormat->findInt32(kKeyBitRate, &bitRate);
+                    mOutputFormat->setInt32(kKeyChannelCount, numChannels);
+                    mOutputFormat->setInt32(kKeySampleRate, sampleRate);
+                    mOutputFormat->setInt32(kKeyBitRate, bitRate);
+                } else {
+#endif
                 CHECK(!"Should not be here. Unknown audio encoding.");
+#ifdef QCOM_HARDWARE
+                }
+#endif
             }
             break;
         }
@@ -4492,8 +5252,19 @@
                 }
 
                 if (mNativeWindow != NULL) {
-                     initNativeWindowCrop();
+#ifdef QCOM_HARDWARE
+                    if (mInSmoothStreamingMode) {
+                        ExtendedUtils::updateNativeWindowBufferGeometry(
+                                mNativeWindow.get(), video_def->nFrameWidth,
+                                video_def->nFrameHeight, video_def->eColorFormat);
+                    }
+#endif
+                    initNativeWindowCrop();
                 }
+#ifdef QCOM_HARDWARE
+            } else {
+                ExtendedUtils::HFR::copyHFRParams(inputFormat, mOutputFormat);
+#endif
             }
             break;
         }
@@ -4515,15 +5286,46 @@
 }
 
 status_t OMXCodec::pause() {
+    CODEC_LOGV("pause mState=%d", mState);
+
     Mutex::Autolock autoLock(mLock);
-
-    mPaused = true;
-
-    return OK;
+#ifdef QCOM_HARDWARE
+    if (mState != EXECUTING) {
+        return UNKNOWN_ERROR;
+    }
+    while (isIntermediateState(mState)) {
+        mAsyncCompletion.wait(mLock);
+    }
+    if (!strncmp(mComponentName, "OMX.qcom.", 9)) {
+        status_t err = mOMX->sendCommand(mNode,
+            OMX_CommandStateSet, OMX_StatePause);
+        CHECK_EQ(err, (status_t)OK);
+        setState(PAUSING);
+        mPaused = true;
+        while (mState != PAUSED && mState != ERROR) {
+            mAsyncCompletion.wait(mLock);
+        }
+        return mState == ERROR ? UNKNOWN_ERROR : OK;
+    } else {
+#endif
+        mPaused = true;
+        return OK;
+#ifdef QCOM_HARDWARE
+    }
+#endif
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 
+#ifdef OMAP_ENHANCEMENT
+void OMXCodec::restorePatchedDataPointer(BufferInfo *info) {
+    CHECK(mIsEncoder && (mQuirks & kAvoidMemcopyInputRecordingFrames));
+    CHECK(mOMXLivesLocally);
+
+    OMX_BUFFERHEADERTYPE *header = (OMX_BUFFERHEADERTYPE *)info->mBuffer;
+    header->pBuffer = (OMX_U8 *)info->mData;
+}
+#endif
 status_t QueryCodecs(
         const sp<IOMX> &omx,
         const char *mime, bool queryDecoders, bool hwCodecOnly,
@@ -4603,8 +5405,13 @@
     // Color format query
     OMX_VIDEO_PARAM_PORTFORMATTYPE portFormat;
     InitOMXParams(&portFormat);
+#ifdef OMAP_ENHANCEMENT
+    portFormat.nPortIndex = !isEncoder ? 0 : 1;
+#else
     portFormat.nPortIndex = !isEncoder ? 1 : 0;
-    for (portFormat.nIndex = 0;; ++portFormat.nIndex)  {
+#endif
+    for (OMX_U32 index = 0;;index++)  {
+        portFormat.nIndex = index;
         err = omx->getParameter(
                 node, OMX_IndexParamVideoPortFormat,
                 &portFormat, sizeof(portFormat));
diff --git a/media/libstagefright/SampleIterator.cpp b/media/libstagefright/SampleIterator.cpp
index eae721b..ee5c0d3 100644
--- a/media/libstagefright/SampleIterator.cpp
+++ b/media/libstagefright/SampleIterator.cpp
@@ -286,7 +286,7 @@
 }
 
 status_t SampleIterator::findSampleTime(
-        uint32_t sampleIndex, uint32_t *time) {
+        uint32_t sampleIndex, uint64_t *time) {
     if (sampleIndex >= mTable->mNumSampleSizes) {
         return ERROR_OUT_OF_RANGE;
     }
@@ -305,9 +305,9 @@
         ++mTimeToSampleIndex;
     }
 
-    *time = mTTSSampleTime + mTTSDuration * (sampleIndex - mTTSSampleIndex);
+    *time = mTTSSampleTime + (uint64_t)mTTSDuration * ((uint64_t)sampleIndex - (uint64_t)mTTSSampleIndex);
 
-    *time += mTable->getCompositionTimeOffset(sampleIndex);
+    *time += (int32_t)mTable->getCompositionTimeOffset(sampleIndex);
 
     return OK;
 }
diff --git a/media/libstagefright/SampleTable.cpp b/media/libstagefright/SampleTable.cpp
index d9858d7..9d86a0f 100644
--- a/media/libstagefright/SampleTable.cpp
+++ b/media/libstagefright/SampleTable.cpp
@@ -360,8 +360,9 @@
         return ERROR_IO;
     }
 
-    if (U32_AT(header) != 0) {
-        // Expected version = 0, flags = 0.
+    if (U32_AT(header) != 0 &&
+        U32_AT(header) != 0x01000000) {
+        // Expected version = 0/1, flags = 0.
         return ERROR_MALFORMED;
     }
 
@@ -460,7 +461,7 @@
     return OK;
 }
 
-uint32_t abs_difference(uint32_t time1, uint32_t time2) {
+uint64_t abs_difference(uint64_t time1, uint64_t time2) {
     return time1 > time2 ? time1 - time2 : time2 - time1;
 }
 
@@ -488,7 +489,7 @@
     mSampleTimeEntries = new SampleTimeEntry[mNumSampleSizes];
 
     uint32_t sampleIndex = 0;
-    uint32_t sampleTime = 0;
+    uint64_t sampleTime = 0;
 
     for (uint32_t i = 0; i < mTimeToSampleCount; ++i) {
         uint32_t n = mTimeToSample[2 * i];
@@ -520,14 +521,14 @@
 }
 
 status_t SampleTable::findSampleAtTime(
-        uint32_t req_time, uint32_t *sample_index, uint32_t flags) {
+        uint64_t req_time, uint32_t *sample_index, uint32_t flags) {
     buildSampleEntriesTable();
 
     uint32_t left = 0;
     uint32_t right = mNumSampleSizes;
     while (left < right) {
         uint32_t center = (left + right) / 2;
-        uint32_t centerTime = mSampleTimeEntries[center].mCompositionTime;
+        uint64_t centerTime = mSampleTimeEntries[center].mCompositionTime;
 
         if (req_time < centerTime) {
             right = center;
@@ -576,12 +577,12 @@
 
             if (closestIndex > 0) {
                 // Check left neighbour and pick closest.
-                uint32_t absdiff1 =
+                uint64_t absdiff1 =
                     abs_difference(
                             mSampleTimeEntries[closestIndex].mCompositionTime,
                             req_time);
 
-                uint32_t absdiff2 =
+                uint64_t absdiff2 =
                     abs_difference(
                             mSampleTimeEntries[closestIndex - 1].mCompositionTime,
                             req_time);
@@ -656,20 +657,20 @@
             return err;
         }
 
-        uint32_t sample_time = mSampleIterator->getSampleTime();
+        uint64_t sample_time = mSampleIterator->getSampleTime();
 
         err = mSampleIterator->seekTo(x);
         if (err != OK) {
             return err;
         }
-        uint32_t x_time = mSampleIterator->getSampleTime();
+        uint64_t x_time = mSampleIterator->getSampleTime();
 
         err = mSampleIterator->seekTo(y);
         if (err != OK) {
             return err;
         }
 
-        uint32_t y_time = mSampleIterator->getSampleTime();
+        uint64_t y_time = mSampleIterator->getSampleTime();
 
         if (abs_difference(x_time, sample_time)
                 > abs_difference(y_time, sample_time)) {
@@ -777,7 +778,7 @@
         uint32_t sampleIndex,
         off64_t *offset,
         size_t *size,
-        uint32_t *compositionTime,
+        uint64_t *compositionTime,
         bool *isSyncSample) {
     Mutex::Autolock autoLock(mLock);
 
diff --git a/media/libstagefright/StagefrightMediaScanner.cpp b/media/libstagefright/StagefrightMediaScanner.cpp
index af8186c..98ba1a4 100644
--- a/media/libstagefright/StagefrightMediaScanner.cpp
+++ b/media/libstagefright/StagefrightMediaScanner.cpp
@@ -43,6 +43,9 @@
         ".wav", ".amr", ".midi", ".xmf", ".rtttl", ".rtx", ".ota",
         ".mkv", ".mka", ".webm", ".ts", ".fl", ".flac", ".mxmf",
         ".avi", ".mpeg", ".mpg", ".awb", ".mpga"
+#ifdef ENABLE_AV_ENHANCEMENTS
+        ,".qcp", ".ac3", ".dts", ".wmv", ".ec3"
+#endif
     };
     static const size_t kNumValidExtensions =
         sizeof(kValidExtensions) / sizeof(kValidExtensions[0]);
diff --git a/media/libstagefright/StagefrightMetadataRetriever.cpp b/media/libstagefright/StagefrightMetadataRetriever.cpp
index 19af4fb..0de6249 100644
--- a/media/libstagefright/StagefrightMetadataRetriever.cpp
+++ b/media/libstagefright/StagefrightMetadataRetriever.cpp
@@ -148,8 +148,16 @@
     // XXX:
     // Once all vendors support OMX_COLOR_FormatYUV420Planar, we can
     // remove this check and always set the decoder output color format
+    // skip this check for software decoders
+#ifndef QCOM_HARDWARE
     if (isYUV420PlanarSupported(client, trackMeta)) {
         format->setInt32(kKeyColorFormat, OMX_COLOR_FormatYUV420Planar);
+#else
+    if (!(flags & OMXCodec::kSoftwareCodecsOnly)) {
+        if (isYUV420PlanarSupported(client, trackMeta)) {
+            format->setInt32(kKeyColorFormat, OMX_COLOR_FormatYUV420Planar);
+        }
+#endif
     }
 
     sp<MediaSource> decoder =
@@ -382,7 +390,11 @@
 
     VideoFrame *frame =
         extractVideoFrameWithCodecFlags(
+#ifndef QCOM_HARDWARE
                 &mClient, trackMeta, source, OMXCodec::kPreferSoftwareCodecs,
+#else
+                &mClient, trackMeta, source, OMXCodec::kSoftwareCodecsOnly,
+#endif
                 timeUs, option);
 
     if (frame == NULL) {
diff --git a/media/libstagefright/TunnelPlayer.cpp b/media/libstagefright/TunnelPlayer.cpp
new file mode 100644
index 0000000..9aacbb6
--- /dev/null
+++ b/media/libstagefright/TunnelPlayer.cpp
@@ -0,0 +1,798 @@
+/*
+ * Copyright (c) 2009-2013, The Linux Foundation. All rights reserved.
+ * Not a Contribution.
+ * Copyright (C) 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_NDEBUG 0
+//#define LOG_NDDEBUG 0
+#define LOG_TAG "TunnelPlayer"
+#include <utils/Log.h>
+#include <utils/threads.h>
+
+#include <signal.h>
+#include <sys/prctl.h>
+#include <binder/IPCThreadState.h>
+#include <media/AudioTrack.h>
+
+#include <media/stagefright/TunnelPlayer.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/ALooper.h>
+#include <media/stagefright/MediaErrors.h>
+#include <media/stagefright/MediaSource.h>
+#include <media/stagefright/MetaData.h>
+#include <media/stagefright/MediaErrors.h>
+#include "include/AwesomePlayer.h"
+#include <cutils/properties.h>
+
+static const char   mName[] = "TunnelPlayer";
+#define MEM_METADATA_SIZE 64
+/*
+ * We need to reserve some space in the
+ * ion buffer (used in HAL) to save the
+ * metadata. so read from the extractor
+ * a somewhat smaller number of bytes.
+ * ideally this number should be bufer_size - sizeof(struct output_metadata_t)
+ */
+#define MEM_BUFFER_SIZE (240*1024 - MEM_METADATA_SIZE)
+#define MEM_BUFFER_COUNT 4
+#define TUNNEL_BUFFER_TIME 1500000
+
+namespace android {
+int TunnelPlayer::mTunnelObjectsAlive = 0;
+
+TunnelPlayer::TunnelPlayer(
+                    const sp<MediaPlayerBase::AudioSink> &audioSink, bool &initCheck,
+                    AwesomePlayer *observer, bool hasVideo)
+:AudioPlayer(audioSink, 0, observer),
+mPositionTimeMediaUs(-1),
+mPositionTimeRealUs(-1),
+mInternalSeeking(false),
+mStarted(false),
+mSampleRate(0),
+mLatencyUs(0),
+mFrameSize(0),
+mNumFramesPlayed(0),
+mNumFramesPlayedSysTimeUs(0),
+mInputBuffer(NULL),
+mSeeking(false),
+mReachedEOS(false),
+mReachedOutputEOS(false),
+mFinalStatus(OK),
+mSeekTimeUs(0),
+mPauseTime(0),
+mIsFirstBuffer(false),
+mFirstBufferResult(OK),
+mFirstBuffer(NULL),
+mAudioSink(audioSink),
+mObserver(observer) {
+    ALOGD("TunnelPlayer::TunnelPlayer()");
+    mTunnelObjectsAlive++;
+    numChannels = 0;
+    mPaused = false;
+    mFormat = AUDIO_FORMAT_MP3;
+    mQueue.start();
+    mQueueStarted      = true;
+    mPauseEvent        = new TunnelEvent(this, &TunnelPlayer::onPauseTimeOut);
+    mPauseEventPending = false;
+
+    mSeekTimeUs = 0;
+    mIsAudioRouted = false;
+    mExtractorThreadAlive = false;
+
+    mHasVideo = hasVideo;
+    initCheck = true;
+
+}
+const int TunnelPlayer::getTunnelObjectsAliveMax() {
+    char value[PROPERTY_VALUE_MAX];
+    property_get("tunnel.multiple", value, "0");
+    if (strcmp("true",value) == 0) {
+        return 4;
+    }
+    return 1;
+}
+
+TunnelPlayer::~TunnelPlayer() {
+    ALOGD("TunnelPlayer::~TunnelPlayer()");
+    if (mQueueStarted) {
+        mQueue.stop();
+    }
+
+    reset();
+    mTunnelObjectsAlive--;
+
+}
+
+void TunnelPlayer::setSource(const sp<MediaSource> &source) {
+    CHECK(mSource == NULL);
+    ALOGD("Setting source from Tunnel Player");
+    mSource = source;
+}
+
+status_t TunnelPlayer::start(bool sourceAlreadyStarted) {
+    CHECK(!mStarted);
+    CHECK(mSource != NULL);
+
+    ALOGV("start: sourceAlreadyStarted %d", sourceAlreadyStarted);
+    //Check if the source is started, start it
+    status_t err;
+    if (!sourceAlreadyStarted) {
+        err = mSource->start();
+        if (err != OK) {
+            return err;
+        }
+    }
+
+    //Create extractor thread, read and initialize all the
+    //mutexes and coditional variables
+    createThreads();
+    ALOGV("Thread Created.");
+    // We allow an optional INFO_FORMAT_CHANGED at the very beginning
+    // of playback, if there is one, getFormat below will retrieve the
+    // updated format, if there isn't, we'll stash away the valid buffer
+    // of data to be used on the first audio callback.
+
+    CHECK(mFirstBuffer == NULL);
+
+    MediaSource::ReadOptions options;
+    if (mSeeking) {
+        options.setSeekTo(mSeekTimeUs);
+        mSeeking = false;
+    }
+
+    mFirstBufferResult = mSource->read(&mFirstBuffer, &options);
+    if (mFirstBufferResult == INFO_FORMAT_CHANGED) {
+        ALOGV("INFO_FORMAT_CHANGED!!!");
+        CHECK(mFirstBuffer == NULL);
+        mFirstBufferResult = OK;
+        mIsFirstBuffer = false;
+    } else {
+        mIsFirstBuffer = true;
+    }
+
+    sp<MetaData> format = mSource->getFormat();
+    const char *mime;
+    bool success = format->findCString(kKeyMIMEType, &mime);
+    if (!strcasecmp(mime,MEDIA_MIMETYPE_AUDIO_AAC)) {
+        mFormat = AUDIO_FORMAT_AAC;
+    }
+    else if (!strcasecmp(mime,MEDIA_MIMETYPE_AUDIO_MPEG)) {
+        mFormat = AUDIO_FORMAT_MP3;
+        ALOGD("TunnelPlayer::start AUDIO_FORMAT_MP3");
+    } else {
+        ALOGE("TunnelPlayer::UNSUPPORTED");
+    }
+
+
+    CHECK(success);
+
+    success = format->findInt32(kKeySampleRate, &mSampleRate);
+    CHECK(success);
+
+    success = format->findInt32(kKeyChannelCount, &numChannels);
+    CHECK(success);
+
+    if(!format->findInt32(kKeyChannelMask, &mChannelMask)) {
+        // log only when there's a risk of ambiguity of channel mask selection
+        ALOGI_IF(numChannels > 2,
+                "source format didn't specify channel mask, using (%d) channel order", numChannels);
+        mChannelMask = CHANNEL_MASK_USE_CHANNEL_ORDER;
+    }
+    audio_output_flags_t flags = (audio_output_flags_t) (AUDIO_OUTPUT_FLAG_TUNNEL |
+                                                         AUDIO_OUTPUT_FLAG_DIRECT);
+    ALOGV("mAudiosink->open() mSampleRate %d, numChannels %d, mChannelMask %d, flags %d",mSampleRate, numChannels, mChannelMask, flags);
+    err = mAudioSink->open(
+        mSampleRate, numChannels, mChannelMask, mFormat,
+        DEFAULT_AUDIOSINK_BUFFERCOUNT,
+        &TunnelPlayer::AudioSinkCallback,
+        this,
+        flags,
+        NULL);
+
+    if (err != OK) {
+        if (mFirstBuffer != NULL) {
+            mFirstBuffer->release();
+            mFirstBuffer = NULL;
+        }
+
+        if (!sourceAlreadyStarted) {
+            mSource->stop();
+        }
+
+        ALOGE("Opening a routing session failed");
+        return err;
+    }
+
+    mIsAudioRouted = true;
+    mStarted = true;
+    mAudioSink->start();
+    mLock.lock();
+    ALOGV("Waking up extractor thread");
+    mExtractorCv.signal();
+    mLock.unlock();
+    return OK;
+}
+
+status_t TunnelPlayer::seekTo(int64_t time_us) {
+
+    ALOGD("seekTo: time_us %lld", time_us);
+
+    Mutex::Autolock _l(mLock); //to sync w/ onpausetimeout
+
+    if (seekTooClose(time_us)) {
+      ALOGV("seek time is too close to current playback position");
+      mLock.unlock(); //unlock and post
+      mObserver->postAudioSeekComplete();
+      mLock.lock();
+      return OK;
+    }
+
+    mSeeking = true;
+    mSeekTimeUs = time_us;
+    mPauseTime = mSeekTimeUs;
+    ALOGV("In seekTo(), mSeekTimeUs %lld",mSeekTimeUs);
+
+    if (mIsAudioRouted) {
+        mAudioSink->flush();
+    }
+
+    if (mReachedEOS) {
+        mReachedEOS = false;
+        mReachedOutputEOS = false;
+        if(mPaused == false) {
+            ALOGV("Going to signal extractor thread since playback is already going on ");
+            mExtractorCv.signal();
+            ALOGV("Signalled extractor thread.");
+        }
+    }
+    ALOGV("seek done.");
+    return OK;
+}
+void TunnelPlayer::pause(bool playPendingSamples) {
+    CHECK(mStarted);
+    if (mPaused) {
+        return;
+    }
+    Mutex::Autolock autoLock(mLock);
+    ALOGV("pause: playPendingSamples %d", playPendingSamples);
+    mPaused = true;
+    int64_t playedTime = 0;
+    if(!mPauseEventPending) {
+        ALOGV("Posting an event for Pause timeout");
+        mQueue.postEventWithDelay(mPauseEvent, TUNNEL_PAUSE_TIMEOUT_USEC);
+        mPauseEventPending = true;
+    }
+    getPlayedTimeFromDSP_l(&playedTime);
+    mPauseTime = mSeekTimeUs + playedTime;
+    if (mAudioSink.get() != NULL) {
+        ALOGV("AudioSink pause");
+        mAudioSink->pause();
+    }
+}
+
+status_t TunnelPlayer::resume() {
+    status_t err = NO_ERROR;
+    Mutex::Autolock autoLock(mLock);
+    ALOGV("resume: mPaused %d",mPaused);
+    if ( mPaused) {
+        CHECK(mStarted);
+        if(mPauseEventPending) {
+            ALOGV("Resume(): Cancelling the puaseTimeout event");
+            mPauseEventPending = false;
+            mQueue.cancelEvent(mPauseEvent->eventID());
+        }
+        audio_format_t format;
+
+        if (!mIsAudioRouted) {
+            audio_output_flags_t flags = (audio_output_flags_t) (AUDIO_OUTPUT_FLAG_TUNNEL |
+                                                                AUDIO_OUTPUT_FLAG_DIRECT);
+            err = mAudioSink->open(
+                mSampleRate, numChannels, mChannelMask, mFormat,
+                DEFAULT_AUDIOSINK_BUFFERCOUNT,
+                &TunnelPlayer::AudioSinkCallback,
+                this,
+                flags,
+                NULL);
+            if (err != NO_ERROR) {
+                ALOGE("Audio sink open failed.");
+            }
+            mIsAudioRouted = true;
+        }
+        mPaused = false;
+        ALOGV("Audio sink open succeeded.");
+        mAudioSink->start();
+        ALOGV("Audio sink start succeeded.");
+        mExtractorCv.signal();
+        ALOGV("Audio signalling extractor thread.");
+    }
+    return err;
+}
+
+//static
+size_t TunnelPlayer::AudioSinkCallback(
+        MediaPlayerBase::AudioSink *audioSink,
+        void *buffer, size_t size, void *cookie,
+        MediaPlayerBase::AudioSink::cb_event_t event) {
+    TunnelPlayer *me = (TunnelPlayer *)cookie;
+    if(me != NULL) {
+        ALOGV("postAudioEOS mSeeking %d", me->mSeeking);
+        if (buffer == NULL && size == AudioTrack::EVENT_UNDERRUN) {
+            if(me->mReachedEOS == true) {
+                //in the case of seek all these flags will be reset
+                me->mReachedOutputEOS = true;
+                ALOGV("postAudioEOS mSeeking %d", me->mSeeking);
+                me->mObserver->postAudioEOS(0);
+            }else {
+                ALOGV("postAudioEOS ignored since %d", me->mSeeking);
+            }
+        } else if (size == AudioTrack::EVENT_HW_FAIL) {
+            ALOGV("postAudioEOS in SSR " );
+            me->mReachedOutputEOS = true;
+            me->mReachedEOS = true;
+            me->mKillExtractorThread = true;
+            me->mObserver->postAudioEOS(0);
+       }
+    }
+    return 1;
+}
+
+void TunnelPlayer::reset() {
+    ALOGV("Reset");
+
+    Mutex::Autolock _l(mLock); //to sync w/ onpausetimeout
+
+    //cancel any pending onpause timeout events
+    //doesnt matter if the event is really present or not
+    mPauseEventPending = false;
+    mQueue.cancelEvent(mPauseEvent->eventID());
+
+    mReachedEOS = true;
+
+    // make sure Decoder thread has exited
+    requestAndWaitForExtractorThreadExit_l();
+
+    // Close the audiosink after all the threads exited to make sure
+    if (mIsAudioRouted) {
+        mAudioSink->stop();
+        mAudioSink->close();
+        mIsAudioRouted = false;
+    }
+    //TODO: Release Wake lock
+
+    // Make sure to release any buffer we hold onto so that the
+    // source is able to stop().
+    if (mFirstBuffer != NULL) {
+        mFirstBuffer->release();
+        mFirstBuffer = NULL;
+    }
+
+    if (mInputBuffer != NULL) {
+        ALOGV("AudioPlayer releasing input buffer.");
+        mInputBuffer->release();
+        mInputBuffer = NULL;
+    }
+
+    if (mStarted)
+        mSource->stop();
+
+    mSource.clear();
+
+    mPositionTimeMediaUs = -1;
+    mPositionTimeRealUs = -1;
+    mSeeking = false;
+    mReachedEOS = false;
+    mReachedOutputEOS = false;
+    mFinalStatus = OK;
+    mStarted = false;
+}
+
+
+bool TunnelPlayer::isSeeking() {
+    Mutex::Autolock autoLock(mLock);
+    return mSeeking;
+}
+
+bool TunnelPlayer::reachedEOS(status_t *finalStatus) {
+    *finalStatus = OK;
+    Mutex::Autolock autoLock(mLock);
+    *finalStatus = mFinalStatus;
+    return mReachedOutputEOS;
+}
+
+
+void *TunnelPlayer::extractorThreadWrapper(void *me) {
+    static_cast<TunnelPlayer *>(me)->extractorThreadEntry();
+    return NULL;
+}
+
+
+void TunnelPlayer::extractorThreadEntry() {
+
+    mLock.lock();
+    uint32_t BufferSizeToUse = MEM_BUFFER_SIZE;
+
+    pid_t tid  = gettid();
+    androidSetThreadPriority(tid, mHasVideo ? ANDROID_PRIORITY_NORMAL :
+                                              ANDROID_PRIORITY_AUDIO);
+    prctl(PR_SET_NAME, (unsigned long)"Extractor Thread", 0, 0, 0);
+
+    ALOGV("extractorThreadEntry wait for signal \n");
+    if (!mStarted && !mKillExtractorThread) {
+        mExtractorCv.wait(mLock);
+    }
+    ALOGV("extractorThreadEntry ready to work \n");
+    mLock.unlock();
+    if (mKillExtractorThread) {
+        return;
+    }
+    if(mSource != NULL) {
+        sp<MetaData> format = mSource->getFormat();
+        const char *mime;
+        bool success = format->findCString(kKeyMIMEType, &mime);
+    }
+    void* local_buf = malloc(BufferSizeToUse);
+    int *lptr = ((int*)local_buf);
+    int bytesWritten = 0;
+    bool lSeeking = false;
+    bool lPaused = false;
+    while (!mKillExtractorThread) {
+
+        if (mReachedEOS || mPaused || !mIsAudioRouted) {
+            ALOGV("Going to sleep before write since "
+                  "mReachedEOS %d, mPaused %d, mIsAudioRouted %d",
+                  mReachedEOS, mPaused, mIsAudioRouted);
+            mExtractorMutex.lock();
+            mExtractorCv.wait(mExtractorMutex);
+            mExtractorMutex.unlock();
+            ALOGV("Woke up from sleep before write since "
+                  "mReachedEOS %d, mPaused %d, mIsAudioRouted %d",
+                  mReachedEOS, mPaused, mIsAudioRouted);
+            continue;
+        }
+
+        ALOGV("FillBuffer: MemBuffer size %d", BufferSizeToUse);
+        ALOGV("Fillbuffer started");
+        bytesWritten = fillBuffer(local_buf, BufferSizeToUse);
+        ALOGV("FillBuffer completed bytesToWrite %d", bytesWritten);
+        if(!mKillExtractorThread) {
+            mLock.lock();
+            lPaused = mPaused;
+            mLock.unlock();
+
+            if(lPaused == true) {
+                //write only if player is not in paused state. Sleep on lock
+                // resume is called
+                ALOGV("Going to sleep in decodethreadiwrite since sink is paused");
+                mExtractorMutex.lock();
+                mExtractorCv.wait(mExtractorMutex);
+                ALOGV("Going to unlock n decodethreadwrite since sink "
+                      "resumed mPaused %d, mIsAudioRouted %d, mReachedEOS %d",
+                      mPaused, mIsAudioRouted, mReachedEOS);
+                mExtractorMutex.unlock();
+            }
+            mLock.lock();
+            lSeeking = mSeeking||mInternalSeeking;
+            mLock.unlock();
+
+            if(lSeeking == false && (mKillExtractorThread == false)){
+                //if we are seeking, ignore write, otherwise write
+                ALOGV("Fillbuffer before seek flag %d", mSeeking);
+                int lWrittenBytes = mAudioSink->write(local_buf, bytesWritten);
+                ALOGV("Fillbuffer after write, written bytes %d and seek flag %d", lWrittenBytes, mSeeking);
+                if(lWrittenBytes > 0) {
+                    //send EOS only if write was successful, if is_buffer_available
+                    // is flushed out (which returns 0 do not SEND EOS
+                    ALOGV("Fillbuffer after write and seek flag %d", mSeeking);
+                    mLock.lock();
+                    lSeeking = mSeeking||mInternalSeeking;
+                    mLock.unlock();
+                    //ignore posting zero length buffer is seeking is set
+                    if(mReachedEOS && bytesWritten && !lSeeking && (mKillExtractorThread == false)) {
+                        ALOGV("Fillbuffer after write sent EOS flag %d", lSeeking);
+                        mAudioSink->write(local_buf, 0);
+                    } else {
+                        ALOGV("Not sending EOS buffer sent since seeking %d, "
+                              "kill %d and mReachedEOS %d",         \
+                              lSeeking, mKillExtractorThread, mReachedEOS);
+                    }
+                } else {
+                    ALOGV("write exited because of flush %d", mSeeking);
+                }
+            } else {
+                ALOGV("Fillbuffer ignored since we seeked after fillBuffer was set %d", mSeeking);
+            }
+        }
+    }
+
+    free(local_buf);
+
+    //TODO: Call fillbuffer with different size and write to mAudioSink()
+}
+void TunnelPlayer::createThreads() {
+
+    // Create extractor Thread
+    pthread_attr_t attr;
+    pthread_attr_init(&attr);
+    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
+
+    mKillExtractorThread = false;
+
+    mExtractorThreadAlive = true;
+
+    ALOGV("Creating Extractor Thread");
+    pthread_create(&mExtractorThread, &attr, extractorThreadWrapper, this);
+
+    pthread_attr_destroy(&attr);
+}
+size_t TunnelPlayer::fillBuffer(void *data, size_t size) {
+
+    if (mReachedEOS) {
+        return 0;
+    }
+
+    bool postSeekComplete = false;
+
+    size_t size_done = 0;
+    size_t size_remaining = size;
+    //clear the flag since we dont know whether we are seeking or not, yet
+    ALOGV("fillBuffer: Clearing seek flag in fill buffer");
+
+    bool yield = !mIsFirstBuffer;
+
+    while (size_remaining > 0) {
+        MediaSource::ReadOptions options;
+        {
+            Mutex::Autolock autoLock(mLock);
+            if(mSeeking) {
+                mInternalSeeking = false;
+            }
+
+            if (mSeeking || mInternalSeeking) {
+                if (mIsFirstBuffer) {
+                    if (mFirstBuffer != NULL) {
+                        mFirstBuffer->release();
+                        mFirstBuffer = NULL;
+                    }
+                    mIsFirstBuffer = false;
+                }
+
+                MediaSource::ReadOptions::SeekMode seekMode;
+                seekMode = MediaSource::ReadOptions::SEEK_CLOSEST_SYNC;
+                options.setSeekTo(mSeekTimeUs, seekMode );
+                if (mInputBuffer != NULL) {
+                    mInputBuffer->release();
+                    mInputBuffer = NULL;
+                }
+
+                // This is to ignore the data already filled in the output buffer
+                size_done = 0;
+                size_remaining = size;
+
+                mSeeking = false;
+                if (mObserver && !mInternalSeeking) {
+                    ALOGV("fillBuffer: Posting audio seek complete event");
+                    postSeekComplete = true;
+                }
+                mInternalSeeking = false;
+                ALOGV("fillBuffer: Setting seek flag in fill buffer");
+                //set the flag since we know that this buffer is the new positions buffer
+            }
+        }
+        if (mInputBuffer == NULL) {
+            status_t err;
+
+            if (mIsFirstBuffer) {
+                mInputBuffer = mFirstBuffer;
+                mFirstBuffer = NULL;
+                err = mFirstBufferResult;
+
+                mIsFirstBuffer = false;
+            } else {
+                err = mSource->read(&mInputBuffer, &options);
+            }
+
+            CHECK((err == OK && mInputBuffer != NULL)
+                  || (err != OK && mInputBuffer == NULL));
+            {
+                Mutex::Autolock autoLock(mLock);
+
+                if (err != OK) {
+                    ALOGD("fill buffer - reached eos true");
+                    mReachedEOS = true;
+                    mFinalStatus = err;
+                    break;
+                }
+            }
+
+        }
+        if (mInputBuffer->range_length() == 0) {
+            mInputBuffer->release();
+            mInputBuffer = NULL;
+            continue;
+        }
+
+        size_t copy = size_remaining;
+        if (copy > mInputBuffer->range_length()) {
+            copy = mInputBuffer->range_length();
+        }
+        memcpy((char *)data + size_done,
+               (const char *)mInputBuffer->data() + mInputBuffer->range_offset(),
+               copy);
+
+        mInputBuffer->set_range(mInputBuffer->range_offset() + copy,
+                                mInputBuffer->range_length() - copy);
+
+        size_done += copy;
+        size_remaining -= copy;
+
+        if (mHasVideo && yield) {
+            sched_yield();
+        }
+    }
+    if(mReachedEOS)
+        memset((char *)data + size_done, 0x0, size_remaining);
+    ALOGV("fill buffer size_done = %d",size_done);
+
+    if (postSeekComplete) {
+        mObserver->postAudioSeekComplete();
+    }
+
+    return size_done;
+}
+
+int64_t TunnelPlayer::getRealTimeUs() {
+    Mutex::Autolock autoLock(mLock);
+
+    /*
+     * If it so happens that the client (e.g. AwesomePlayer),
+     * queries for the current time before compressed
+     * data from the new position is given to the compressed
+     * driver, we need to return the seek position
+     */
+    if (mSeeking || mInternalSeeking) {
+        ALOGV("Seek yet to be processed, return seek time as current time %lld",
+              mSeekTimeUs);
+        return mSeekTimeUs;
+    }
+
+    getOffsetRealTime_l(&mPositionTimeRealUs);
+    //update media time too
+    mPositionTimeMediaUs = mPositionTimeRealUs;
+    return mPositionTimeRealUs;
+}
+
+void TunnelPlayer::getPlayedTimeFromDSP_l(int64_t* timeStamp ) {
+    ALOGV("going to query timestamp");
+    mAudioSink->getTimeStamp((uint64_t*)timeStamp);
+    ALOGV("timestamp returned from DSP %lld ", (*timeStamp));
+    return;
+}
+
+//offset with pause and seek time
+void TunnelPlayer::getOffsetRealTime_l(int64_t* offsetTime) {
+    if (mPaused) {
+        *offsetTime = mPauseTime;
+        ALOGV("getMediaTimeUs() mPaused %d mSeekTimeUs %lld mPauseTime %lld", mPaused, mSeekTimeUs, mPauseTime );
+    } else {
+        getPlayedTimeFromDSP_l(offsetTime);
+        ALOGV("getMediaTimeUs() mPaused %d mSeekTimeUs %lld mPauseTime %lld, timeStamp %lld", mPaused, mSeekTimeUs, mPauseTime, *offsetTime);
+        *offsetTime = mSeekTimeUs + *offsetTime;
+    }
+}
+
+int64_t TunnelPlayer::getMediaTimeUs() {
+    //essentially there is only one time, the real time
+    return getRealTimeUs();
+}
+
+bool TunnelPlayer::getMediaTimeMapping(
+                                   int64_t *realtime_us, int64_t *mediatime_us) {
+    Mutex::Autolock autoLock(mLock);
+
+    *realtime_us = mPositionTimeRealUs;
+    *mediatime_us = mPositionTimeMediaUs;
+
+    return mPositionTimeRealUs != -1 && mPositionTimeMediaUs != -1;
+}
+
+//lock has been taken in reset() to sync with onpausetimeout
+void TunnelPlayer::requestAndWaitForExtractorThreadExit_l() {
+
+    ALOGV("requestAndWaitForExtractorThreadExit_l -1");
+
+    if (!mExtractorThreadAlive)
+        return;
+
+    mKillExtractorThread = true;
+
+    ALOGV("requestAndWaitForExtractorThreadExit_l +0");
+    if (mIsAudioRouted && !mReachedOutputEOS) {
+        mAudioSink->flush();
+    }
+
+
+    ALOGV("requestAndWaitForExtractorThreadExit_l +1");
+    mExtractorCv.signal();
+    mLock.unlock();
+    ALOGV("requestAndWaitForExtractorThreadExit_l +2");
+    pthread_join(mExtractorThread,NULL);
+    mLock.lock();
+    ALOGV("requestAndWaitForExtractorThreadExit_l +3");
+
+    ALOGV("Extractor thread killed");
+}
+
+void TunnelPlayer::onPauseTimeOut() {
+    Mutex::Autolock autoLock(mLock);
+    int64_t playedTime = 0;
+    ALOGV("onPauseTimeOut");
+    if (!mPauseEventPending) {
+        return;
+    }
+    mPauseEventPending = false;
+    // 1.) Set seek flags
+    mReachedEOS = false;
+    mReachedOutputEOS = false;
+
+    if(mSeeking == false) {
+        ALOGV("onPauseTimeOut +2");
+        mInternalSeeking = true;
+        ALOGV("onPauseTimeOut +3");
+        getPlayedTimeFromDSP_l(&playedTime);
+        mSeekTimeUs += playedTime;
+    } else {
+        ALOGV("Do not update seek time if it was seeked before onpause timeout");
+    }
+
+    // 2.) Close routing Session
+    ALOGV("onPauseTimeOut +4");
+    mAudioSink->flush();
+    ALOGV("onPauseTimeOut +5");
+    mAudioSink->stop();
+    ALOGV("onPauseTimeOut +6");
+    mAudioSink->close();
+    ALOGV("onPauseTimeOut +7");
+    mIsAudioRouted = false;
+}
+
+/*
+ * Returns true if the seek position is too close to the
+ * current playback position.
+ * Caller must acquire mLock
+ */
+bool TunnelPlayer::seekTooClose(int64_t time_us) {
+    int64_t t1 = -1;
+    /* The time as per DSP just before flush is issued */
+    if (mPositionTimeRealUs == -1) {
+        getOffsetRealTime_l(&mPositionTimeRealUs);
+    }
+
+    t1 = mPositionTimeRealUs;
+    /*
+     * empirical
+     * -----------
+     * This constant signifies how much data (in Us) has been rendered by the
+     * DSP in the interval between the moment flush is issued on AudioSink to
+     * after ioctl(PAUSE) returns in Audio HAL. (flush triggers an implicit
+     * pause in audio HAL)
+     *
+     */
+    const int64_t deltaUs = 60000LL; /* 60-70ms on msm8974 */
+    return (time_us > t1) && ((time_us - t1) <= deltaUs);
+}
+
+} //namespace android
diff --git a/media/libstagefright/Utils.cpp b/media/libstagefright/Utils.cpp
old mode 100644
new mode 100755
index 216a329..517465d
--- a/media/libstagefright/Utils.cpp
+++ b/media/libstagefright/Utils.cpp
@@ -32,6 +32,9 @@
 #include <hardware/audio.h>
 #include <media/stagefright/Utils.h>
 #include <media/AudioParameter.h>
+#ifdef QCOM_HARDWARE
+#include <media/stagefright/ExtendedCodec.h>
+#endif
 
 namespace android {
 
@@ -253,6 +256,9 @@
         msg->setBuffer("csd-1", buffer);
     }
 
+#ifdef QCOM_HARDWARE
+    ExtendedCodec::convertMetaDataToMessage(meta, &msg);
+#endif
     *format = msg;
 
     return OK;
diff --git a/media/libstagefright/WAVEWriter.cpp b/media/libstagefright/WAVEWriter.cpp
new file mode 100644
index 0000000..468765f
--- /dev/null
+++ b/media/libstagefright/WAVEWriter.cpp
@@ -0,0 +1,323 @@
+/*
+ * Copyright (c) 2012 - 2013, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials provided
+ *       with the distribution.
+ *     * Neither the name of The Linux Foundation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "WAVEWriter"
+#include <utils/Log.h>
+
+#include <media/stagefright/WAVEWriter.h>
+#include <media/stagefright/MediaBuffer.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MediaErrors.h>
+#include <media/stagefright/MediaSource.h>
+#include <media/stagefright/MetaData.h>
+#include <media/mediarecorder.h>
+#include <sys/prctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+namespace android {
+
+static struct wav_header hdr;
+
+
+WAVEWriter::WAVEWriter(const char *filename)
+    : mFd(-1),
+      mInitCheck(NO_INIT),
+      mStarted(false),
+      mPaused(false),
+      mResumed(false) {
+
+    mFd = open(filename, O_CREAT | O_LARGEFILE | O_TRUNC | O_RDWR, S_IRUSR | S_IWUSR);
+    if (mFd >= 0) {
+        mInitCheck = OK;
+    }
+}
+
+WAVEWriter::WAVEWriter(int fd)
+    : mFd(dup(fd)),
+      mInitCheck(mFd < 0? NO_INIT: OK),
+      mStarted(false),
+      mPaused(false),
+      mResumed(false) {
+}
+
+WAVEWriter::~WAVEWriter() {
+    if (mStarted) {
+        stop();
+    }
+
+    if (mFd != -1) {
+        close(mFd);
+        mFd = -1;
+    }
+}
+
+status_t WAVEWriter::initCheck() const {
+    return mInitCheck;
+}
+
+status_t WAVEWriter::addSource(const sp<MediaSource> &source) {
+    uint32_t count;
+    if (mInitCheck != OK) {
+        ALOGE("Init Check not OK, return");
+        return mInitCheck;
+    }
+
+    if (mSource != NULL) {
+        ALOGE("A source already exists, return");
+        return UNKNOWN_ERROR;
+    }
+
+    sp<MetaData> meta = source->getFormat();
+
+    const char *mime;
+    CHECK(meta->findCString(kKeyMIMEType, &mime));
+
+    int32_t channelCount;
+    int32_t sampleRate;
+    CHECK(meta->findInt32(kKeyChannelCount, &channelCount));
+    CHECK(meta->findInt32(kKeySampleRate, &sampleRate));
+
+    memset(&hdr, 0, sizeof(struct wav_header));
+    hdr.riff_id = ID_RIFF;
+    hdr.riff_fmt = ID_WAVE;
+    hdr.fmt_id = ID_FMT;
+    hdr.fmt_sz = 16;
+    hdr.audio_format = FORMAT_PCM;
+    hdr.num_channels = channelCount;
+    hdr.sample_rate = sampleRate;
+    hdr.bits_per_sample = 16;
+    hdr.byte_rate = (sampleRate * channelCount * hdr.bits_per_sample) / 8;
+    hdr.block_align = ( hdr.bits_per_sample * channelCount ) / 8;
+    hdr.data_id = ID_DATA;
+    hdr.data_sz = 0;
+    hdr.riff_sz = hdr.data_sz + 44 - 8;
+
+    if (write(mFd, &hdr, sizeof(hdr)) != sizeof(hdr)) {
+        ALOGE("Write header error, return ERROR_IO");
+        return -ERROR_IO;
+    }
+
+    mSource = source;
+
+    return OK;
+}
+
+status_t WAVEWriter::start(MetaData *params) {
+    if (mInitCheck != OK) {
+        ALOGE("Init Check not OK, return");
+        return mInitCheck;
+    }
+
+    if (mSource == NULL) {
+        ALOGE("NULL Source");
+        return UNKNOWN_ERROR;
+    }
+
+    if (mStarted && mPaused) {
+        mPaused = false;
+        mResumed = true;
+        return OK;
+    } else if (mStarted) {
+        ALOGE("Already startd, return");
+        return OK;
+    }
+
+    status_t err = mSource->start();
+
+    if (err != OK) {
+        return err;
+    }
+
+    pthread_attr_t attr;
+    pthread_attr_init(&attr);
+    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
+
+    mReachedEOS = false;
+    mDone = false;
+
+    pthread_create(&mThread, &attr, ThreadWrapper, this);
+    pthread_attr_destroy(&attr);
+
+    mStarted = true;
+
+    return OK;
+}
+
+status_t WAVEWriter::pause() {
+    if (!mStarted) {
+        return OK;
+    }
+    mPaused = true;
+    return OK;
+}
+
+status_t WAVEWriter::stop() {
+    if (!mStarted) {
+        return OK;
+    }
+
+    mDone = true;
+
+    void *dummy;
+    pthread_join(mThread, &dummy);
+
+    status_t err = (status_t) dummy;
+    {
+        status_t status = mSource->stop();
+        if (err == OK &&
+            (status != OK && status != ERROR_END_OF_STREAM)) {
+            err = status;
+        }
+    }
+
+    mStarted = false;
+    return err;
+}
+
+bool WAVEWriter::exceedsFileSizeLimit() {
+    if (mMaxFileSizeLimitBytes == 0) {
+        return false;
+    }
+    return mEstimatedSizeBytes >= mMaxFileSizeLimitBytes;
+}
+
+bool WAVEWriter::exceedsFileDurationLimit() {
+    if (mMaxFileDurationLimitUs == 0) {
+        return false;
+    }
+    return mEstimatedDurationUs >= mMaxFileDurationLimitUs;
+}
+
+// static
+void *WAVEWriter::ThreadWrapper(void *me) {
+    return (void *) static_cast<WAVEWriter *>(me)->threadFunc();
+}
+
+status_t WAVEWriter::threadFunc() {
+    mEstimatedDurationUs = 0;
+    mEstimatedSizeBytes = 0;
+    bool stoppedPrematurely = true;
+    int64_t previousPausedDurationUs = 0;
+    int64_t maxTimestampUs = 0;
+    status_t err = OK;
+
+    prctl(PR_SET_NAME, (unsigned long)"WAVEWriter", 0, 0, 0);
+    hdr.data_sz = 0;
+    while (!mDone) {
+        MediaBuffer *buffer;
+        err = mSource->read(&buffer);
+
+        if (err != OK) {
+            break;
+        }
+
+        if (mPaused) {
+            buffer->release();
+            buffer = NULL;
+            continue;
+        }
+
+        mEstimatedSizeBytes += buffer->range_length();
+        if (exceedsFileSizeLimit()) {
+            buffer->release();
+            buffer = NULL;
+            notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED, 0);
+            break;
+        }
+
+        int64_t timestampUs;
+        CHECK(buffer->meta_data()->findInt64(kKeyTime, &timestampUs));
+        if (timestampUs > mEstimatedDurationUs) {
+            mEstimatedDurationUs = timestampUs;
+        }
+        if (mResumed) {
+            previousPausedDurationUs += (timestampUs - maxTimestampUs - 20000);
+            mResumed = false;
+        }
+        timestampUs -= previousPausedDurationUs;
+        ALOGV("time stamp: %lld, previous paused duration: %lld",
+                timestampUs, previousPausedDurationUs);
+        if (timestampUs > maxTimestampUs) {
+            maxTimestampUs = timestampUs;
+        }
+
+        if (exceedsFileDurationLimit()) {
+            buffer->release();
+            buffer = NULL;
+            notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_DURATION_REACHED, 0);
+            break;
+        }
+        ssize_t n = write(mFd,
+                        (const uint8_t *)buffer->data() + buffer->range_offset(),
+                        buffer->range_length());
+
+        hdr.data_sz += (ssize_t)buffer->range_length();
+        hdr.riff_sz = hdr.data_sz + 44 - 8;
+
+        if (n < (ssize_t)buffer->range_length()) {
+            buffer->release();
+            buffer = NULL;
+
+            break;
+        }
+
+        if (stoppedPrematurely) {
+            stoppedPrematurely = false;
+        }
+
+        buffer->release();
+        buffer = NULL;
+    }
+
+    if (stoppedPrematurely) {
+        notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_TRACK_INFO_COMPLETION_STATUS, UNKNOWN_ERROR);
+    }
+
+    lseek(mFd, 0, SEEK_SET);
+    write(mFd, &hdr, sizeof(hdr));
+    lseek(mFd, 0, SEEK_END);
+
+    close(mFd);
+    mFd = -1;
+    mReachedEOS = true;
+    if (err == ERROR_END_OF_STREAM) {
+        return OK;
+    }
+    return err;
+}
+
+bool WAVEWriter::reachedEOS() {
+    return mReachedEOS;
+}
+
+}  // namespace android
diff --git a/media/libstagefright/avc_utils.cpp b/media/libstagefright/avc_utils.cpp
index b822868..1d843f3 100644
--- a/media/libstagefright/avc_utils.cpp
+++ b/media/libstagefright/avc_utils.cpp
@@ -44,7 +44,11 @@
 void FindAVCDimensions(
         const sp<ABuffer> &seqParamSet,
         int32_t *width, int32_t *height,
+#ifdef QCOM_HARDWARE
+        int32_t *sarWidth, int32_t *sarHeight, int32_t *isInterlaced) {
+#else
         int32_t *sarWidth, int32_t *sarHeight) {
+#endif
     ABitReader br(seqParamSet->data() + 1, seqParamSet->size() - 1);
 
     unsigned profile_idc = br.getBits(8);
@@ -63,7 +67,13 @@
         parseUE(&br);  // bit_depth_luma_minus8
         parseUE(&br);  // bit_depth_chroma_minus8
         br.skipBits(1);  // qpprime_y_zero_transform_bypass_flag
-        CHECK_EQ(br.getBits(1), 0u);  // seq_scaling_matrix_present_flag
+#ifdef QCOM_HARDWARE
+        bool seq_scaling_matrix_present = (br.getBits(1) != 0u);
+        if (isInterlaced != NULL && seq_scaling_matrix_present) {
+            return;
+        }
+        CHECK_EQ(seq_scaling_matrix_present, false);  // seq_scaling_matrix_present_flag
+#endif
     }
 
     parseUE(&br);  // log2_max_frame_num_minus4
@@ -133,6 +143,12 @@
             (frame_crop_top_offset + frame_crop_bottom_offset) * cropUnitY;
     }
 
+#ifdef QCOM_HARDWARE
+    if (isInterlaced != NULL) {
+        *isInterlaced = !frame_mbs_only_flag;
+    }
+#endif
+
     if (sarWidth != NULL) {
         *sarWidth = 0;
     }
diff --git a/media/libstagefright/codecs/aacdec/SoftAAC2.cpp b/media/libstagefright/codecs/aacdec/SoftAAC2.cpp
index 1b20cbb..2f7da48 100644
--- a/media/libstagefright/codecs/aacdec/SoftAAC2.cpp
+++ b/media/libstagefright/codecs/aacdec/SoftAAC2.cpp
@@ -362,9 +362,13 @@
             inInfo->mOwnedByUs = false;
             notifyEmptyBufferDone(inHeader);
 
-            if (mDecoderHasData) {
+            if (mDecoderHasData || mInputBufferCount) {
                 // flush out the decoder's delayed data by calling DecodeFrame
                 // one more time, with the AACDEC_FLUSH flag set
+
+                // for the use case where the first frame in the buffer is EOS,
+                // decode the header to update the sample rate and channel mode
+                // and flush out the buffer.
                 INT_PCM *outBuffer =
                         reinterpret_cast<INT_PCM *>(
                                 outHeader->pBuffer + outHeader->nOffset);
@@ -395,6 +399,9 @@
             }
 
             outHeader->nFlags = OMX_BUFFERFLAG_EOS;
+            outHeader->nTimeStamp =
+                mAnchorTimeUs
+                    + (mNumSamplesOutput * 1000000ll) / mStreamInfo->sampleRate;
 
             outQueue.erase(outQueue.begin());
             outInfo->mOwnedByUs = false;
diff --git a/media/libstagefright/codecs/amrnb/dec/SoftAMR.cpp b/media/libstagefright/codecs/amrnb/dec/SoftAMR.cpp
index 3320688..78d0b23 100644
--- a/media/libstagefright/codecs/amrnb/dec/SoftAMR.cpp
+++ b/media/libstagefright/codecs/amrnb/dec/SoftAMR.cpp
@@ -352,7 +352,14 @@
             }
 
             size_t frameSize = getFrameSize(mode);
-            CHECK_GE(inHeader->nFilledLen, frameSize);
+            if (inHeader->nFilledLen < frameSize) {
+                ALOGE("Filled length vs frameSize %d vs %d. Corrupt clip?",
+                   inHeader->nFilledLen, frameSize);
+
+                notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
+                mSignalledError = true;
+                return;
+            }
 
             int16_t *outPtr = (int16_t *)outHeader->pBuffer;
 
@@ -429,6 +436,17 @@
 }
 
 void SoftAMR::onPortFlushCompleted(OMX_U32 portIndex) {
+        ALOGE("onPortFlushCompleted portindex %d, resetting frame ",portIndex);
+        if(portIndex == 0) {
+#ifdef QCOM_HARDWARE
+           if(mMode == MODE_NARROW)
+              Speech_Decode_Frame_reset(mState);
+           else
+              pvDecoder_AmrWb_Reset(mState, 0);
+#else
+           Speech_Decode_Frame_reset(mState);
+#endif
+        }
 }
 
 void SoftAMR::onPortEnableCompleted(OMX_U32 portIndex, bool enabled) {
diff --git a/media/libstagefright/codecs/amrnb/enc/SoftAMRNBEncoder.cpp b/media/libstagefright/codecs/amrnb/enc/SoftAMRNBEncoder.cpp
index 50b739c..c6300a8 100644
--- a/media/libstagefright/codecs/amrnb/enc/SoftAMRNBEncoder.cpp
+++ b/media/libstagefright/codecs/amrnb/enc/SoftAMRNBEncoder.cpp
@@ -71,7 +71,7 @@
     def.eDir = OMX_DirInput;
     def.nBufferCountMin = kNumBuffers;
     def.nBufferCountActual = def.nBufferCountMin;
-    def.nBufferSize = kNumSamplesPerFrame * sizeof(int16_t);
+    def.nBufferSize = kNumSamplesPerFrame * sizeof(int16_t) * 4;
     def.bEnabled = OMX_TRUE;
     def.bPopulated = OMX_FALSE;
     def.eDomain = OMX_PortDomainAudio;
diff --git a/media/libstagefright/codecs/amrwbenc/SoftAMRWBEncoder.cpp b/media/libstagefright/codecs/amrwbenc/SoftAMRWBEncoder.cpp
index 9ccb49c..afd2b32 100644
--- a/media/libstagefright/codecs/amrwbenc/SoftAMRWBEncoder.cpp
+++ b/media/libstagefright/codecs/amrwbenc/SoftAMRWBEncoder.cpp
@@ -78,7 +78,7 @@
     def.eDir = OMX_DirInput;
     def.nBufferCountMin = kNumBuffers;
     def.nBufferCountActual = def.nBufferCountMin;
-    def.nBufferSize = kNumSamplesPerFrame * sizeof(int16_t);
+    def.nBufferSize = kNumSamplesPerFrame * sizeof(int16_t) * 4;
     def.bEnabled = OMX_TRUE;
     def.bPopulated = OMX_FALSE;
     def.eDomain = OMX_PortDomainAudio;
diff --git a/media/libstagefright/codecs/mp3dec/Android.mk b/media/libstagefright/codecs/mp3dec/Android.mk
index 135c715..c27a63d 100644
--- a/media/libstagefright/codecs/mp3dec/Android.mk
+++ b/media/libstagefright/codecs/mp3dec/Android.mk
@@ -42,6 +42,11 @@
  	src/pvmp3_dct_16.cpp
 endif
 
+ifeq ($(BOARD_USES_QCOM_HARDWARE),true)
+LOCAL_SRC_FILES += \
+	MP3Decoder.cpp
+endif
+
 LOCAL_C_INCLUDES := \
         frameworks/av/media/libstagefright/include \
         $(LOCAL_PATH)/src \
diff --git a/media/libstagefright/codecs/mp3dec/MP3Decoder.cpp b/media/libstagefright/codecs/mp3dec/MP3Decoder.cpp
new file mode 100644
index 0000000..c757589
--- /dev/null
+++ b/media/libstagefright/codecs/mp3dec/MP3Decoder.cpp
@@ -0,0 +1,601 @@
+/*
+ * Copyright (C) 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.
+ */
+
+#include "MP3Decoder.h"
+
+#include "include/pvmp3decoder_api.h"
+
+#include <media/stagefright/MediaBufferGroup.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MetaData.h>
+#include <media/stagefright/Utils.h>
+
+#include <cutils/log.h>
+
+#define LITERAL_TO_STRING_INTERNAL(x)    #x
+#define LITERAL_TO_STRING(x) LITERAL_TO_STRING_INTERNAL(x)
+
+#define CHECK_EQ(x,y)                                                   \
+    LOG_ALWAYS_FATAL_IF(                                                \
+            (x) != (y),                                                 \
+            __FILE__ ":" LITERAL_TO_STRING(__LINE__) " " #x " != " #y)
+
+#define CHECK(x)                                                        \
+    LOG_ALWAYS_FATAL_IF(                                                \
+            !(x),                                                       \
+            __FILE__ ":" LITERAL_TO_STRING(__LINE__) " " #x)
+
+
+namespace android {
+
+// Everything must match except for
+// protection, bitrate, padding, private bits, mode extension,
+// copyright bit, original bit and emphasis.
+// Yes ... there are things that must indeed match...
+static const uint32_t kMask = 0xfffe0cc0;
+
+static bool get_mp3_frame_size(
+        uint32_t header, size_t *frame_size,
+        int *out_sampling_rate = NULL, int *out_channels = NULL,
+        int *out_bitrate = NULL) {
+    *frame_size = 0;
+
+    if (out_sampling_rate) {
+        *out_sampling_rate = 0;
+    }
+
+    if (out_channels) {
+        *out_channels = 0;
+    }
+
+    if (out_bitrate) {
+        *out_bitrate = 0;
+    }
+
+    if ((header & 0xffe00000) != 0xffe00000) {
+        return false;
+    }
+
+    unsigned version = (header >> 19) & 3;
+
+    if (version == 0x01) {
+        return false;
+    }
+
+    unsigned layer = (header >> 17) & 3;
+
+    if (layer == 0x00) {
+        return false;
+    }
+
+    unsigned protection = (header >> 16) & 1;
+
+    unsigned bitrate_index = (header >> 12) & 0x0f;
+
+    if (bitrate_index == 0 || bitrate_index == 0x0f) {
+        // Disallow "free" bitrate.
+        return false;
+    }
+
+    unsigned sampling_rate_index = (header >> 10) & 3;
+
+    if (sampling_rate_index == 3) {
+        return false;
+    }
+
+    static const int kSamplingRateV1[] = { 44100, 48000, 32000 };
+    int sampling_rate = kSamplingRateV1[sampling_rate_index];
+    if (version == 2 /* V2 */) {
+        sampling_rate /= 2;
+    } else if (version == 0 /* V2.5 */) {
+        sampling_rate /= 4;
+    }
+
+    unsigned padding = (header >> 9) & 1;
+
+    if (layer == 3) {
+        // layer I
+
+        static const int kBitrateV1[] = {
+            32, 64, 96, 128, 160, 192, 224, 256,
+            288, 320, 352, 384, 416, 448
+        };
+
+        static const int kBitrateV2[] = {
+            32, 48, 56, 64, 80, 96, 112, 128,
+            144, 160, 176, 192, 224, 256
+        };
+
+        int bitrate =
+            (version == 3 /* V1 */)
+                ? kBitrateV1[bitrate_index - 1]
+                : kBitrateV2[bitrate_index - 1];
+
+        if (out_bitrate) {
+            *out_bitrate = bitrate;
+        }
+
+        *frame_size = (12000 * bitrate / sampling_rate + padding) * 4;
+    } else {
+        // layer II or III
+
+        static const int kBitrateV1L2[] = {
+            32, 48, 56, 64, 80, 96, 112, 128,
+            160, 192, 224, 256, 320, 384
+        };
+
+        static const int kBitrateV1L3[] = {
+            32, 40, 48, 56, 64, 80, 96, 112,
+            128, 160, 192, 224, 256, 320
+        };
+
+        static const int kBitrateV2[] = {
+            8, 16, 24, 32, 40, 48, 56, 64,
+            80, 96, 112, 128, 144, 160
+        };
+
+        int bitrate;
+        if (version == 3 /* V1 */) {
+            bitrate = (layer == 2 /* L2 */)
+                ? kBitrateV1L2[bitrate_index - 1]
+                : kBitrateV1L3[bitrate_index - 1];
+        } else {
+            // V2 (or 2.5)
+
+            bitrate = kBitrateV2[bitrate_index - 1];
+        }
+
+        if (out_bitrate) {
+            *out_bitrate = bitrate;
+        }
+
+        if (version == 3 /* V1 */) {
+            *frame_size = 144000 * bitrate / sampling_rate + padding;
+        } else {
+            // V2 or V2.5
+            *frame_size = 72000 * bitrate / sampling_rate + padding;
+        }
+    }
+
+    if (out_sampling_rate) {
+        *out_sampling_rate = sampling_rate;
+    }
+
+    if (out_channels) {
+        int channel_mode = (header >> 6) & 3;
+
+        *out_channels = (channel_mode == 3) ? 1 : 2;
+    }
+
+    return true;
+}
+
+static bool resync(
+        uint8_t *data, uint32_t size, uint32_t match_header, off_t *out_pos) {
+
+    bool valid = false;
+    off_t pos = 0;
+    *out_pos = 0;
+    do {
+        if (pos + 4 > size) {
+            // Don't scan forever.
+            ALOGV("no dice, no valid sequence of frames found.");
+            break;
+        }
+
+        uint32_t header = U32_AT(data + pos);
+
+        if (match_header != 0 && (header & kMask) != (match_header & kMask)) {
+            ++pos;
+            continue;
+        }
+
+        ALOGV("found possible frame at %ld (header = 0x%08x)", pos, header);
+
+        // We found what looks like a valid frame,
+        valid = true;
+        *out_pos = pos;
+    } while (!valid);
+
+    return valid;
+}
+
+
+MP3Decoder::MP3Decoder(const sp<MediaSource> &source)
+    : mSource(source),
+      mNumChannels(0),
+      mStarted(false),
+      mBufferGroup(NULL),
+      mConfig(new tPVMP3DecoderExternal),
+      mDecoderBuf(NULL),
+      mAnchorTimeUs(0),
+      mNumFramesOutput(0),
+      mInputBuffer(NULL),
+      mPartialBuffer(NULL),
+      mFixedHeader(0) {
+    init();
+}
+
+void MP3Decoder::init() {
+    sp<MetaData> srcFormat = mSource->getFormat();
+
+    int32_t sampleRate;
+    CHECK(srcFormat->findInt32(kKeyChannelCount, &mNumChannels));
+    CHECK(srcFormat->findInt32(kKeySampleRate, &sampleRate));
+
+    mMeta = new MetaData;
+    mMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_RAW);
+    mMeta->setInt32(kKeyChannelCount, mNumChannels);
+    mMeta->setInt32(kKeySampleRate, sampleRate);
+
+    int64_t durationUs;
+    if (srcFormat->findInt64(kKeyDuration, &durationUs)) {
+        mMeta->setInt64(kKeyDuration, durationUs);
+    }
+
+    mMeta->setCString(kKeyDecoderComponent, "MP3Decoder");
+}
+
+MP3Decoder::~MP3Decoder() {
+    if (mStarted) {
+        stop();
+    }
+
+    delete mConfig;
+    mConfig = NULL;
+}
+
+status_t MP3Decoder::start(MetaData *params) {
+    CHECK(!mStarted);
+
+    mBufferGroup = new MediaBufferGroup;
+    mBufferGroup->add_buffer(new MediaBuffer(4608 * 2));
+
+    mConfig->equalizerType = flat;
+    mConfig->crcEnabled = false;
+
+    uint32_t memRequirements = pvmp3_decoderMemRequirements();
+    mDecoderBuf = malloc(memRequirements);
+
+    pvmp3_InitDecoder(mConfig, mDecoderBuf);
+
+    mSource->start();
+
+    mAnchorTimeUs = 0;
+    mNumFramesOutput = 0;
+    mStarted = true;
+
+    return OK;
+}
+
+status_t MP3Decoder::stop() {
+    CHECK(mStarted);
+
+    if (mInputBuffer) {
+        mInputBuffer->release();
+        mInputBuffer = NULL;
+    }
+
+    free(mDecoderBuf);
+    mDecoderBuf = NULL;
+
+    delete mBufferGroup;
+    mBufferGroup = NULL;
+
+    mSource->stop();
+
+    mStarted = false;
+
+    return OK;
+}
+
+sp<MetaData> MP3Decoder::getFormat() {
+    return mMeta;
+}
+
+status_t MP3Decoder::updatePartialFrame() {
+    status_t err = OK;
+    if (mPartialBuffer == NULL) {
+        return err;
+    }
+
+    size_t frameSize = 0;
+    uint32_t partialBufLen = mPartialBuffer->range_length();
+    uint32_t inputBufLen = mInputBuffer->range_length();
+    uint8_t frameHeader[4];
+    uint8_t *frmHdr;
+    uint32_t header;
+
+
+    // Look at the frame size and complete the partial frame
+    // Also check if a vaild header is found after the partial frame
+    if (partialBufLen < 4) { // check if partial frame has the 4 bytes header
+        if (inputBufLen < (4 - partialBufLen)) {
+            // input buffer does not have the frame header bytes
+            // bail out TODO
+            ALOGE("MP3Decoder::updatePartialFrame buffer to small header not found"
+                 " partial buffer len %d, input buffer len %d",
+                 partialBufLen, inputBufLen);
+            //mPartialBuffer->release();
+            //mPartialBuffer = NULL;
+            return UNKNOWN_ERROR;
+        }
+
+        // copy the header bytes to frameHeader
+        memcpy (frameHeader, mPartialBuffer->data(), partialBufLen);
+        memcpy (frameHeader + partialBufLen, mInputBuffer->data(), (4 - partialBufLen));
+        // get the first 4 bytes of the buffer
+        header = U32_AT((uint8_t *)frameHeader);
+        frmHdr = frameHeader;
+    } else {
+        frmHdr = (uint8_t *)mPartialBuffer->data();
+    }
+
+    // check if its a good frame, and the frame size
+    // get the first 4 bytes of the buffer
+    header = U32_AT(frmHdr);
+    bool curFrame = get_mp3_frame_size(header,&frameSize);
+    if (!curFrame) {
+        ALOGE("MP3Decoder::read - partial frame does not have a vaild header 0x%x",
+             header);
+        return UNKNOWN_ERROR;
+    }
+
+    // check if the following frame is good
+    uint32_t nextFrameOffset = frameSize - partialBufLen;
+    if ((nextFrameOffset + 4) <= inputBufLen) {
+        header = U32_AT((uint8_t *)mInputBuffer->data() + nextFrameOffset);
+        if ((header & 0xffe00000) != 0xffe00000) {
+            // next frame does not have a valid header,
+            // this may not be the next buffer, bail out.
+            ALOGE("MP3Decoder::read - next frame does not have a vaild header 0x%x",
+                 header);
+            return UNKNOWN_ERROR;
+        }
+    } else {
+        // next frame header is out of range
+        // assume good header for now
+        ALOGE("MP3Decoder::read - assuming next frame is good");
+    }
+
+    // check if the input buffer has the remaining partial frame
+    if (frameSize > (partialBufLen + inputBufLen)) {
+        // input buffer does not have the remaining partial frame,
+        // discard data here as frame split in 3 buffers not supported
+        ALOGE("MP3Decoder::updatePartialFrame - input buffer does not have the complete frame."
+             " frame size %d, saved partial buffer len %d,"
+             " input buffer len %d", frameSize, partialBufLen, inputBufLen);
+        return UNKNOWN_ERROR;
+    }
+
+    // check if the mPartialBuffer can fit the remaining frame
+    if ((mPartialBuffer->size() - partialBufLen) < (frameSize - partialBufLen)) {
+        // mPartialBuffer is small to hold the reaming frame
+        //TODO
+        ALOGE("MP3Decoder::updatePartialFrame - mPartialBuffer is small, size %d, required &d",
+             (mPartialBuffer->size() - partialBufLen), (frameSize - partialBufLen));
+        return UNKNOWN_ERROR;
+    }
+
+    // done with error checks
+    // copy the partial frames to from a complete frame
+    // Copy the remaining frame from input buffer
+    uint32_t bytesRemaining = frameSize - mPartialBuffer->range_length();
+    memcpy ((uint8_t *)mPartialBuffer->data() + mPartialBuffer->range_length(),
+            (uint8_t *)mInputBuffer->data() + mInputBuffer->range_offset(),
+            bytesRemaining);
+
+    // mark the bytes as consumed from input buffer
+    mInputBuffer->set_range(
+                           mInputBuffer->range_offset() + bytesRemaining,
+                           mInputBuffer->range_length() - bytesRemaining);
+
+    // set the range and length of mPartialBuffer
+    mPartialBuffer->set_range(0,
+                              mPartialBuffer->range_length() + bytesRemaining);
+
+    ALOGE("MP3Decoder::updatePartialFrame - copied the partial frame %d, input buffer length %d",
+         bytesRemaining, mInputBuffer->range_length());
+
+    return err;
+}
+
+status_t MP3Decoder::read(
+        MediaBuffer **out, const ReadOptions *options) {
+    status_t err;
+
+    *out = NULL;
+    bool usedPartialFrame = false;
+    bool seekSource = false;
+
+    int64_t seekTimeUs;
+    ReadOptions::SeekMode mode;
+    if (options && options->getSeekTo(&seekTimeUs, &mode)) {
+        CHECK(seekTimeUs >= 0);
+
+        mNumFramesOutput = 0;
+        seekSource = true;
+
+        if (mInputBuffer) {
+            mInputBuffer->release();
+            mInputBuffer = NULL;
+        }
+
+        if (mPartialBuffer) {
+            mPartialBuffer->release();
+            mPartialBuffer = NULL;
+        }
+
+        // Make sure that the next buffer output does not still
+        // depend on fragments from the last one decoded.
+        pvmp3_InitDecoder(mConfig, mDecoderBuf);
+    } else {
+        seekTimeUs = -1;
+    }
+
+    if (mInputBuffer == NULL) {
+        err = mSource->read(&mInputBuffer, options);
+
+        if (err != OK) {
+            return err;
+        }
+
+        if ((mFixedHeader == 0) && (mInputBuffer->range_length() > 4)) {
+            //save the first 4 bytes as fixed header for the reset of the file
+            mFixedHeader = U32_AT((uint8_t *)mInputBuffer->data());
+        }
+
+        if (seekSource == true) {
+            off_t syncOffset = 0;
+            bool valid = resync((uint8_t *)mInputBuffer->data() + mInputBuffer->range_offset()
+                                ,mInputBuffer->range_length(), mFixedHeader, &syncOffset);
+            if (valid) {
+                // consume these bytes, we might find a frame header in next buffer
+                mInputBuffer->set_range(
+                    mInputBuffer->range_offset() + syncOffset,
+                    mInputBuffer->range_length() - syncOffset);
+                ALOGV("mp3 decoder found a sync point after seek syncOffset %d", syncOffset);
+            } else {
+                ALOGV("NO SYNC POINT found, buffer length %d",mInputBuffer->range_length());
+            }
+        }
+
+        int64_t timeUs;
+        if (mInputBuffer->meta_data()->findInt64(kKeyTime, &timeUs)) {
+            mAnchorTimeUs = timeUs;
+            mNumFramesOutput = 0;
+        } else {
+            // We must have a new timestamp after seeking.
+            CHECK(seekTimeUs < 0);
+        }
+        // check for partial frame
+        if (mPartialBuffer != NULL) {
+            err = updatePartialFrame();
+            if (err != OK) {
+                // updating partial frame failed, discard the previously
+                // saved partial frame and continue
+                mPartialBuffer->release();
+                mPartialBuffer = NULL;
+                err = OK;
+            }
+        }
+    }
+
+    MediaBuffer *buffer;
+    CHECK_EQ(mBufferGroup->acquire_buffer(&buffer), OK);
+
+    if (mPartialBuffer != NULL) {
+        mConfig->pInputBuffer =
+        (uint8_t *)mPartialBuffer->data() + mPartialBuffer->range_offset();
+        mConfig->inputBufferCurrentLength = mPartialBuffer->range_length();
+        usedPartialFrame = true;
+    } else {
+        mConfig->pInputBuffer =
+            (uint8_t *)mInputBuffer->data() + mInputBuffer->range_offset();
+        mConfig->inputBufferCurrentLength = mInputBuffer->range_length();
+    }
+
+    mConfig->inputBufferMaxLength = 0;
+    mConfig->inputBufferUsedLength = 0;
+
+    mConfig->outputFrameSize = buffer->size() / sizeof(int16_t);
+    mConfig->pOutputBuffer = static_cast<int16_t *>(buffer->data());
+
+    ERROR_CODE decoderErr;
+    if ((decoderErr = pvmp3_framedecoder(mConfig, mDecoderBuf))
+            != NO_DECODING_ERROR) {
+        ALOGV("mp3 decoder returned error %d", decoderErr);
+
+        if ((decoderErr != NO_ENOUGH_MAIN_DATA_ERROR) &&
+            (decoderErr != SYNCH_LOST_ERROR)) {
+            buffer->release();
+            buffer = NULL;
+
+            mInputBuffer->release();
+            mInputBuffer = NULL;
+            if (mPartialBuffer) {
+                mPartialBuffer->release();
+                mPartialBuffer = NULL;
+            }
+            ALOGE("mp3 decoder returned UNKNOWN_ERROR");
+
+            return UNKNOWN_ERROR;
+        }
+
+        if ((mPartialBuffer == NULL) && (decoderErr == NO_ENOUGH_MAIN_DATA_ERROR)) {
+            // Might be a partial frame, save it
+            mPartialBuffer = new MediaBuffer(mInputBuffer->size());
+            memcpy ((uint8_t *)mPartialBuffer->data(),
+                    mConfig->pInputBuffer, mConfig->inputBufferCurrentLength);
+            mPartialBuffer->set_range(0, mConfig->inputBufferCurrentLength);
+            // set output buffer to 0
+            mConfig->outputFrameSize = 0;
+            // consume the copied bytes from input
+            mConfig->inputBufferUsedLength = mConfig->inputBufferCurrentLength;
+        } else if(decoderErr == SYNCH_LOST_ERROR) {
+            // Try to find the mp3 frame header in the current buffer
+            off_t syncOffset = 0;
+            bool valid = resync(mConfig->pInputBuffer, mConfig->inputBufferCurrentLength,
+                                mFixedHeader, &syncOffset);
+            if (!valid || !syncOffset) {
+                // consume these bytes, we might find a frame header in next buffer
+                syncOffset = mConfig->inputBufferCurrentLength;
+            }
+            // set output buffer to 0
+            mConfig->outputFrameSize = 0;
+            // consume the junk bytes from input buffer
+            mConfig->inputBufferUsedLength = syncOffset;
+        } else {
+            // This is recoverable, just ignore the current frame and
+            // play silence instead.
+            memset(buffer->data(), 0, mConfig->outputFrameSize * sizeof(int16_t));
+            mConfig->inputBufferUsedLength = mInputBuffer->range_length();
+        }
+    }
+
+    buffer->set_range(
+            0, mConfig->outputFrameSize * sizeof(int16_t));
+
+    if ((mPartialBuffer != NULL) && usedPartialFrame) {
+        mPartialBuffer->set_range(
+            mPartialBuffer->range_offset() + mConfig->inputBufferUsedLength,
+            mPartialBuffer->range_length() - mConfig->inputBufferUsedLength);
+        mPartialBuffer->release();
+        mPartialBuffer = NULL;
+    } else {
+        mInputBuffer->set_range(
+            mInputBuffer->range_offset() + mConfig->inputBufferUsedLength,
+            mInputBuffer->range_length() - mConfig->inputBufferUsedLength);
+    }
+
+    if (mInputBuffer->range_length() == 0) {
+        mInputBuffer->release();
+        mInputBuffer = NULL;
+    }
+
+    buffer->meta_data()->setInt64(
+            kKeyTime,
+            mAnchorTimeUs
+                + (mNumFramesOutput * 1000000) / mConfig->samplingRate);
+
+    mNumFramesOutput += mConfig->outputFrameSize / mNumChannels;
+
+    *out = buffer;
+
+    return OK;
+}
+
+}  // namespace android
diff --git a/media/libstagefright/codecs/mp3dec/SoftMP3.cpp b/media/libstagefright/codecs/mp3dec/SoftMP3.cpp
index 7c382fb..be42ae5 100644
--- a/media/libstagefright/codecs/mp3dec/SoftMP3.cpp
+++ b/media/libstagefright/codecs/mp3dec/SoftMP3.cpp
@@ -110,7 +110,7 @@
 void SoftMP3::initDecoder() {
     mConfig->equalizerType = flat;
     mConfig->crcEnabled = false;
-
+    mConfig->samplingRate = mSamplingRate;
     uint32_t memRequirements = pvmp3_decoderMemRequirements();
     mDecoderBuf = malloc(memRequirements);
 
@@ -252,10 +252,13 @@
             if (decoderErr != NO_ENOUGH_MAIN_DATA_ERROR
                         && decoderErr != SIDE_INFO_ERROR) {
                 ALOGE("mp3 decoder returned error %d", decoderErr);
-
-                notify(OMX_EventError, OMX_ErrorUndefined, decoderErr, NULL);
-                mSignalledError = true;
-                return;
+                if(decoderErr == SYNCH_LOST_ERROR) {
+                    mConfig->outputFrameSize = kOutputBufferSize / sizeof(int16_t);
+                } else {
+                    notify(OMX_EventError, OMX_ErrorUndefined, decoderErr, NULL);
+                    mSignalledError = true;
+                    return;
+                }
             }
 
             if (mConfig->outputFrameSize == 0) {
diff --git a/media/libstagefright/colorconversion/SoftwareRenderer.cpp b/media/libstagefright/colorconversion/SoftwareRenderer.cpp
index 77f21b7..d74a5f4 100644
--- a/media/libstagefright/colorconversion/SoftwareRenderer.cpp
+++ b/media/libstagefright/colorconversion/SoftwareRenderer.cpp
@@ -94,11 +94,20 @@
     CHECK(mCropHeight > 0);
     CHECK(mConverter == NULL || mConverter->isValid());
 
+#ifdef EXYNOS4_ENHANCEMENTS
+    CHECK_EQ(0,
+            native_window_set_usage(
+            mNativeWindow.get(),
+            GRALLOC_USAGE_SW_READ_NEVER | GRALLOC_USAGE_SW_WRITE_OFTEN
+            | GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_EXTERNAL_DISP
+            | GRALLOC_USAGE_HW_FIMC1 | GRALLOC_USAGE_HWC_HWOVERLAY));
+#else
     CHECK_EQ(0,
             native_window_set_usage(
             mNativeWindow.get(),
             GRALLOC_USAGE_SW_READ_NEVER | GRALLOC_USAGE_SW_WRITE_OFTEN
             | GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_EXTERNAL_DISP));
+#endif
 
     CHECK_EQ(0,
             native_window_set_scaling_mode(
@@ -200,13 +209,25 @@
         const uint8_t *src_uv =
             (const uint8_t *)data + mWidth * (mHeight - mCropTop / 2);
 
-        uint8_t *dst_y = (uint8_t *)dst;
+#ifdef EXYNOS4_ENHANCEMENTS
+        void *pYUVBuf[3];
 
+        CHECK_EQ(0, mapper.unlock(buf->handle));
+        CHECK_EQ(0, mapper.lock(
+                buf->handle, GRALLOC_USAGE_SW_WRITE_OFTEN | GRALLOC_USAGE_YUV_ADDR, bounds, pYUVBuf));
+
+        size_t dst_c_stride = buf->stride / 2;
+        uint8_t *dst_y = (uint8_t *)pYUVBuf[0];
+        uint8_t *dst_v = (uint8_t *)pYUVBuf[1];
+        uint8_t *dst_u = (uint8_t *)pYUVBuf[2];
+#else
         size_t dst_y_size = buf->stride * buf->height;
         size_t dst_c_stride = ALIGN(buf->stride / 2, 16);
         size_t dst_c_size = dst_c_stride * buf->height / 2;
+        uint8_t *dst_y = (uint8_t *)dst;
         uint8_t *dst_v = dst_y + dst_y_size;
         uint8_t *dst_u = dst_v + dst_c_size;
+#endif
 
         for (int y = 0; y < mCropHeight; ++y) {
             memcpy(dst_y, src_y, mCropWidth);
diff --git a/media/libstagefright/id3/Android.mk b/media/libstagefright/id3/Android.mk
index bf6f7bb..7f0cb6c 100644
--- a/media/libstagefright/id3/Android.mk
+++ b/media/libstagefright/id3/Android.mk
@@ -4,6 +4,10 @@
 LOCAL_SRC_FILES := \
 	ID3.cpp
 
+ifneq ($(TI_CUSTOM_DOMX_PATH),)
+LOCAL_C_INCLUDES += $(TI_CUSTOM_DOMX_PATH)/omx_core/inc
+endif
+
 LOCAL_MODULE := libstagefright_id3
 
 include $(BUILD_STATIC_LIBRARY)
diff --git a/media/libstagefright/include/AwesomePlayer.h b/media/libstagefright/include/AwesomePlayer.h
index 271df8e..61dba35 100644
--- a/media/libstagefright/include/AwesomePlayer.h
+++ b/media/libstagefright/include/AwesomePlayer.h
@@ -1,4 +1,6 @@
 /*
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ * Not a Contribution.
  * Copyright (C) 2009 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -102,6 +104,7 @@
     void postAudioEOS(int64_t delayUs = 0ll);
     void postAudioSeekComplete();
     void postAudioTearDown();
+    void printFileName(int fd);
     status_t dump(int fd, const Vector<String16> &args) const;
 
 private:
@@ -204,6 +207,9 @@
 
     bool mWatchForAudioSeekComplete;
     bool mWatchForAudioEOS;
+#ifdef QCOM_ENHANCED_AUDIO
+    static int mTunnelAliveAP;
+#endif
 
     sp<TimedEventQueue::Event> mVideoEvent;
     bool mVideoEventPending;
@@ -241,6 +247,7 @@
     sp<DecryptHandle> mDecryptHandle;
 
     int64_t mLastVideoTimeUs;
+    int64_t mFrameDurationUs;
     TimedTextDriver *mTextDriver;
 
     sp<WVMExtractor> mWVMExtractor;
@@ -313,6 +320,17 @@
         ASSIGN
     };
     void modifyFlags(unsigned value, FlagMode mode);
+#ifdef QCOM_ENHANCED_AUDIO
+    void checkTunnelExceptions();
+#endif
+    void logFirstFrame();
+    void logCatchUp(int64_t ts, int64_t clock, int64_t delta);
+    void logLate(int64_t ts, int64_t clock, int64_t delta);
+    void logOnTime(int64_t ts, int64_t clock, int64_t delta);
+    void printStats();
+    int64_t getTimeOfDayUs();
+    bool mStatistics;
+    int64_t mLateAVSyncMargin;
 
     struct TrackStat {
         String8 mMIME;
@@ -338,6 +356,23 @@
         int32_t mVideoHeight;
         uint32_t mFlags;
         Vector<TrackStat> mTracks;
+
+        int64_t mConsecutiveFramesDropped;
+        uint32_t mCatchupTimeStart;
+        uint32_t mNumTimesSyncLoss;
+        uint32_t mMaxEarlyDelta;
+        uint32_t mMaxLateDelta;
+        uint32_t mMaxTimeSyncLoss;
+        uint64_t mTotalFrames;
+        int64_t mFirstFrameLatencyStartUs; //first frame latency start
+        int64_t mFirstFrameLatencyUs;
+        int64_t mLastFrameUs;
+        bool mVeryFirstFrame;
+        int64_t mTotalTimeUs;
+        int64_t mLastPausedTimeMs;
+        int64_t mLastSeekToTimeMs;
+        int64_t mResumeDelayStartUs;
+        int64_t mSeekDelayStartUs;
     } mStats;
 
     bool    mOffloadAudio;
@@ -357,6 +392,11 @@
 
     size_t countTracks() const;
 
+#ifdef QCOM_ENHANCED_AUDIO
+    bool inSupportedTunnelFormats(const char * mime);
+    //Flag to check if tunnel mode audio is enabled
+    bool mIsTunnelAudio;
+#endif
     AwesomePlayer(const AwesomePlayer &);
     AwesomePlayer &operator=(const AwesomePlayer &);
 };
diff --git a/media/libstagefright/include/ExtendedExtractor.h b/media/libstagefright/include/ExtendedExtractor.h
new file mode 100644
index 0000000..3bce1ff
--- /dev/null
+++ b/media/libstagefright/include/ExtendedExtractor.h
@@ -0,0 +1,49 @@
+/*Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials provided
+ *      with the distribution.
+ *     * Neither the name of The Linux Foundation nor the names of its
+ *      contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef EXTENDED_EXTRACTOR_
+#define EXTENDED_EXTRACTOR_
+
+#include <media/stagefright/DataSource.h>
+
+namespace android {
+
+class MediaExtractor;
+class ExtendedExtractor
+{
+public:
+    static MediaExtractor* Create (
+            const sp<DataSource> &source, const char *mime);
+    static bool Sniff (
+            const sp<DataSource> &source, String8 *mimeType,
+            float *confidence,sp<AMessage> *meta);
+};
+
+}  // namespace android
+
+#endif //EXTENDED_EXTRACTOR_
diff --git a/media/libstagefright/include/ExtendedUtils.h b/media/libstagefright/include/ExtendedUtils.h
new file mode 100644
index 0000000..1c3f3aa
--- /dev/null
+++ b/media/libstagefright/include/ExtendedUtils.h
@@ -0,0 +1,151 @@
+/*Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials provided
+ *      with the distribution.
+ *     * Neither the name of The Linux Foundation nor the names of its
+ *      contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef QC_UTILS_H_
+#define QC_UTILS_H_
+
+#include <utils/StrongPointer.h>
+#include <media/Metadata.h>
+#include <media/stagefright/MediaSource.h>
+#include <media/stagefright/foundation/AString.h>
+#include <media/stagefright/MediaCodecList.h>
+
+#include <media/MediaRecorderBase.h>
+#include <media/stagefright/MediaExtractor.h>
+#include <camera/CameraParameters.h>
+#include <OMX_Video.h>
+#include <android/native_window.h>
+
+#define MIN_BITERATE_AAC 24000
+#define MAX_BITERATE_AAC 192000
+
+namespace android {
+
+/*
+ * This class is a placeholder for utility methods for
+ * QC specific changes
+ */
+struct ExtendedUtils {
+
+    /*
+     * This class is a placeholder for set of methods used
+     * to enable HFR (High Frame Rate) Recording
+     *
+     * HFR is a slow-motion recording feature where framerate
+     * is increased at capture, but file is composed to play
+     * back at normal rate, giving a net result of slow-motion.
+     * If HFR factor = N
+     *   framerate (at capture and encoder) = N * actual value
+     *   timeStamps (at composition) = N * actual value
+     *   bitrate = N * actual value
+     *      (as the encoder still gets actual timestamps)
+     */
+    struct HFR {
+        // set kKeyHFR when 'video-hfr' paramater is enabled
+        static void setHFRIfEnabled(
+                const CameraParameters& params, sp<MetaData> &meta);
+
+        // recalculate fileduration when hfr is enabled
+        static status_t reCalculateFileDuration(
+                sp<MetaData> &meta, sp<MetaData> &enc_meta,
+                int64_t &maxFileDurationUs, int32_t frameRate,
+                video_encoder videoEncoder);
+
+        // compute timestamp when hfr is enabled
+        static void reCalculateTimeStamp(
+                sp<MetaData> &meta, int64_t &timestampUs);
+
+        // recalculate frameRate and bitrate when hfr is enabled
+        static void reCalculateHFRParams(
+                const sp<MetaData> &meta, int32_t &frameRate,
+                int32_t &bitrate);
+
+        // Copy HFR params (bitrate,framerate) from output to
+        // to input format, if HFR is enabled
+        static void copyHFRParams(
+                const sp<MetaData> &inputFormat,
+                sp<MetaData> &outputFormat);
+    };
+
+    /*
+     * This class is a placeholder for methods to override
+     * default heaviour based on shell properties set
+     */
+    struct ShellProp {
+        // check if shell property to disable audio is set
+        static bool isAudioDisabled();
+
+        //helper function to set encoding profiles
+        static void setEncoderProfile(video_encoder &videoEncoder,
+                int32_t &videoEncoderProfile);
+
+        static bool isSmoothStreamingEnabled();
+
+        static int64_t getMaxAVSyncLateMargin();
+    };
+
+    //set B frames for MPEG4
+    static void setBFrames(OMX_VIDEO_PARAM_MPEG4TYPE &mpeg4type, int32_t &numBFrames,
+            const char* componentName);
+
+    //set B frames for H264
+    static void setBFrames(OMX_VIDEO_PARAM_AVCTYPE &h264type, int32_t &numBFrames,
+            int32_t iFramesInterval, int32_t frameRate, const char* componentName);
+
+    static bool UseQCHWAACEncoder(audio_encoder Encoder, int32_t Channel,
+            int32_t BitRate, int32_t SampleRate);
+
+    static sp<MediaExtractor> MediaExtractor_CreateIfNeeded(
+            sp<MediaExtractor> defaultExt, const sp<DataSource> &source,
+            const char *mime);
+
+    //helper function to add media codecs with specific quirks
+    static void helper_addMediaCodec(Vector<MediaCodecList::CodecInfo> &mCodecInfos,
+                                     KeyedVector<AString, size_t> &mTypes,
+                                     bool encoder, const char *name,
+                                     const char *type, uint32_t quirks);
+
+    //helper function to calculate the value of quirks from strings
+    static uint32_t helper_getCodecSpecificQuirks(KeyedVector<AString, size_t> &mCodecQuirks,
+                                                  Vector<AString> quirks);
+
+    static bool isAVCProfileSupported(int32_t profile);
+
+    //notify stride change to ANW
+    static void updateNativeWindowBufferGeometry(ANativeWindow* anw,
+            OMX_U32 width, OMX_U32 height, OMX_COLOR_FORMATTYPE colorFormat);
+
+    static bool checkIsThumbNailMode(const uint32_t flags, char* componentName);
+
+    static void setArbitraryModeIfInterlaced(
+            const uint8_t *ptr, const sp<MetaData> &meta);
+
+    static int32_t checkIsInterlace(sp<MetaData> &meta);
+};
+
+}
+#endif  //QC_UTILS_H_
diff --git a/media/libstagefright/include/MP3Decoder.h b/media/libstagefright/include/MP3Decoder.h
new file mode 100644
index 0000000..8ff570a
--- /dev/null
+++ b/media/libstagefright/include/MP3Decoder.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 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.
+ */
+
+#ifndef MP3_DECODER_H_
+
+#define MP3_DECODER_H_
+
+#include <media/stagefright/MediaSource.h>
+
+struct tPVMP3DecoderExternal;
+
+namespace android {
+
+struct MediaBufferGroup;
+
+struct MP3Decoder : public MediaSource {
+    MP3Decoder(const sp<MediaSource> &source);
+
+    virtual status_t start(MetaData *params);
+    virtual status_t stop();
+
+    virtual sp<MetaData> getFormat();
+
+    virtual status_t read(
+            MediaBuffer **buffer, const ReadOptions *options);
+
+protected:
+    virtual ~MP3Decoder();
+
+private:
+    sp<MediaSource> mSource;
+    sp<MetaData> mMeta;
+    int32_t mNumChannels;
+
+    bool mStarted;
+
+    MediaBufferGroup *mBufferGroup;
+
+    tPVMP3DecoderExternal *mConfig;
+    void *mDecoderBuf;
+    int64_t mAnchorTimeUs;
+    int64_t mNumFramesOutput;
+    uint32_t mFixedHeader;
+
+    MediaBuffer *mInputBuffer;
+    MediaBuffer *mPartialBuffer;
+
+    void init();
+
+    MP3Decoder(const MP3Decoder &);
+    MP3Decoder &operator=(const MP3Decoder &);
+    status_t updatePartialFrame();
+};
+
+}  // namespace android
+
+#endif  // MP3_DECODER_H_
diff --git a/media/libstagefright/include/SampleIterator.h b/media/libstagefright/include/SampleIterator.h
index b5a043c..47ea5bf 100644
--- a/media/libstagefright/include/SampleIterator.h
+++ b/media/libstagefright/include/SampleIterator.h
@@ -29,7 +29,7 @@
     uint32_t getDescIndex() const { return mChunkDesc; }
     off64_t getSampleOffset() const { return mCurrentSampleOffset; }
     size_t getSampleSize() const { return mCurrentSampleSize; }
-    uint32_t getSampleTime() const { return mCurrentSampleTime; }
+    uint64_t getSampleTime() const { return mCurrentSampleTime; }
 
     status_t getSampleSizeDirect(
             uint32_t sampleIndex, size_t *size);
@@ -53,19 +53,19 @@
 
     uint32_t mTimeToSampleIndex;
     uint32_t mTTSSampleIndex;
-    uint32_t mTTSSampleTime;
+    uint64_t mTTSSampleTime;
     uint32_t mTTSCount;
     uint32_t mTTSDuration;
 
     uint32_t mCurrentSampleIndex;
     off64_t mCurrentSampleOffset;
     size_t mCurrentSampleSize;
-    uint32_t mCurrentSampleTime;
+    uint64_t mCurrentSampleTime;
 
     void reset();
     status_t findChunkRange(uint32_t sampleIndex);
     status_t getChunkOffset(uint32_t chunk, off64_t *offset);
-    status_t findSampleTime(uint32_t sampleIndex, uint32_t *time);
+    status_t findSampleTime(uint32_t sampleIndex, uint64_t *time);
 
     SampleIterator(const SampleIterator &);
     SampleIterator &operator=(const SampleIterator &);
diff --git a/media/libstagefright/include/SampleTable.h b/media/libstagefright/include/SampleTable.h
index 847dff7..d05e7c7 100644
--- a/media/libstagefright/include/SampleTable.h
+++ b/media/libstagefright/include/SampleTable.h
@@ -65,7 +65,7 @@
             uint32_t sampleIndex,
             off64_t *offset,
             size_t *size,
-            uint32_t *compositionTime,
+            uint64_t *compositionTime,
             bool *isSyncSample = NULL);
 
     enum {
@@ -74,7 +74,7 @@
         kFlagClosest
     };
     status_t findSampleAtTime(
-            uint32_t req_time, uint32_t *sample_index, uint32_t flags);
+            uint64_t req_time, uint32_t *sample_index, uint32_t flags);
 
     status_t findSyncSampleNear(
             uint32_t start_sample_index, uint32_t *sample_index,
@@ -113,7 +113,7 @@
 
     struct SampleTimeEntry {
         uint32_t mSampleIndex;
-        uint32_t mCompositionTime;
+        uint64_t mCompositionTime;
     };
     SampleTimeEntry *mSampleTimeEntries;
 
diff --git a/media/libstagefright/include/avc_utils.h b/media/libstagefright/include/avc_utils.h
index d517320..205e8ae 100644
--- a/media/libstagefright/include/avc_utils.h
+++ b/media/libstagefright/include/avc_utils.h
@@ -40,8 +40,11 @@
 void FindAVCDimensions(
         const sp<ABuffer> &seqParamSet,
         int32_t *width, int32_t *height,
+#ifdef QCOM_HARDWARE
+        int32_t *sarWidth = NULL, int32_t *sarHeight = NULL, int32_t *isInterlaced = NULL);
+#else
         int32_t *sarWidth = NULL, int32_t *sarHeight = NULL);
-
+#endif
 unsigned parseUE(ABitReader *br);
 
 status_t getNextNALUnit(
diff --git a/media/libstagefright/mpeg2ts/ESQueue.cpp b/media/libstagefright/mpeg2ts/ESQueue.cpp
index 8f9c9c8..0679a1a 100644
--- a/media/libstagefright/mpeg2ts/ESQueue.cpp
+++ b/media/libstagefright/mpeg2ts/ESQueue.cpp
@@ -504,7 +504,9 @@
 
         if (first) {
             timeUs = info->mTimestampUs;
-            first = false;
+            if(mMode != AAC) {
+                first = false;
+            }
         }
 
         if (info->mLength > size) {
diff --git a/media/libstagefright/omx/Android.mk b/media/libstagefright/omx/Android.mk
index cd912e7..724325f 100644
--- a/media/libstagefright/omx/Android.mk
+++ b/media/libstagefright/omx/Android.mk
@@ -27,6 +27,10 @@
         libstagefright_foundation       \
         libdl
 
+ifeq ($(BOARD_USES_PROPRIETARY_OMX),SAMSUNG)
+LOCAL_CFLAGS     += -DSAMSUNG_OMX
+endif
+
 LOCAL_MODULE:= libstagefright_omx
 
 include $(BUILD_SHARED_LIBRARY)
diff --git a/media/libstagefright/omx/OMXMaster.cpp b/media/libstagefright/omx/OMXMaster.cpp
index 6b6d0ab..c544770 100644
--- a/media/libstagefright/omx/OMXMaster.cpp
+++ b/media/libstagefright/omx/OMXMaster.cpp
@@ -45,6 +45,9 @@
 
 void OMXMaster::addVendorPlugin() {
     addPlugin("libstagefrighthw.so");
+#ifdef SAMSUNG_OMX
+    addPlugin("libsomxcore.so");
+#endif
 }
 
 void OMXMaster::addPlugin(const char *libname) {
diff --git a/media/libstagefright/omx/OMXNodeInstance.cpp b/media/libstagefright/omx/OMXNodeInstance.cpp
index 6c5c857..35fd568 100644
--- a/media/libstagefright/omx/OMXNodeInstance.cpp
+++ b/media/libstagefright/omx/OMXNodeInstance.cpp
@@ -764,15 +764,20 @@
         OMX_U32 portIndex, OMX::buffer_id buffer) {
     Mutex::Autolock autoLock(mLock);
 
-    removeActiveBuffer(portIndex, buffer);
-
     OMX_BUFFERHEADERTYPE *header = (OMX_BUFFERHEADERTYPE *)buffer;
     BufferMeta *buffer_meta = static_cast<BufferMeta *>(header->pAppPrivate);
 
     OMX_ERRORTYPE err = OMX_FreeBuffer(mHandle, portIndex, header);
 
-    delete buffer_meta;
-    buffer_meta = NULL;
+    if (err != OMX_ErrorNone) {
+        ALOGW("OMX_FreeBuffer failed w/ err %x, do not remove from active buffer list", err);
+    } else {
+        ALOGI("OMX_FreeBuffer for buffer header %p successful", header);
+        removeActiveBuffer(portIndex, buffer);
+
+        delete buffer_meta;
+        buffer_meta = NULL;
+    }
 
     return StatusFromOMXError(err);
 }
diff --git a/media/libstagefright/timedtext/Android.mk b/media/libstagefright/timedtext/Android.mk
index f099bbd..4c6172a 100644
--- a/media/libstagefright/timedtext/Android.mk
+++ b/media/libstagefright/timedtext/Android.mk
@@ -14,6 +14,10 @@
         $(TOP)/frameworks/av/include/media/stagefright/timedtext \
         $(TOP)/frameworks/av/media/libstagefright
 
+ifneq ($(TI_CUSTOM_DOMX_PATH),)
+LOCAL_C_INCLUDES += $(TI_CUSTOM_DOMX_PATH)/omx_core/inc
+endif
+
 LOCAL_MODULE:= libstagefright_timedtext
 
 include $(BUILD_STATIC_LIBRARY)
diff --git a/media/libstagefright/wifi-display/Android.mk b/media/libstagefright/wifi-display/Android.mk
index f70454a..7b828fa 100644
--- a/media/libstagefright/wifi-display/Android.mk
+++ b/media/libstagefright/wifi-display/Android.mk
@@ -16,9 +16,14 @@
 
 LOCAL_C_INCLUDES:= \
         $(TOP)/frameworks/av/media/libstagefright \
-        $(TOP)/frameworks/native/include/media/openmax \
         $(TOP)/frameworks/av/media/libstagefright/mpeg2ts \
 
+ifneq ($(TI_CUSTOM_DOMX_PATH),)
+LOCAL_C_INCLUDES += $(TI_CUSTOM_DOMX_PATH)/omx_core/inc
+else
+LOCAL_C_INCLUDES += $(TOP)/frameworks/native/include/media/openmax
+endif
+
 LOCAL_SHARED_LIBRARIES:= \
         libbinder                       \
         libcutils                       \
diff --git a/media/libstagefright/wifi-display/source/WifiDisplaySource.cpp b/media/libstagefright/wifi-display/source/WifiDisplaySource.cpp
index 05e4018..0057d97 100644
--- a/media/libstagefright/wifi-display/source/WifiDisplaySource.cpp
+++ b/media/libstagefright/wifi-display/source/WifiDisplaySource.cpp
@@ -931,7 +931,11 @@
     }
 
     mUsingHDCP = false;
-    if (!params->findParameter("wfd_content_protection", &value)) {
+    char val[PROPERTY_VALUE_MAX];
+    if (property_get("persist.sys.wfd.nohdcp", val, NULL)
+            && !strcmp("1", val)) {
+        ALOGI("Content protection has been disabled for WFD sinks");
+    } else if (!params->findParameter("wfd_content_protection", &value)) {
         ALOGI("Sink doesn't appear to support content protection.");
     } else if (value == "none") {
         ALOGI("Sink does not support content protection.");
diff --git a/media/mediaserver/Android.mk b/media/mediaserver/Android.mk
index 1ac647a..5f84723 100644
--- a/media/mediaserver/Android.mk
+++ b/media/mediaserver/Android.mk
@@ -28,6 +28,11 @@
 LOCAL_STATIC_LIBRARIES := \
 	libregistermsext
 
+ifeq ($(BOARD_USE_SECTVOUT),true)
+	LOCAL_CFLAGS += -DSECTVOUT
+	LOCAL_SHARED_LIBRARIES += libTVOut
+endif
+
 LOCAL_C_INCLUDES := \
     frameworks/av/media/libmediaplayerservice \
     frameworks/av/services/medialog \
diff --git a/media/mediaserver/main_mediaserver.cpp b/media/mediaserver/main_mediaserver.cpp
index d5207d5..efe6e85 100644
--- a/media/mediaserver/main_mediaserver.cpp
+++ b/media/mediaserver/main_mediaserver.cpp
@@ -37,6 +37,12 @@
 
 using namespace android;
 
+#ifdef SECTVOUT
+namespace android { namespace SecTVOutService {
+void instantiate(void);
+} }
+#endif
+
 int main(int argc, char** argv)
 {
     signal(SIGPIPE, SIG_IGN);
@@ -124,6 +130,9 @@
         sp<ProcessState> proc(ProcessState::self());
         sp<IServiceManager> sm = defaultServiceManager();
         ALOGI("ServiceManager: %p", sm.get());
+#ifdef SECTVOUT
+        SecTVOutService::instantiate();
+#endif
         AudioFlinger::instantiate();
         MediaPlayerService::instantiate();
         CameraService::instantiate();
diff --git a/services/audioflinger/Android.mk b/services/audioflinger/Android.mk
index 54377f1..cba7af0 100644
--- a/services/audioflinger/Android.mk
+++ b/services/audioflinger/Android.mk
@@ -46,6 +46,14 @@
     libdl \
     libpowermanager
 
+# SRS Processing
+ifeq ($(strip $(BOARD_USES_SRS_TRUEMEDIA)),true)
+LOCAL_SHARED_LIBRARIES += libsrsprocessing
+LOCAL_CFLAGS += -DSRS_PROCESSING
+LOCAL_C_INCLUDES += $(TARGET_OUT_HEADERS)/mm-audio/audio-effects
+endif
+# SRS Processing
+
 LOCAL_STATIC_LIBRARIES := \
     libscheduling_policy \
     libcpustats \
@@ -64,6 +72,10 @@
     LOCAL_CFLAGS += -DANDROID_SMP=0
 endif
 
+ifeq ($(BOARD_HAVE_PRE_KITKAT_AUDIO_BLOB),true)
+    LOCAL_CFLAGS += -DHAVE_PRE_KITKAT_AUDIO_BLOB
+endif
+
 LOCAL_CFLAGS += -fvisibility=hidden
 
 include $(BUILD_SHARED_LIBRARY)
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index acbd19a..f10c8e0 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -1,5 +1,6 @@
 /*
-**
+** Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
+** Not a Contribution.
 ** Copyright 2007, The Android Open Source Project
 **
 ** Licensed under the Apache License, Version 2.0 (the "License");
@@ -63,6 +64,11 @@
 #include <media/AudioParameter.h>
 #include <private/android_filesystem_config.h>
 
+#ifdef SRS_PROCESSING
+#include "srs_processing.h"
+#include "postpro_patch_ics.h"
+#endif
+
 // ----------------------------------------------------------------------------
 
 // Note: the following macro is used for extremely verbose logging message.  In
@@ -121,11 +127,13 @@
     if (rc) {
         goto out;
     }
+#if !defined(ICS_AUDIO_BLOB) && !defined(MR0_AUDIO_BLOB)
     if ((*dev)->common.version != AUDIO_DEVICE_API_VERSION_CURRENT) {
         ALOGE("%s wrong audio hw device version %04x", __func__, (*dev)->common.version);
         rc = BAD_VALUE;
         goto out;
     }
+#endif
     return 0;
 
 out:
@@ -146,7 +154,12 @@
       mBtNrecIsOff(false),
       mIsLowRamDevice(true),
       mIsDeviceTypeKnown(false),
+#ifdef QCOM_HARDWARE
+      mGlobalEffectEnableTime(0),
+      mAllChainsLocked(false)
+#else
       mGlobalEffectEnableTime(0)
+#endif
 {
     getpid_cached = getpid();
     char value[PROPERTY_VALUE_MAX];
@@ -178,6 +191,11 @@
     Mutex::Autolock _l(mLock);
 
     /* TODO: move all this work into an Init() function */
+#ifdef QCOM_HARDWARE
+    mLPASessionId = -2; // -2 is invalid session ID
+    mIsEffectConfigChanged = false;
+    mLPAEffectChain = NULL;
+#endif
     char val_str[PROPERTY_VALUE_MAX] = { 0 };
     if (property_get("ro.audio.flinger_standbytime_ms", val_str, NULL) >= 0) {
         uint32_t int_val;
@@ -237,6 +255,13 @@
             if ((dev->get_supported_devices != NULL) &&
                     (dev->get_supported_devices(dev) & devices) == devices)
                 return audioHwDevice;
+#ifdef ICS_AUDIO_BLOB
+            else if (dev->get_supported_devices == NULL && i != 0 &&
+                    devices == 0x80)
+                // Reasonably safe assumption: A non-primary HAL without
+                // get_supported_devices is a locally-built A2DP binary
+                return audioHwDevice;
+#endif
         }
     } else {
         // check a match for the requested module handle
@@ -558,9 +583,126 @@
     return trackHandle;
 }
 
+#ifdef QCOM_HARDWARE
+sp<IDirectTrack> AudioFlinger::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)
+{
+    *status = NO_ERROR;
+    status_t lStatus = NO_ERROR;
+    sp<IDirectTrack> track = NULL;
+    DirectAudioTrack* directTrack = NULL;
+    Mutex::Autolock _l(mLock);
+
+    ALOGV("createDirectTrack() sessionId: %d sampleRate %d channelMask %d",
+         *sessionId, sampleRate, channelMask);
+    AudioSessionDescriptor *desc = mDirectAudioTracks.valueFor(output);
+    if(desc == NULL) {
+        ALOGE("Error: Invalid output (%d) to create direct audio track", output);
+        lStatus = BAD_VALUE;
+        goto Exit;
+    }
+    desc->mStreamType = streamType;
+    if (desc->flag & AUDIO_OUTPUT_FLAG_LPA) {
+        if (sessionId != NULL && *sessionId != AUDIO_SESSION_OUTPUT_MIX) {
+            for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
+                sp<PlaybackThread> t = mPlaybackThreads.valueAt(i);
+                // Check if the session ID is already associated with a track
+                uint32_t sessions = t->hasAudioSession(*sessionId);
+
+                // check if an effect with same session ID is waiting for a ssession to be created
+                ALOGV("check if an effect with same session ID is waiting for a ssession to be created");
+                if ((mLPAEffectChain == NULL) && (sessions & PlaybackThread::EFFECT_SESSION)) {
+                    // Clear reference to previous effect chain if any
+                    t->mLock.lock();
+                    ALOGV("getting the LPA effect chain and setting LPA flag to true.");
+                    mLPAEffectChain = t->getEffectChain_l(*sessionId);
+                    t->mLock.unlock();
+                }
+            }
+            mLPASessionId = *sessionId;
+            if (mLPAEffectChain != NULL) {
+                mLPAEffectChain->setLPAFlag(true);
+                // For LPA, the volume will be applied in DSP. No need for volume
+                // control in the Effect chain, so setting it to unity.
+                uint32_t volume = 0x1000000; // Equals to 1.0 in 8.24 format
+                mLPAEffectChain->setVolume_l(&volume,&volume);
+            } else {
+                ALOGW("There was no effectChain created for the sessionId(%d)", mLPASessionId);
+            }
+            mLPASampleRate  = sampleRate;
+            mLPANumChannels = popcount(channelMask);
+        } else {
+            if(sessionId != NULL) {
+                ALOGE("Error: Invalid sessionID (%d) for direct audio track", *sessionId);
+            }
+        }
+    }
+    mLock.unlock();
+    directTrack = new DirectAudioTrack(this, output, desc, client, desc->flag);
+    desc->trackRefPtr = dynamic_cast<void *>(directTrack);
+    mLock.lock();
+    if (directTrack != 0) {
+        track = dynamic_cast<IDirectTrack *>(directTrack);
+        AudioEventObserver* obv = dynamic_cast<AudioEventObserver *>(directTrack);
+        ALOGE("setting observer mOutputDesc track %p, obv %p", track.get(), obv);
+        desc->stream->set_observer(desc->stream, reinterpret_cast<void *>(obv));
+    } else {
+        lStatus = BAD_VALUE;
+    }
+Exit:
+    if(lStatus) {
+        if (track != NULL) {
+            track.clear();
+        }
+        *status = lStatus;
+    }
+    return track;
+}
+
+void AudioFlinger::deleteEffectSession()
+{
+    ALOGV("deleteSession");
+    // -2 is invalid session ID
+    mLPASessionId = -2;
+    if (mLPAEffectChain != NULL) {
+        mLPAEffectChain->lock();
+        mLPAEffectChain->setLPAFlag(false);
+        size_t i, numEffects = mLPAEffectChain->getNumEffects();
+        for(i = 0; i < numEffects; i++) {
+            sp<EffectModule> effect = mLPAEffectChain->getEffectFromIndex_l(i);
+            effect->setInBuffer(mLPAEffectChain->inBuffer());
+            if (i == numEffects-1) {
+                effect->setOutBuffer(mLPAEffectChain->outBuffer());
+            } else {
+                effect->setOutBuffer(mLPAEffectChain->inBuffer());
+            }
+            effect->configure();
+        }
+        mLPAEffectChain->unlock();
+        mLPAEffectChain.clear();
+        mLPAEffectChain = NULL;
+    }
+}
+#endif
+
 uint32_t AudioFlinger::sampleRate(audio_io_handle_t output) const
 {
     Mutex::Autolock _l(mLock);
+#ifdef QCOM_HARDWARE
+    if (!mDirectAudioTracks.isEmpty()) {
+        AudioSessionDescriptor *desc = mDirectAudioTracks.valueFor(output);
+        if(desc != NULL) {
+            return desc->stream->common.get_sample_rate(&desc->stream->common);
+        }
+    }
+#endif
     PlaybackThread *thread = checkPlaybackThread_l(output);
     if (thread == NULL) {
         ALOGW("sampleRate() unknown thread %d", output);
@@ -572,6 +714,12 @@
 int AudioFlinger::channelCount(audio_io_handle_t output) const
 {
     Mutex::Autolock _l(mLock);
+#ifdef QCOM_HARDWARE
+    AudioSessionDescriptor *desc = mDirectAudioTracks.valueFor(output);
+    if(desc != NULL) {
+        return desc->stream->common.get_channels(&desc->stream->common);
+    }
+#endif
     PlaybackThread *thread = checkPlaybackThread_l(output);
     if (thread == NULL) {
         ALOGW("channelCount() unknown thread %d", output);
@@ -594,6 +742,12 @@
 size_t AudioFlinger::frameCount(audio_io_handle_t output) const
 {
     Mutex::Autolock _l(mLock);
+#ifdef QCOM_HARDWARE
+    AudioSessionDescriptor *desc = mDirectAudioTracks.valueFor(output);
+    if(desc != NULL) {
+        return desc->stream->common.get_buffer_size(&desc->stream->common);
+    }
+#endif
     PlaybackThread *thread = checkPlaybackThread_l(output);
     if (thread == NULL) {
         ALOGW("frameCount() unknown thread %d", output);
@@ -607,6 +761,15 @@
 uint32_t AudioFlinger::latency(audio_io_handle_t output) const
 {
     Mutex::Autolock _l(mLock);
+#ifdef QCOM_HARDWARE
+    if (!mDirectAudioTracks.isEmpty()) {
+        AudioSessionDescriptor *desc = mDirectAudioTracks.valueFor(output);
+        if (desc != NULL) {
+            return desc->stream->get_latency(desc->stream);
+        }
+    }
+#endif
+
     PlaybackThread *thread = checkPlaybackThread_l(output);
     if (thread == NULL) {
         ALOGW("latency(): no playback thread found for output handle %d", output);
@@ -737,6 +900,7 @@
     Mutex::Autolock _l(mLock);
     mMasterMute = muted;
 
+#ifndef ICS_AUDIO_BLOB
     // Set master mute in the HALs which support it.
     for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
         AutoMutex lock(mHardwareLock);
@@ -755,6 +919,7 @@
     // mute will simply ignore the setting.
     for (size_t i = 0; i < mPlaybackThreads.size(); i++)
         mPlaybackThreads.valueAt(i)->setMasterMute(muted);
+#endif
 
     return NO_ERROR;
 }
@@ -795,10 +960,33 @@
     }
 
     AutoMutex lock(mLock);
+#ifdef QCOM_HARDWARE
+    ALOGV("setStreamVolume stream %d, output %d, value %f",stream, output, value);
+    AudioSessionDescriptor *desc = NULL;
+    if (!mDirectAudioTracks.isEmpty()) {
+        desc = mDirectAudioTracks.valueFor(output);
+        if (desc != NULL) {
+            ALOGV("setStreamVolume for mAudioTracks size %d desc %p",mDirectAudioTracks.size(),desc);
+            if (desc->mStreamType == stream) {
+                mStreamTypes[stream].volume = value;
+                desc->mVolumeScale = value;
+                desc->stream->set_volume(desc->stream,
+                                         desc->mVolumeLeft * mStreamTypes[stream].volume,
+                                         desc->mVolumeRight* mStreamTypes[stream].volume);
+                return NO_ERROR;
+            }
+        }
+    }
+#endif
     PlaybackThread *thread = NULL;
     if (output) {
         thread = checkPlaybackThread_l(output);
         if (thread == NULL) {
+#ifdef QCOM_HARDWARE
+            if (desc != NULL) {
+                return NO_ERROR;
+            }
+#endif
             return BAD_VALUE;
         }
     }
@@ -881,6 +1069,11 @@
     // ioHandle == 0 means the parameters are global to the audio hardware interface
     if (ioHandle == 0) {
         Mutex::Autolock _l(mLock);
+#ifdef SRS_PROCESSING
+        POSTPRO_PATCH_ICS_PARAMS_SET(keyValuePairs);
+        if (!mDirectAudioTracks.isEmpty())
+            audioConfigChanged_l(AudioSystem::EFFECT_CONFIG_CHANGED, 0, NULL);
+#endif
         status_t final_result = NO_ERROR;
         {
             AutoMutex lock(mHardwareLock);
@@ -928,6 +1121,33 @@
         return final_result;
     }
 
+#ifdef QCOM_HARDWARE
+    AudioSessionDescriptor *desc = NULL;
+    if (!mDirectAudioTracks.isEmpty()) {
+        desc = mDirectAudioTracks.valueFor(ioHandle);
+        if (desc != NULL) {
+            ALOGV("setParameters for mAudioTracks size %d desc %p",mDirectAudioTracks.size(),desc);
+            desc->stream->common.set_parameters(&desc->stream->common, keyValuePairs.string());
+            AudioParameter param = AudioParameter(keyValuePairs);
+            String8 key = String8(AudioParameter::keyRouting);
+            int device;
+            if (param.getInt(key, device) == NO_ERROR) {
+                mDirectDevice = device;
+#ifdef SRS_PROCESSING
+                ALOGV("setParameters:: routing change to device %d", device);
+                POSTPRO_PATCH_ICS_OUTPROC_MIX_ROUTE(desc->trackRefPtr, param, device);
+                if(desc->flag & AUDIO_OUTPUT_FLAG_TUNNEL)
+                    audioConfigChanged_l(AudioSystem::EFFECT_CONFIG_CHANGED, 0, NULL);
+#endif
+                if(mLPAEffectChain != NULL){
+                    mLPAEffectChain->setDevice_l(device);
+                    audioConfigChanged_l(AudioSystem::EFFECT_CONFIG_CHANGED, 0, NULL);
+                }
+            }
+        }
+    }
+#endif
+
     // hold a strong ref on thread in case closeOutput() or closeInput() is called
     // and the thread is exited once the lock is released
     sp<ThreadBase> thread;
@@ -964,6 +1184,9 @@
     if (ioHandle == 0) {
         String8 out_s8;
 
+#ifdef SRS_PROCESSING
+        POSTPRO_PATCH_ICS_PARAMS_GET(keys, out_s8);
+#endif
         for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
             char *s;
             {
@@ -1007,7 +1230,11 @@
     config.format = format;
 
     audio_hw_device_t *dev = mPrimaryHardwareDev->hwDevice();
+#ifndef ICS_AUDIO_BLOB
     size_t size = dev->get_input_buffer_size(dev, &config);
+#else
+    size_t size = dev->get_input_buffer_size(dev, sampleRate, format, popcount(channelMask));
+#endif
     mHardwareStatus = AUDIO_HW_IDLE;
     return size;
 }
@@ -1088,6 +1315,23 @@
     }
 }
 
+#ifdef QCOM_HARDWARE
+status_t AudioFlinger::deregisterClient(const sp<IAudioFlingerClient>& client)
+{
+    ALOGV("deregisterClient() %p, tid %d, calling tid %d", client.get(), gettid(), IPCThreadState::self()->getCallingPid());
+    Mutex::Autolock _l(mLock);
+
+    pid_t pid = IPCThreadState::self()->getCallingPid();
+    int index = mNotificationClients.indexOfKey(pid);
+    if (index >= 0) {
+        mNotificationClients.removeItemsAt(index);
+        return true;
+    }
+
+    return false;
+}
+#endif
+
 void AudioFlinger::removeNotificationClient(pid_t pid)
 {
     Mutex::Autolock _l(mLock);
@@ -1118,11 +1362,33 @@
 // audioConfigChanged_l() must be called with AudioFlinger::mLock held
 void AudioFlinger::audioConfigChanged_l(int event, audio_io_handle_t ioHandle, const void *param2)
 {
-    size_t size = mNotificationClients.size();
-    for (size_t i = 0; i < size; i++) {
-        mNotificationClients.valueAt(i)->audioFlingerClient()->ioConfigChanged(event, ioHandle,
-                                                                               param2);
+#ifdef QCOM_HARDWARE
+    ALOGV("AudioFlinger::audioConfigChanged_l: event %d", event);
+    if (event == AudioSystem::EFFECT_CONFIG_CHANGED) {
+        mIsEffectConfigChanged = true;
     }
+    if (!mNotificationClients.isEmpty()){
+#endif
+        size_t size = mNotificationClients.size();
+        for (size_t i = 0; i < size; i++) {
+            mNotificationClients.valueAt(i)->audioFlingerClient()->ioConfigChanged(event, ioHandle,
+                                                                                   param2);
+        }
+#ifdef QCOM_HARDWARE
+    }
+    if ((!mDirectAudioTracks.isEmpty())&& (event == AudioSystem::EFFECT_CONFIG_CHANGED)){
+        size_t dsize = mDirectAudioTracks.size();
+        for(size_t i = 0; i < dsize; i++) {
+            AudioSessionDescriptor *desc = mDirectAudioTracks.valueAt(i);
+            if(desc && ((DirectAudioTrack*)desc->trackRefPtr)) {
+                ALOGV("signalling directAudioTrack ");
+                ((DirectAudioTrack*)desc->trackRefPtr)->signalEffect();
+            } else{
+                ALOGV("not found track to signal directAudioTrack ");
+            }
+        }
+    }
+#endif
 }
 
 // removeClient_l() must be called with AudioFlinger::mLock held
@@ -1243,6 +1509,10 @@
     RecordThread *thread;
     size_t inFrameCount;
     int lSessionId;
+#ifdef QCOM_HARDWARE
+    size_t inputBufferSize = 0;
+    uint32_t channelCount = popcount(channelMask);
+#endif
 
     // check calling permissions
     if (!recordingAllowed()) {
@@ -1251,11 +1521,21 @@
         goto Exit;
     }
 
+#ifdef QCOM_HARDWARE
+    // Check that audio input stream accepts requested audio parameters
+    inputBufferSize = getInputBufferSize(sampleRate, format, channelCount);
+    if (inputBufferSize == 0) {
+        lStatus = BAD_VALUE;
+        ALOGE("Bad audio input parameters: sampling rate %u, format %d, channels %d",  sampleRate, format, channelCount);
+        goto Exit;
+    }
+#else
     if (format != AUDIO_FORMAT_PCM_16_BIT) {
         ALOGE("openRecord() invalid format %d", format);
         lStatus = BAD_VALUE;
         goto Exit;
     }
+#endif
 
     // add client to list
     { // scope for mLock
@@ -1286,6 +1566,32 @@
                 *sessionId = lSessionId;
             }
         }
+
+#ifdef QCOM_HARDWARE
+        // frameCount must be a multiple of input buffer size
+        // Change for Codec type
+        uint8_t channelCount = popcount(channelMask);
+        if (*flags & IAudioFlinger::TRACK_VOICE_COMMUNICATION) {
+             inFrameCount = inputBufferSize/channelCount/sizeof(short);
+        } else {
+            if ((format == AUDIO_FORMAT_PCM_16_BIT) ||
+                (format == AUDIO_FORMAT_PCM_8_BIT)) {
+              inFrameCount = inputBufferSize/channelCount/sizeof(short);
+            } else if (format == AUDIO_FORMAT_AMR_NB) {
+              inFrameCount = inputBufferSize/channelCount/AMR_FRAMESIZE;
+            } else if (format == AUDIO_FORMAT_EVRC) {
+              inFrameCount = inputBufferSize/channelCount/EVRC_FRAMESIZE;
+            } else if (format == AUDIO_FORMAT_QCELP) {
+              inFrameCount = inputBufferSize/channelCount/QCELP_FRAMESIZE;
+            } else if (format == AUDIO_FORMAT_AAC) {
+              inFrameCount = inputBufferSize/AAC_FRAMESIZE;
+            } else if (format == AUDIO_FORMAT_AMR_WB) {
+              inFrameCount = inputBufferSize/channelCount/AMR_WB_FRAMESIZE;
+            }
+        }
+        frameCount = ((frameCount - 1)/inFrameCount + 1) * inFrameCount;
+#endif
+
         // create new record track.
         // The record track uses one track in mHardwareMixerThread by convention.
         // TODO: the uid should be passed in as a parameter to openRecord
@@ -1362,6 +1668,7 @@
     {  // scope for auto-lock pattern
         AutoMutex lock(mHardwareLock);
 
+#if !defined(ICS_AUDIO_BLOB) && !defined(MR0_AUDIO_BLOB)
         if (0 == mAudioHwDevs.size()) {
             mHardwareStatus = AUDIO_HW_GET_MASTER_VOLUME;
             if (NULL != dev->get_master_volume) {
@@ -1379,6 +1686,7 @@
                 }
             }
         }
+#endif
 
         mHardwareStatus = AUDIO_HW_SET_MASTER_VOLUME;
         if ((NULL != dev->set_master_volume) &&
@@ -1387,12 +1695,14 @@
                     AudioHwDevice::AHWD_CAN_SET_MASTER_VOLUME);
         }
 
+#if !defined(ICS_AUDIO_BLOB) && !defined(MR0_AUDIO_BLOB)
         mHardwareStatus = AUDIO_HW_SET_MASTER_MUTE;
         if ((NULL != dev->set_master_mute) &&
             (OK == dev->set_master_mute(dev, mMasterMute))) {
             flags = static_cast<AudioHwDevice::Flags>(flags |
                     AudioHwDevice::AHWD_CAN_SET_MASTER_MUTE);
         }
+#endif
 
         mHardwareStatus = AUDIO_HW_IDLE;
     }
@@ -1442,6 +1752,20 @@
 
 // ----------------------------------------------------------------------------
 
+#ifdef HAVE_PRE_KITKAT_AUDIO_BLOB
+audio_io_handle_t AudioFlinger::openOutput(audio_module_handle_t module,
+                                           audio_devices_t *pDevices,
+                                           uint32_t *pSamplingRate,
+                                           audio_format_t *pFormat,
+                                           audio_channel_mask_t *pChannelMask,
+                                           uint32_t *pLatencyMs,
+                                           audio_output_flags_t flags)
+{
+    return openOutput(module, pDevices, pSamplingRate, pFormat, pChannelMask,
+            pLatencyMs, flags, NULL);
+}
+#endif
+
 audio_io_handle_t AudioFlinger::openOutput(audio_module_handle_t module,
                                            audio_devices_t *pDevices,
                                            uint32_t *pSamplingRate,
@@ -1456,9 +1780,11 @@
     config.sample_rate = (pSamplingRate != NULL) ? *pSamplingRate : 0;
     config.channel_mask = (pChannelMask != NULL) ? *pChannelMask : 0;
     config.format = (pFormat != NULL) ? *pFormat : AUDIO_FORMAT_DEFAULT;
+#ifndef HAVE_PRE_KITKAT_AUDIO_BLOB
     if (offloadInfo) {
         config.offload_info = *offloadInfo;
     }
+#endif
 
     audio_stream_out_t *outStream = NULL;
     AudioHwDevice *outHwDev;
@@ -1470,8 +1796,10 @@
               config.format,
               config.channel_mask,
               flags);
+#ifndef HAVE_PRE_KITKAT_AUDIO_BLOB
     ALOGV("openOutput(), offloadInfo %p version 0x%04x",
           offloadInfo, offloadInfo == NULL ? -1 : offloadInfo->version );
+#endif
 
     if (pDevices == NULL || *pDevices == 0) {
         return 0;
@@ -1488,12 +1816,24 @@
 
     mHardwareStatus = AUDIO_HW_OUTPUT_OPEN;
 
-    status_t status = hwDevHal->open_output_stream(hwDevHal,
+    status_t status;
+#ifndef ICS_AUDIO_BLOB
+    status = hwDevHal->open_output_stream(hwDevHal,
                                           id,
                                           *pDevices,
                                           (audio_output_flags_t)flags,
                                           &config,
                                           &outStream);
+#else
+    status = hwDevHal->open_output_stream(hwDevHal,
+                                          *pDevices,
+                                          (int *)&config.format,
+                                          &config.channel_mask,
+                                          &config.sample_rate,
+                                          &outStream);
+    uint32_t newflags = flags | AUDIO_OUTPUT_FLAG_PRIMARY;
+    flags = (audio_output_flags_t)newflags;
+#endif
 
     mHardwareStatus = AUDIO_HW_IDLE;
     ALOGV("openOutput() openOutputStream returned output %p, SamplingRate %d, Format %#08x, "
@@ -1506,10 +1846,23 @@
 
     if (status == NO_ERROR && outStream != NULL) {
         AudioStreamOut *output = new AudioStreamOut(outHwDev, outStream, flags);
-
         if (flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
             thread = new OffloadThread(this, output, id, *pDevices);
             ALOGV("openOutput() created offload output: ID %d thread %p", id, thread);
+#ifdef QCOM_HARDWARE
+        }
+        if (flags & AUDIO_OUTPUT_FLAG_LPA || flags & AUDIO_OUTPUT_FLAG_TUNNEL ) {
+            AudioSessionDescriptor *desc = new AudioSessionDescriptor(hwDevHal, outStream, flags);
+            desc->mActive = true;
+            //TODO: no stream type
+            //desc->mStreamType = streamType;
+            desc->mVolumeLeft = 1.0;
+            desc->mVolumeRight = 1.0;
+            desc->device = *pDevices;
+            desc->trackRefPtr = NULL;
+            mDirectAudioTracks.add(id, desc);
+            mDirectDevice = desc->device;
+#endif
         } else if ((flags & AUDIO_OUTPUT_FLAG_DIRECT) ||
             (config.format != AUDIO_FORMAT_PCM_16_BIT) ||
             (config.channel_mask != AUDIO_CHANNEL_OUT_STEREO)) {
@@ -1519,7 +1872,9 @@
             thread = new MixerThread(this, output, id, *pDevices);
             ALOGV("openOutput() created mixer output: ID %d thread %p", id, thread);
         }
-        mPlaybackThreads.add(id, thread);
+        if (thread != NULL) {
+            mPlaybackThreads.add(id, thread);
+        }
 
         if (pSamplingRate != NULL) {
             *pSamplingRate = config.sample_rate;
@@ -1530,18 +1885,30 @@
         if (pChannelMask != NULL) {
             *pChannelMask = config.channel_mask;
         }
-        if (pLatencyMs != NULL) {
-            *pLatencyMs = thread->latency();
+        if (thread != NULL) {
+            if (pLatencyMs != NULL) *pLatencyMs = thread->latency();
+            // notify client processes of the new output creation
+            thread->audioConfigChanged_l(AudioSystem::OUTPUT_OPENED);
         }
+#ifdef QCOM_HARDWARE
+        else {
+            *pLatencyMs = 0;
+            if ((flags & AUDIO_OUTPUT_FLAG_LPA) || (flags & AUDIO_OUTPUT_FLAG_TUNNEL)) {
+                AudioSessionDescriptor *desc = mDirectAudioTracks.valueFor(id);
+                *pLatencyMs = desc->stream->get_latency(desc->stream);
+            }
+        }
+#endif
 
-        // notify client processes of the new output creation
-        thread->audioConfigChanged_l(AudioSystem::OUTPUT_OPENED);
 
         // the first primary output opened designates the primary hw device
         if ((mPrimaryHardwareDev == NULL) && (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
             ALOGI("Using module %d has the primary audio interface", module);
             mPrimaryHardwareDev = outHwDev;
-
+#ifdef SRS_PROCESSING
+            SRS_Processing::RawDataSet(NULL, "qdsp hook", &mPrimaryHardwareDev,
+                sizeof(&mPrimaryHardwareDev));
+#endif
             AutoMutex lock(mHardwareLock);
             mHardwareStatus = AUDIO_HW_SET_MODE;
             hwDevHal->set_mode(hwDevHal, mMode);
@@ -1584,6 +1951,22 @@
 {
     // keep strong reference on the playback thread so that
     // it is not destroyed while exit() is executed
+#ifdef QCOM_HARDWARE
+    AudioSessionDescriptor *desc = mDirectAudioTracks.valueFor(output);
+    if (desc) {
+        ALOGV("Closing DirectTrack output %d", output);
+        desc->mActive = false;
+        desc->stream->common.standby(&desc->stream->common);
+        desc->hwDev->close_output_stream(desc->hwDev, desc->stream);
+        desc->trackRefPtr = NULL;
+        desc->stream = NULL;
+        mDirectAudioTracks.removeItem(output);
+        audioConfigChanged_l(AudioSystem::OUTPUT_CLOSED, output, NULL);
+        delete desc;
+        return NO_ERROR;
+    }
+#endif
+
     sp<PlaybackThread> thread;
     {
         Mutex::Autolock _l(mLock);
@@ -1700,8 +2083,16 @@
     audio_hw_device_t *inHwHal = inHwDev->hwDevice();
     audio_io_handle_t id = nextUniqueId();
 
+#ifndef ICS_AUDIO_BLOB
     status = inHwHal->open_input_stream(inHwHal, id, *pDevices, &config,
                                         &inStream);
+#else
+    status = inHwHal->open_input_stream(inHwHal, *pDevices, 
+                                        (int *)&config.format, 
+                                        &config.channel_mask,
+                                        &config.sample_rate, (audio_in_acoustics_t)0,
+                                        &inStream);
+#endif
     ALOGV("openInput() openInputStream returned input %p, SamplingRate %d, Format %d, Channels %x, "
             "status %d",
             inStream,
@@ -1716,10 +2107,18 @@
     if (status == BAD_VALUE &&
         reqFormat == config.format && config.format == AUDIO_FORMAT_PCM_16_BIT &&
         (config.sample_rate <= 2 * reqSamplingRate) &&
-        (popcount(config.channel_mask) <= FCC_2) && (popcount(reqChannels) <= FCC_2)) {
+        (getInputChannelCount(config.channel_mask) <= FCC_2) && (getInputChannelCount(reqChannels) <= FCC_2)) {
         ALOGV("openInput() reopening with proposed sampling rate and channel mask");
         inStream = NULL;
+#ifndef ICS_AUDIO_BLOB
         status = inHwHal->open_input_stream(inHwHal, id, *pDevices, &config, &inStream);
+#else
+        status = inHwHal->open_input_stream(inHwHal, *pDevices, 
+                                        (int *)&config.format, 
+                                        &config.channel_mask,
+                                        &config.sample_rate, (audio_in_acoustics_t)0,
+                                        &inStream);
+#endif
     }
 
     if (status == NO_ERROR && inStream != NULL) {
@@ -2525,8 +2924,6 @@
 }
 #endif
 
-// ----------------------------------------------------------------------------
-
 status_t AudioFlinger::onTransact(
         uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
 {
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index 53e238e..c0c9b99 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -1,5 +1,6 @@
 /*
-**
+** Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+** Not a Contribution.
 ** Copyright 2007, The Android Open Source Project
 **
 ** Licensed under the Apache License, Version 2.0 (the "License");
@@ -28,6 +29,10 @@
 
 #include <media/IAudioFlinger.h>
 #include <media/IAudioFlingerClient.h>
+#ifdef QCOM_HARDWARE
+#include <media/IDirectTrack.h>
+#include <media/IDirectTrackClient.h>
+#endif
 #include <media/IAudioTrack.h>
 #include <media/IAudioRecord.h>
 #include <media/AudioSystem.h>
@@ -54,7 +59,7 @@
 #include "AudioWatchdog.h"
 
 #include <powermanager/IPowerManager.h>
-
+#include <utils/List.h>
 #include <media/nbaio/NBLog.h>
 #include <private/media/AudioTrackShared.h>
 
@@ -86,6 +91,14 @@
 
 #define INCLUDING_FROM_AUDIOFLINGER_H
 
+static uint32_t getInputChannelCount(uint32_t channels) {
+    // only mono, stereo, and 5.1 are supported for input sources
+#ifdef QCOM_HARDWARE
+    return popcount((channels)&(AUDIO_CHANNEL_IN_STEREO|AUDIO_CHANNEL_IN_MONO|AUDIO_CHANNEL_IN_5POINT1));
+#else
+    return popcount(channels);
+#endif
+}
 class AudioFlinger :
     public BinderService<AudioFlinger>,
     public BnAudioFlinger
@@ -111,7 +124,18 @@
                                 String8& name,
                                 int clientUid,
                                 status_t *status);
-
+#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);
+    virtual void deleteEffectSession();
+#endif
     virtual sp<IAudioRecord> openRecord(
                                 audio_io_handle_t input,
                                 uint32_t sampleRate,
@@ -152,10 +176,22 @@
     virtual     String8     getParameters(audio_io_handle_t ioHandle, const String8& keys) const;
 
     virtual     void        registerClient(const sp<IAudioFlingerClient>& client);
-
+#ifdef QCOM_HARDWARE
+    virtual     status_t    deregisterClient(const sp<IAudioFlingerClient>& client);
+#endif
     virtual     size_t      getInputBufferSize(uint32_t sampleRate, audio_format_t format,
                                                audio_channel_mask_t channelMask) const;
 
+#ifdef HAVE_PRE_KITKAT_AUDIO_BLOB
+    virtual audio_io_handle_t openOutput(audio_module_handle_t module,
+                                         audio_devices_t *pDevices,
+                                         uint32_t *pSamplingRate,
+                                         audio_format_t *pFormat,
+                                         audio_channel_mask_t *pChannelMask,
+                                         uint32_t *pLatencyMs,
+                                         audio_output_flags_t flags);
+#endif
+
     virtual audio_io_handle_t openOutput(audio_module_handle_t module,
                                          audio_devices_t *pDevices,
                                          uint32_t *pSamplingRate,
@@ -230,6 +266,14 @@
                                 Parcel* reply,
                                 uint32_t flags);
 
+#ifdef QCOM_HARDWARE
+    bool applyEffectsOn(void *token,
+                        int16_t *buffer1,
+                        int16_t *buffer2,
+                        int size,
+                        bool force);
+#endif
+
     // end of IAudioFlinger interface
 
     sp<NBLog::Writer>   newWriter_l(size_t size, const char *name);
@@ -375,6 +419,9 @@
     class EffectModule;
     class EffectHandle;
     class EffectChain;
+#ifdef QCOM_HARDWARE
+    struct AudioSessionDescriptor;
+#endif
     struct AudioStreamOut;
     struct AudioStreamIn;
 
@@ -464,7 +511,118 @@
 
               sp<PlaybackThread> getEffectThread_l(int sessionId, int EffectId);
 
+#ifdef QCOM_HARDWARE
+    // server side of the client's IAudioTrack
+    class DirectAudioTrack : public android::BnDirectTrack,
+                             public AudioEventObserver
+    {
+    public:
+                            DirectAudioTrack(const sp<AudioFlinger>& audioFlinger,
+                                             int output, AudioSessionDescriptor *outputDesc,
+                                             IDirectTrackClient* client, audio_output_flags_t outflag);
+        virtual             ~DirectAudioTrack();
+        virtual status_t    start();
+        virtual void        stop();
+        virtual void        flush();
+        virtual void        mute(bool);
+        virtual void        pause();
+        virtual ssize_t     write(const void *buffer, size_t bytes);
+        virtual void        setVolume(float left, float right);
+        virtual int64_t     getTimeStamp();
+        virtual void        postEOS(int64_t delayUs);
+        void                signalEffect();
 
+        virtual status_t    onTransact(
+            uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags);
+    private:
+
+        IDirectTrackClient* mClient;
+        AudioSessionDescriptor *mOutputDesc;
+        int  mOutput;
+        bool mIsPaused;
+        audio_output_flags_t mFlag;
+
+        class BufferInfo {
+        public:
+            BufferInfo(void *buf1, void *buf2, int32_t nSize) :
+            localBuf(buf1), dspBuf(buf2), memBufsize(nSize)
+            {}
+
+            void *localBuf;
+            void *dspBuf;
+            uint32_t memBufsize;
+            uint32_t bytesToWrite;
+        };
+        List<BufferInfo> mBufPool;
+        List<BufferInfo> mEffectsPool;
+        void *mEffectsThreadScratchBuffer;
+
+        void allocateBufPool();
+        void deallocateBufPool();
+
+        //******Effects*************
+        static void *EffectsThreadWrapper(void *me);
+        void EffectsThreadEntry();
+        // make sure the Effects thread also exited
+        void requestAndWaitForEffectsThreadExit();
+        void createEffectThread();
+        Condition mEffectCv;
+        Mutex mEffectLock;
+        pthread_t mEffectsThread;
+        bool mKillEffectsThread;
+        bool mEffectsThreadAlive;
+        bool mEffectConfigChanged;
+
+        //Structure to recieve the Effect notification from the flinger.
+        class AudioFlingerDirectTrackClient: public IBinder::DeathRecipient, public BnAudioFlingerClient {
+        public:
+            AudioFlingerDirectTrackClient(void *obj);
+
+            DirectAudioTrack *pBaseClass;
+            // DeathRecipient
+            virtual void binderDied(const wp<IBinder>& who);
+
+            // IAudioFlingerClient
+
+            // indicate a change in the configuration of an output or input: keeps the cached
+            // values for output/input parameters upto date in client process
+            virtual void ioConfigChanged(int event, audio_io_handle_t ioHandle, const void *param2);
+
+            friend class DirectAudioTrack;
+        };
+        // helper function to obtain AudioFlinger service handle
+        sp<AudioFlinger> mAudioFlinger;
+        sp<AudioFlingerDirectTrackClient> mAudioFlingerClient;
+
+        void clearPowerManager();
+
+        class PMDeathRecipient : public IBinder::DeathRecipient {
+            public:
+                            PMDeathRecipient(void *obj){parentClass = (DirectAudioTrack *)obj;}
+                virtual     ~PMDeathRecipient() {}
+
+                // IBinder::DeathRecipient
+                virtual     void        binderDied(const wp<IBinder>& who);
+
+            private:
+                            DirectAudioTrack *parentClass;
+                            PMDeathRecipient(const PMDeathRecipient&);
+                            PMDeathRecipient& operator = (const PMDeathRecipient&);
+
+            friend class DirectAudioTrack;
+        };
+
+        friend class PMDeathRecipient;
+
+        Mutex pmLock;
+        void        acquireWakeLock();
+        void        releaseWakeLock();
+
+        sp<IPowerManager>       mPowerManager;
+        sp<IBinder>             mWakeLockToken;
+        sp<PMDeathRecipient>    mDeathRecipient;
+    };
+#endif
                 void        removeClient_l(pid_t pid);
                 void        removeNotificationClient(pid_t pid);
 
@@ -526,6 +684,22 @@
         AudioStreamIn(AudioHwDevice *dev, audio_stream_in_t *in) :
             audioHwDev(dev), stream(in) {}
     };
+#ifdef QCOM_HARDWARE
+    struct AudioSessionDescriptor {
+        bool    mActive;
+        int     mStreamType;
+        float   mVolumeLeft;
+        float   mVolumeRight;
+        float   mVolumeScale;
+        audio_hw_device_t   *hwDev;
+        audio_stream_out_t  *stream;
+        audio_output_flags_t flag;
+        void *trackRefPtr;
+        audio_devices_t device;
+        AudioSessionDescriptor(audio_hw_device_t *dev, audio_stream_out_t *out, audio_output_flags_t outflag) :
+            hwDev(dev), stream(out), flag(outflag)  {}
+    };
+#endif
 
     // for mAudioSessionRefs only
     struct AudioSessionRef {
@@ -590,10 +764,20 @@
                 volatile int32_t                    mNextUniqueId;  // updated by android_atomic_inc
                 audio_mode_t                        mMode;
                 bool                                mBtNrecIsOff;
-
+#ifdef QCOM_HARDWARE
+                DefaultKeyedVector<audio_io_handle_t, AudioSessionDescriptor *> mDirectAudioTracks;
                 // protected by mLock
+                volatile bool                       mIsEffectConfigChanged;
+#endif
                 Vector<AudioSessionRef*> mAudioSessionRefs;
-
+#ifdef QCOM_HARDWARE
+                sp<EffectChain> mLPAEffectChain;
+                int         mLPASessionId;
+                audio_devices_t mDirectDevice;//device for directTrack,used for effects
+                int                                 mLPASampleRate;
+                int                                 mLPANumChannels;
+                volatile bool                       mAllChainsLocked;
+#endif
                 float       masterVolume_l() const;
                 bool        masterMute_l() const;
                 audio_module_handle_t loadHwModule_l(const char *name);
diff --git a/services/audioflinger/AudioMixer.cpp b/services/audioflinger/AudioMixer.cpp
index 07dc6dd..32d2892 100644
--- a/services/audioflinger/AudioMixer.cpp
+++ b/services/audioflinger/AudioMixer.cpp
@@ -561,7 +561,11 @@
                       (value == 48000 && devSampleRate == 44100))) {
                     quality = AudioResampler::LOW_QUALITY;
                 } else {
+#ifdef QCOM_HARDWARE
+                    quality = AudioResampler::VERY_HIGH_QUALITY;
+#else
                     quality = AudioResampler::DEFAULT_QUALITY;
+#endif
                 }
                 resampler = AudioResampler::create(
                         format,
diff --git a/services/audioflinger/AudioPolicyService.cpp b/services/audioflinger/AudioPolicyService.cpp
index 35e816b..4cb6df5 100644
--- a/services/audioflinger/AudioPolicyService.cpp
+++ b/services/audioflinger/AudioPolicyService.cpp
@@ -418,12 +418,15 @@
         return BAD_VALUE;
     }
     Mutex::Autolock _l(mLock);
+#ifndef ICS_AUDIO_BLOB
     if (mpAudioPolicy->set_stream_volume_index_for_device) {
         return mpAudioPolicy->set_stream_volume_index_for_device(mpAudioPolicy,
                                                                 stream,
                                                                 index,
                                                                 device);
-    } else {
+    } else 
+#endif
+    {
         return mpAudioPolicy->set_stream_volume_index(mpAudioPolicy, stream, index);
     }
 }
@@ -439,12 +442,15 @@
         return BAD_VALUE;
     }
     Mutex::Autolock _l(mLock);
+#ifndef ICS_AUDIO_BLOB
     if (mpAudioPolicy->get_stream_volume_index_for_device) {
         return mpAudioPolicy->get_stream_volume_index_for_device(mpAudioPolicy,
                                                                 stream,
                                                                 index,
                                                                 device);
-    } else {
+    } else 
+#endif
+    {
         return mpAudioPolicy->get_stream_volume_index(mpAudioPolicy, stream, index);
     }
 }
@@ -515,15 +521,19 @@
 
 bool AudioPolicyService::isStreamActiveRemotely(audio_stream_type_t stream, uint32_t inPastMs) const
 {
+#if !defined(ICS_AUDIO_BLOB) && !defined(MR1_AUDIO_BLOB)
     if (mpAudioPolicy == NULL) {
         return 0;
     }
     Mutex::Autolock _l(mLock);
     return mpAudioPolicy->is_stream_active_remotely(mpAudioPolicy, stream, inPastMs);
+#endif
+    return 0;
 }
 
 bool AudioPolicyService::isSourceActive(audio_source_t source) const
 {
+#ifndef ICS_AUDIO_BLOB
     if (mpAudioPolicy == NULL) {
         return false;
     }
@@ -532,6 +542,9 @@
     }
     Mutex::Autolock _l(mLock);
     return mpAudioPolicy->is_source_active(mpAudioPolicy, source);
+#else
+    return false;
+#endif
 }
 
 status_t AudioPolicyService::queryDefaultPreProcessing(int audioSession,
@@ -1020,7 +1033,9 @@
             } else {
                 data2->mKeyValuePairs = param2.toString();
             }
-            command->mTime = command2->mTime;
+            if (!strcmp(data2->mKeyValuePairs.string(), data->mKeyValuePairs.string())){
+                command->mTime = command2->mTime;
+            }
             // force delayMs to non 0 so that code below does not request to wait for
             // command status as the command is now delayed
             delayMs = 1;
@@ -1137,6 +1152,9 @@
 
 bool AudioPolicyService::isOffloadSupported(const audio_offload_info_t& info)
 {
+#ifdef HAVE_PRE_KITKAT_AUDIO_BLOB
+    return false;
+#endif
     if (mpAudioPolicy == NULL) {
         ALOGV("mpAudioPolicy == NULL");
         return false;
diff --git a/services/audioflinger/AudioResampler.cpp b/services/audioflinger/AudioResampler.cpp
index 2c3c719..48c189c 100644
--- a/services/audioflinger/AudioResampler.cpp
+++ b/services/audioflinger/AudioResampler.cpp
@@ -52,6 +52,7 @@
     static const int kPreInterpShift = kNumPhaseBits - kNumInterpBits;
 
     void init() {}
+    void reset();
     void resampleMono16(int32_t* out, size_t outFrameCount,
             AudioBufferProvider* provider);
     void resampleStereo16(int32_t* out, size_t outFrameCount,
@@ -294,6 +295,14 @@
     }
 }
 
+void AudioResamplerOrder1::reset() {
+    mInputIndex = 0;
+    mPhaseFraction = 0;
+    mBuffer.frameCount = 0;
+    mX0L = 0;
+    mX0R = 0;
+}
+
 void AudioResamplerOrder1::resampleStereo16(int32_t* out, size_t outFrameCount,
         AudioBufferProvider* provider) {
 
diff --git a/services/audioflinger/AudioResamplerCubic.cpp b/services/audioflinger/AudioResamplerCubic.cpp
index 18e59e9..ff4e473 100644
--- a/services/audioflinger/AudioResamplerCubic.cpp
+++ b/services/audioflinger/AudioResamplerCubic.cpp
@@ -32,6 +32,14 @@
     memset(&right, 0, sizeof(state));
 }
 
+void AudioResamplerCubic::reset(){
+   mInputIndex = 0;
+   mPhaseFraction = 0;
+   mBuffer.frameCount = 0;
+   memset(&left, 0, sizeof(state));
+   memset(&right, 0, sizeof(state));
+}
+
 void AudioResamplerCubic::resample(int32_t* out, size_t outFrameCount,
         AudioBufferProvider* provider) {
 
diff --git a/services/audioflinger/AudioResamplerCubic.h b/services/audioflinger/AudioResamplerCubic.h
index 203b933..5ec38ee 100644
--- a/services/audioflinger/AudioResamplerCubic.h
+++ b/services/audioflinger/AudioResamplerCubic.h
@@ -43,6 +43,7 @@
         int32_t a, b, c, y0, y1, y2, y3;
     } state;
     void init();
+    void reset ();
     void resampleMono16(int32_t* out, size_t outFrameCount,
             AudioBufferProvider* provider);
     void resampleStereo16(int32_t* out, size_t outFrameCount,
diff --git a/services/audioflinger/AudioResamplerSinc.cpp b/services/audioflinger/AudioResamplerSinc.cpp
index 207f26b..60cfef7 100644
--- a/services/audioflinger/AudioResamplerSinc.cpp
+++ b/services/audioflinger/AudioResamplerSinc.cpp
@@ -497,6 +497,15 @@
     mRingFull = mImpulse + (numCoefs+1)*mChannelCount;
 }
 
+void AudioResamplerSinc::reset(){
+    mInputIndex = 0;
+    mPhaseFraction = 0;
+    mBuffer.frameCount = 0;
+    const Constants& c(*mConstants);
+    const size_t stateSize = (2*c.halfNumCoefs) * mChannelCount * 2;
+    memset(mState, 0, sizeof(int16_t)*stateSize);
+}
+
 void AudioResamplerSinc::setVolume(int16_t left, int16_t right) {
     AudioResampler::setVolume(left, right);
     mVolumeSIMD[0] = int32_t(left)<<16;
diff --git a/services/audioflinger/AudioResamplerSinc.h b/services/audioflinger/AudioResamplerSinc.h
index 1ea4474..636586f 100644
--- a/services/audioflinger/AudioResamplerSinc.h
+++ b/services/audioflinger/AudioResamplerSinc.h
@@ -44,6 +44,8 @@
 private:
     void init();
 
+    void reset();
+
     virtual void setVolume(int16_t left, int16_t right);
 
     template<int CHANNELS>
diff --git a/services/audioflinger/Effects.cpp b/services/audioflinger/Effects.cpp
index a8a5169..a8f0511 100644
--- a/services/audioflinger/Effects.cpp
+++ b/services/audioflinger/Effects.cpp
@@ -1,5 +1,6 @@
 /*
-**
+** Copyright (c) 2013, The Linux Foundation. All rights reserved.
+** Not a Contribution.
 ** Copyright 2012, The Android Open Source Project
 **
 ** Licensed under the Apache License, Version 2.0 (the "License");
@@ -29,6 +30,11 @@
 #include "AudioFlinger.h"
 #include "ServiceUtilities.h"
 
+#ifdef SRS_PROCESSING
+#include "srs_processing.h"
+#include "postpro_patch_ics.h"
+#endif
+
 // ----------------------------------------------------------------------------
 
 // Note: the following macro is used for extremely verbose logging message.  In
@@ -66,7 +72,11 @@
       mStatus(NO_INIT), mState(IDLE),
       // mMaxDisableWaitCnt is set by configure() and not used before then
       // mDisableWaitCnt is set by process() and updateState() and not used before then
+#ifdef QCOM_HARDWARE
+      mSuspended(false), mIsForLPA(false)
+#else
       mSuspended(false)
+#endif
 {
     ALOGV("Constructor %p", this);
     int lStatus;
@@ -301,12 +311,20 @@
     (*mEffectInterface)->command(mEffectInterface, EFFECT_CMD_RESET, 0, NULL, 0, NULL);
 }
 
+#ifdef QCOM_HARDWARE
+status_t AudioFlinger::EffectModule::configure(bool isForLPA, int sampleRate, int channelCount, int frameCount)
+#else
 status_t AudioFlinger::EffectModule::configure()
+#endif
 {
     status_t status;
+    status_t cmdStatus = 0;
     sp<ThreadBase> thread;
     uint32_t size;
     audio_channel_mask_t channelMask;
+#ifdef QCOM_HARDWARE
+    uint32_t channels;
+#endif
 
     if (mEffectInterface == NULL) {
         status = NO_INIT;
@@ -321,6 +339,26 @@
 
     // TODO: handle configuration of effects replacing track process
     channelMask = thread->channelMask();
+#ifdef QCOM_HARDWARE
+    if(popcount(channelMask) > 2) {
+        ALOGE("Error: Trying to apply effect on  %d channel content",popcount(channelMask));
+        return INVALID_OPERATION;
+    }
+    mIsForLPA = isForLPA;
+    if(isForLPA) {
+        if (channelCount == 1) {
+            channels = AUDIO_CHANNEL_OUT_MONO;
+        } else {
+            channels = AUDIO_CHANNEL_OUT_STEREO;
+        }
+    } else {
+        if (thread->channelCount() == 1) {
+            channels = AUDIO_CHANNEL_OUT_MONO;
+        } else {
+            channels = AUDIO_CHANNEL_OUT_STEREO;
+        }
+    }
+#endif
 
     if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
         mConfig.inputCfg.channels = AUDIO_CHANNEL_OUT_MONO;
@@ -330,7 +368,15 @@
     mConfig.outputCfg.channels = channelMask;
     mConfig.inputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
     mConfig.outputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
-    mConfig.inputCfg.samplingRate = thread->sampleRate();
+#ifdef QCOM_HARDWARE
+    if(isForLPA){
+        mConfig.inputCfg.samplingRate = sampleRate;
+    } else {
+#endif
+        mConfig.inputCfg.samplingRate = thread->sampleRate();
+#ifdef QCOM_HARDWARE
+    }
+#endif
     mConfig.outputCfg.samplingRate = mConfig.inputCfg.samplingRate;
     mConfig.inputCfg.bufferProvider.cookie = NULL;
     mConfig.inputCfg.bufferProvider.getBuffer = NULL;
@@ -355,13 +401,20 @@
     }
     mConfig.inputCfg.mask = EFFECT_CONFIG_ALL;
     mConfig.outputCfg.mask = EFFECT_CONFIG_ALL;
-    mConfig.inputCfg.buffer.frameCount = thread->frameCount();
+#ifdef QCOM_HARDWARE
+    if(isForLPA) {
+        mConfig.inputCfg.buffer.frameCount = frameCount;
+    } else {
+#endif
+        mConfig.inputCfg.buffer.frameCount = thread->frameCount();
+#ifdef QCOM_HARDWARE
+    }
+#endif
     mConfig.outputCfg.buffer.frameCount = mConfig.inputCfg.buffer.frameCount;
 
     ALOGV("configure() %p thread %p buffer %p framecount %d",
             this, thread.get(), mConfig.inputCfg.buffer.raw, mConfig.inputCfg.buffer.frameCount);
 
-    status_t cmdStatus;
     size = sizeof(int);
     status = (*mEffectInterface)->command(mEffectInterface,
                                                    EFFECT_CMD_SET_CONFIG,
@@ -412,7 +465,7 @@
     if (mEffectInterface == NULL) {
         return NO_INIT;
     }
-    status_t cmdStatus;
+    status_t cmdStatus = 0;
     uint32_t size = sizeof(status_t);
     status_t status = (*mEffectInterface)->command(mEffectInterface,
                                                    EFFECT_CMD_INIT,
@@ -440,7 +493,7 @@
     if (mStatus != NO_ERROR) {
         return mStatus;
     }
-    status_t cmdStatus;
+    status_t cmdStatus = 0;
     uint32_t size = sizeof(status_t);
     status_t status = (*mEffectInterface)->command(mEffectInterface,
                                                    EFFECT_CMD_ENABLE,
@@ -553,10 +606,15 @@
 // must be called with EffectModule::mLock held
 status_t AudioFlinger::EffectModule::setEnabled_l(bool enabled)
 {
-
+#ifdef QCOM_HARDWARE
+    bool effectStateChanged = false;
+#endif
     ALOGV("setEnabled %p enabled %d", this, enabled);
 
     if (enabled != isEnabled()) {
+#ifdef QCOM_HARDWARE
+        effectStateChanged = true;
+#endif
         status_t status = AudioSystem::setEffectEnabled(mId, enabled);
         if (enabled && status != NO_ERROR) {
             return status;
@@ -594,6 +652,19 @@
             }
         }
     }
+#ifdef QCOM_HARDWARE
+    /*
+       Send notification event to LPA Player when an effect for
+       LPA output is enabled or disabled.
+    */
+    sp<EffectChain> chain = mChain.promote();
+    if (effectStateChanged && chain->isForLPATrack()) {
+        sp<ThreadBase> thread = mThread.promote();
+        unlock();//Acquire locks in certain sequence to avoid deadlock
+        thread->effectConfigChanged();
+        lock();
+    }
+#endif
     return NO_ERROR;
 }
 
@@ -645,7 +716,7 @@
     if (isProcessEnabled() &&
             ((mDescriptor.flags & EFFECT_FLAG_VOLUME_MASK) == EFFECT_FLAG_VOLUME_CTRL ||
             (mDescriptor.flags & EFFECT_FLAG_VOLUME_MASK) == EFFECT_FLAG_VOLUME_IND)) {
-        status_t cmdStatus;
+        status_t cmdStatus = 0;
         uint32_t volume[2];
         uint32_t *pVolume = NULL;
         uint32_t size = sizeof(volume);
@@ -680,7 +751,7 @@
     }
     status_t status = NO_ERROR;
     if ((mDescriptor.flags & EFFECT_FLAG_DEVICE_MASK) == EFFECT_FLAG_DEVICE_IND) {
-        status_t cmdStatus;
+        status_t cmdStatus = 0;
         uint32_t size = sizeof(status_t);
         uint32_t cmd = audio_is_output_devices(device) ? EFFECT_CMD_SET_DEVICE :
                             EFFECT_CMD_SET_INPUT_DEVICE;
@@ -702,7 +773,7 @@
     }
     status_t status = NO_ERROR;
     if ((mDescriptor.flags & EFFECT_FLAG_AUDIO_MODE_MASK) == EFFECT_FLAG_AUDIO_MODE_IND) {
-        status_t cmdStatus;
+        status_t cmdStatus = 0;
         uint32_t size = sizeof(status_t);
         status = (*mEffectInterface)->command(mEffectInterface,
                                               EFFECT_CMD_SET_AUDIO_MODE,
@@ -1137,6 +1208,17 @@
         return disable();
     }
 
+#ifdef QCOM_HARDWARE
+    if(mEffect->isOnLPA() &&
+       ((cmdCode == EFFECT_CMD_SET_PARAM) || (cmdCode == EFFECT_CMD_SET_PARAM_DEFERRED) ||
+        (cmdCode == EFFECT_CMD_SET_PARAM_COMMIT) || (cmdCode == EFFECT_CMD_SET_DEVICE) ||
+        (cmdCode == EFFECT_CMD_SET_VOLUME) || (cmdCode == EFFECT_CMD_SET_AUDIO_MODE)) ) {
+        // Notify Direct track for the change in Effect module
+        // TODO: check if it is required to send mLPAHandle
+        ALOGV("Notifying Direct Track for the change in effect config %d", cmdCode);
+        mClient->audioFlinger()->audioConfigChanged_l(AudioSystem::EFFECT_CONFIG_CHANGED, 0, NULL);
+    }
+#endif
     return mEffect->command(cmdCode, cmdSize, pCmdData, replySize, pReplyData);
 }
 
@@ -1204,7 +1286,11 @@
                                         int sessionId)
     : mThread(thread), mSessionId(sessionId), mActiveTrackCnt(0), mTrackCnt(0), mTailBufferCount(0),
       mOwnInBuffer(false), mVolumeCtrlIdx(-1), mLeftVolume(UINT_MAX), mRightVolume(UINT_MAX),
+#ifdef QCOM_HARDWARE
+      mNewLeftVolume(UINT_MAX), mNewRightVolume(UINT_MAX), mIsForLPATrack(false)
+#else
       mNewLeftVolume(UINT_MAX), mNewRightVolume(UINT_MAX)
+#endif
 {
     mStrategy = AudioSystem::getStrategyForStream(AUDIO_STREAM_MUSIC);
     if (thread == NULL) {
@@ -1250,6 +1336,20 @@
     return 0;
 }
 
+#ifdef QCOM_HARDWARE
+sp<AudioFlinger::EffectModule> AudioFlinger::EffectChain::getEffectFromIndex_l(int idx)
+{
+    sp<EffectModule> effect = NULL;
+    if(idx < 0 || idx >= mEffects.size()) {
+        ALOGE("EffectChain::getEffectFromIndex_l: invalid index %d", idx);
+    }
+    if(mEffects.size() > 0){
+        effect = mEffects[idx];
+    }
+    return effect;
+}
+#endif
+
 // getEffectFromType_l() must be called with ThreadBase::mLock held
 sp<AudioFlinger::EffectModule> AudioFlinger::EffectChain::getEffectFromType_l(
         const effect_uuid_t *type)
@@ -1315,7 +1415,11 @@
     }
 
     size_t size = mEffects.size();
+#ifdef QCOM_HARDWARE
+    if (doProcess || isForLPATrack()) {
+#else
     if (doProcess) {
+#endif
         for (size_t i = 0; i < size; i++) {
             mEffects[i]->process();
         }
@@ -1780,6 +1884,7 @@
     }
 }
 
+
 bool AudioFlinger::EffectChain::isNonOffloadableEnabled()
 {
     Mutex::Autolock _l(mLock);
@@ -1792,4 +1897,181 @@
     return false;
 }
 
+#ifdef QCOM_HARDWARE
+#define DEAFULT_FRAME_COUNT 1200
+bool AudioFlinger::applyEffectsOn(void *token, int16_t *inBuffer,
+                            int16_t *outBuffer, int size, bool force)
+{
+    ALOGV("applyEffectsOn: inBuf %p outBuf %p size %d token %p", inBuffer, outBuffer, size, token);
+    // This might be the first buffer to apply effects after effect config change
+    // should not skip effects processing
+    mIsEffectConfigChanged = false;
+
+    volatile size_t numEffects = 0;
+#ifdef SRS_PROCESSING
+    POSTPRO_PATCH_ICS_OUTPROC_DIRECT_SAMPLES(token, AUDIO_FORMAT_PCM_16_BIT, outBuffer, size, mLPASampleRate, mLPANumChannels);
+#endif
+
+    if(mLPAEffectChain != NULL) {
+        numEffects = mLPAEffectChain->getNumEffects();
+    }
+
+    if( numEffects > 0) {
+        size_t  i     = 0;
+        int16_t *pIn  = inBuffer;
+        int16_t *pOut = outBuffer;
+
+        int frameCount = size / (sizeof(int16_t) * mLPANumChannels);
+
+        while(frameCount > 0) {
+            if(mLPAEffectChain == NULL) {
+                ALOGV("LPA Effect Chain is removed - No effects processing !!");
+                numEffects = 0;
+                break;
+            }
+            mLPAEffectChain->lock();
+
+            numEffects = mLPAEffectChain->getNumEffects();
+            if(!numEffects) {
+                ALOGV("applyEffectsOn: All the effects are removed - nothing to process");
+                mLPAEffectChain->unlock();
+                break;
+            }
+
+            int outFrameCount = (frameCount > DEAFULT_FRAME_COUNT ? DEAFULT_FRAME_COUNT: frameCount);
+            bool isEffectEnabled = false;
+            for(i = 0; i < numEffects; i++) {
+                // If effect configuration is changed while applying effects do not process further
+                if(mIsEffectConfigChanged && !force) {
+                    mLPAEffectChain->unlock();
+                    ALOGV("applyEffectsOn: mIsEffectConfigChanged is set - no further processing %d",frameCount);
+                    return false;
+                }
+                sp<EffectModule> effect = mLPAEffectChain->getEffectFromIndex_l(i);
+                if(effect == NULL) {
+                    ALOGE("getEffectFromIndex_l(%d) returned NULL ptr", i);
+                    mLPAEffectChain->unlock();
+                    return false;
+                }
+                if(i == 0) {
+                    // For the first set input and output buffers different
+                    isEffectEnabled = effect->isProcessEnabled();
+                    effect->setInBuffer(pIn);
+                    effect->setOutBuffer(pOut);
+                } else {
+                    // For the remaining use previous effect's output buffer as input buffer
+                    effect->setInBuffer(pOut);
+                    effect->setOutBuffer(pOut);
+                }
+                // true indicates that it is being applied on LPA output
+                effect->configure(true, mLPASampleRate, mLPANumChannels, outFrameCount);
+            }
+
+            if(isEffectEnabled) {
+                // Clear the output buffer
+                memset(pOut, 0, (outFrameCount * mLPANumChannels * sizeof(int16_t)));
+            } else {
+                // Copy input buffer content to the output buffer
+                memcpy(pOut, pIn, (outFrameCount * mLPANumChannels * sizeof(int16_t)));
+            }
+
+            mLPAEffectChain->process_l();
+
+            mLPAEffectChain->unlock();
+
+            // Update input and output buffer pointers
+            pIn        += (outFrameCount * mLPANumChannels);
+            pOut       += (outFrameCount * mLPANumChannels);
+            frameCount -= outFrameCount;
+        }
+    }
+
+    if (!numEffects && !force) {
+        ALOGV("applyEffectsOn: There are no effects to be applied");
+        if(inBuffer != outBuffer) {
+            // No effect applied so just copy input buffer to output buffer
+            memcpy(outBuffer, inBuffer, size);
+        }
+    }
+    return true;
+}
+
+void *AudioFlinger::DirectAudioTrack::EffectsThreadWrapper(void *me) {
+    static_cast<DirectAudioTrack *>(me)->EffectsThreadEntry();
+    return NULL;
+}
+
+void AudioFlinger::DirectAudioTrack::EffectsThreadEntry() {
+    while(1) {
+        mEffectLock.lock();
+        if (!mEffectConfigChanged && !mKillEffectsThread) {
+            mEffectCv.wait(mEffectLock);
+        }
+        if(mKillEffectsThread) {
+            mEffectLock.unlock();
+            break;
+        }
+        if (mEffectConfigChanged) {
+            mEffectConfigChanged = false;
+            if (mFlag & AUDIO_OUTPUT_FLAG_LPA) {
+                for ( List<BufferInfo>::iterator it = mEffectsPool.begin();
+                      it != mEffectsPool.end(); it++) {
+                    ALOGV("ete: calling applyEffectsOn buff %x",it->localBuf);
+                    bool isEffectsApplied = mAudioFlinger->applyEffectsOn(
+                                    static_cast<void *>(this),
+                                    (int16_t *)it->localBuf,
+                                    (int16_t *)mEffectsThreadScratchBuffer,
+                                    it->bytesToWrite,
+                                    false);
+                    if (isEffectsApplied == true){
+                        ALOGV("ete:dsp updated for local buf %x",it->localBuf);
+                        memcpy(it->dspBuf, mEffectsThreadScratchBuffer, it->bytesToWrite);
+                    }
+                    else
+                        ALOGV("ete:dsp updated for local buf %x SKIPPED",it->localBuf);
+
+                    if (mEffectConfigChanged) {
+                        ALOGE("ete:effects changed, abort effects application");
+                        break;
+                    }
+            }
+#ifdef SRS_PROCESSING
+            } else if (mFlag & AUDIO_OUTPUT_FLAG_TUNNEL) {
+                ALOGV("applying effects for TUNNEL");
+                char buffer[2];
+                    //dummy buffer to ensure the SRS processing takes place
+                    // The API mandates Sample rate and channel mode. Hence
+                    // defaulted the sample rate channel mode to 48000 and 2 respectively
+                POSTPRO_PATCH_ICS_OUTPROC_DIRECT_SAMPLES(static_cast<void *>(this),
+                                                         AUDIO_FORMAT_PCM_16_BIT,
+                                                        (int16_t*)buffer, 2, 48000, 2);
+#endif
+            }
+        }
+        mEffectLock.unlock();
+    }
+    ALOGV("Effects thread is dead");
+    mEffectsThreadAlive = false;
+}
+
+void AudioFlinger::DirectAudioTrack::requestAndWaitForEffectsThreadExit() {
+    if (!mEffectsThreadAlive)
+        return;
+    mKillEffectsThread = true;
+    mEffectCv.signal();
+    pthread_join(mEffectsThread,NULL);
+    ALOGV("effects thread killed");
+}
+
+void AudioFlinger::DirectAudioTrack::createEffectThread() {
+    //Create the effects thread
+    pthread_attr_t attr;
+    pthread_attr_init(&attr);
+    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
+    mEffectsThreadAlive = true;
+    ALOGV("Creating Effects Thread");
+    pthread_create(&mEffectsThread, &attr, EffectsThreadWrapper, this);
+}
+#endif
+
 }; // namespace android
diff --git a/services/audioflinger/Effects.h b/services/audioflinger/Effects.h
index b717857..5ad312b 100644
--- a/services/audioflinger/Effects.h
+++ b/services/audioflinger/Effects.h
@@ -1,5 +1,6 @@
 /*
-**
+** Copyright (c) 2013, The Linux Foundation. All rights reserved.
+** Not a Contribution.
 ** Copyright 2012, The Android Open Source Project
 **
 ** Licensed under the Apache License, Version 2.0 (the "License");
@@ -68,7 +69,14 @@
                      void *pReplyData);
 
     void reset_l();
+#ifdef QCOM_HARDWARE
+    status_t configure(bool isForLPA = false,
+                       int sampleRate = 0,
+                       int channelCount = 0,
+                       int frameCount = 0);
+#else
     status_t configure();
+#endif
     status_t init();
     effect_state state() const {
         return mState;
@@ -119,6 +127,10 @@
                         { return (mDescriptor.flags & EFFECT_FLAG_OFFLOAD_SUPPORTED) != 0; }
     status_t         setOffloaded(bool offloaded, audio_io_handle_t io);
     bool             isOffloaded() const;
+#ifdef QCOM_HARDWARE
+    bool             isOnLPA() { return mIsForLPA;}
+    void             setLPAFlag(bool isForLPA) {mIsForLPA = isForLPA; }
+#endif
 
     void             dump(int fd, const Vector<String16>& args);
 
@@ -153,6 +165,9 @@
     uint32_t mDisableWaitCnt;       // current process() calls count during disable period.
     bool     mSuspended;            // effect is suspended: temporarily disabled by framework
     bool     mOffloaded;            // effect is currently offloaded to the audio DSP
+#ifdef QCOM_HARDWARE
+    bool     mIsForLPA;
+#endif
 };
 
 // The EffectHandle class implements the IEffect interface. It provides resources
@@ -262,12 +277,18 @@
 
     status_t addEffect_l(const sp<EffectModule>& handle);
     size_t removeEffect_l(const sp<EffectModule>& handle);
+#ifdef QCOM_HARDWARE
+    size_t getNumEffects() { return mEffects.size(); }
+#endif
 
     int sessionId() const { return mSessionId; }
     void setSessionId(int sessionId) { mSessionId = sessionId; }
 
     sp<EffectModule> getEffectFromDesc_l(effect_descriptor_t *descriptor);
     sp<EffectModule> getEffectFromId_l(int id);
+#ifdef QCOM_HARDWARE
+    sp<EffectModule> getEffectFromIndex_l(int idx);
+#endif
     sp<EffectModule> getEffectFromType_l(const effect_uuid_t *type);
     bool setVolume_l(uint32_t *left, uint32_t *right);
     void setDevice_l(audio_devices_t device);
@@ -317,6 +338,10 @@
 
 
     void dump(int fd, const Vector<String16>& args);
+#ifdef QCOM_HARDWARE
+    bool isForLPATrack() {return mIsForLPATrack; }
+    void setLPAFlag(bool flag) {mIsForLPATrack = flag;}
+#endif
 
 protected:
     friend class AudioFlinger;  // for mThread, mEffects
@@ -365,6 +390,9 @@
     uint32_t mNewLeftVolume;       // new volume on left channel
     uint32_t mNewRightVolume;      // new volume on right channel
     uint32_t mStrategy; // strategy for this effect chain
+#ifdef QCOM_HARDWARE
+    bool     mIsForLPATrack;
+#endif
     // mSuspendedEffects lists all effects currently suspended in the chain.
     // Use effect type UUID timelow field as key. There is no real risk of identical
     // timeLow fields among effect type UUIDs.
diff --git a/services/audioflinger/RecordTracks.h b/services/audioflinger/RecordTracks.h
index 57de568..8e20d5a 100644
--- a/services/audioflinger/RecordTracks.h
+++ b/services/audioflinger/RecordTracks.h
@@ -28,6 +28,9 @@
                                 audio_format_t format,
                                 audio_channel_mask_t channelMask,
                                 size_t frameCount,
+#ifdef QCOM_HARDWARE
+                                uint32_t flags,
+#endif
                                 int sessionId,
                                 int uid);
     virtual             ~RecordTrack();
@@ -58,6 +61,9 @@
                                    int64_t pts = kInvalidPTS);
     // releaseBuffer() not overridden
 
+#ifdef QCOM_HARDWARE
+    track_flags_t       mFlags;
+#endif
     bool                mOverflow;  // overflow on most recent attempt to fill client buffer
     AudioRecordServerProxy* mAudioRecordServerProxy;
 };
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 3d657b3..045cc29 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -1,5 +1,6 @@
 /*
-**
+** Copyright (c) 2013, The Linux Foundation. All rights reserved.
+** Not a Contribution.
 ** Copyright 2012, The Android Open Source Project
 **
 ** Licensed under the Apache License, Version 2.0 (the "License");
@@ -64,6 +65,11 @@
 #include <cpustats/ThreadCpuUsage.h>
 #endif
 
+#ifdef SRS_PROCESSING
+#include "srs_processing.h"
+#include "postpro_patch_ics.h"
+#endif
+
 // ----------------------------------------------------------------------------
 
 // Note: the following macro is used for extremely verbose logging message.  In
@@ -79,6 +85,11 @@
 #define ALOGVV(a...) do { } while(0)
 #endif
 
+#ifdef QCOM_HARDWARE
+#define DIRECT_TRACK_EOS 1
+#define DIRECT_TRACK_HW_FAIL 6
+static const char lockName[] = "DirectTrack";
+#endif
 namespace android {
 
 // retry counts for buffer fill timeout
@@ -341,6 +352,13 @@
     return status;
 }
 
+#ifdef QCOM_HARDWARE
+void AudioFlinger::ThreadBase::effectConfigChanged() {
+    ALOGV("New effect is being added to LPA chain, Notifying LPA Direct Track");
+    mAudioFlinger->audioConfigChanged_l(AudioSystem::EFFECT_CONFIG_CHANGED, 0, NULL);
+}
+#endif
+
 void AudioFlinger::ThreadBase::sendIoConfigEvent(int event, int param)
 {
     Mutex::Autolock _l(mLock);
@@ -794,6 +812,21 @@
             addEffectChain_l(chain);
             chain->setStrategy(getStrategyForSession_l(sessionId));
             chainCreated = true;
+#ifdef QCOM_HARDWARE
+            if(sessionId == mAudioFlinger->mLPASessionId) {
+                // Clear reference to previous effect chain if any
+                if(mAudioFlinger->mLPAEffectChain.get()) {
+                    mAudioFlinger->mLPAEffectChain.clear();
+                }
+                ALOGV("New EffectChain is created for LPA session ID %d", sessionId);
+                mAudioFlinger->mLPAEffectChain = chain;
+                chain->setLPAFlag(true);
+                // For LPA, the volume will be applied in DSP. No need for volume
+                // control in the Effect chain, so setting it to unity.
+                uint32_t volume = 0x1000000; // Equals to 1.0 in 8.24 format
+                chain->setVolume_l(&volume,&volume);
+            }
+#endif
         } else {
             effect = chain->getEffectFromDesc_l(desc);
         }
@@ -822,7 +855,11 @@
             }
             effectCreated = true;
 
+#ifdef QCOM_HARDWARE
+            effect->setDevice(mAudioFlinger->mLPASessionId == sessionId ? mAudioFlinger->mDirectDevice:mOutDevice);
+#else
             effect->setDevice(mOutDevice);
+#endif
             effect->setDevice(mInDevice);
             effect->setMode(mAudioFlinger->getMode());
             effect->setAudioSource(mAudioSource);
@@ -937,8 +974,20 @@
         Vector< sp<AudioFlinger::EffectChain> >& effectChains)
 {
     effectChains = mEffectChains;
+#ifdef QCOM_HARDWARE
+    mAudioFlinger->mAllChainsLocked = true;
+#endif
     for (size_t i = 0; i < mEffectChains.size(); i++) {
-        mEffectChains[i]->lock();
+#ifdef QCOM_HARDWARE
+        if (mEffectChains[i] != mAudioFlinger->mLPAEffectChain) {
+#else
+            mEffectChains[i]->lock();
+#endif
+#ifdef QCOM_HARDWARE
+        } else {
+            mAudioFlinger-> mAllChainsLocked = false;
+        }
+#endif
     }
 }
 
@@ -946,7 +995,10 @@
         const Vector< sp<AudioFlinger::EffectChain> >& effectChains)
 {
     for (size_t i = 0; i < effectChains.size(); i++) {
-        effectChains[i]->unlock();
+#ifdef QCOM_HARDWARE
+        if (mAudioFlinger->mAllChainsLocked || effectChains[i] != mAudioFlinger->mLPAEffectChain)
+#endif
+            effectChains[i]->unlock();
     }
 }
 
@@ -1248,7 +1300,10 @@
         // This is probably too conservative, but legacy application code may depend on it.
         // If you change this calculation, also review the start threshold which is related.
         uint32_t latencyMs = mOutput->stream->get_latency(mOutput->stream);
-        uint32_t minBufCount = latencyMs / ((1000 * mNormalFrameCount) / mSampleRate);
+        uint32_t minBufCount = 0;
+        if (mSampleRate) {
+            minBufCount = latencyMs / ((1000 * mNormalFrameCount) / mSampleRate);
+        }
         if (minBufCount < 2) {
             minBufCount = 2;
         }
@@ -1260,7 +1315,17 @@
     }
 
     if (mType == DIRECT) {
+#ifdef QCOM_HARDWARE
+        if (((format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM)
+               ||((format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AMR_NB)
+               ||((format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AMR_WB)
+               ||((format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_EVRC)
+               ||((format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_EVRCB)
+               ||((format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_EVRCWB)
+               ||((format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_EVRCNW)) {
+#else
         if ((format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM) {
+#endif
             if (sampleRate != mSampleRate || format != mFormat || channelMask != mChannelMask) {
                 ALOGE("createTrack_l() Bad parameter: sampleRate %u format %d, channelMask 0x%08x "
                         "for output %p with format %d",
@@ -2153,6 +2218,13 @@
 
     standbyTime = systemTime();
 
+#ifdef SRS_PROCESSING
+if (mType == MIXER) {
+        POSTPRO_PATCH_ICS_OUTPROC_MIX_INIT(this, gettid());
+    } else if (mType == DUPLICATING) {
+        POSTPRO_PATCH_ICS_OUTPROC_DUPE_INIT(this, gettid());
+    }
+#endif
     // MIXER
     nsecs_t lastWarning = 0;
 
@@ -2314,8 +2386,14 @@
             // only process effects if we're going to write
             if (sleepTime == 0 && mType != OFFLOAD) {
                 for (size_t i = 0; i < effectChains.size(); i ++) {
-                    effectChains[i]->process_l();
-                }
+#ifdef QCOM_HARDWARE
+                    if (effectChains[i] != mAudioFlinger->mLPAEffectChain) {
+#endif
+                        effectChains[i]->process_l();
+#ifdef QCOM_HARDWARE
+                  }
+#endif
+               }
             }
         }
         // Process effect chains for offloaded thread even if no audio
@@ -2334,6 +2412,15 @@
         if (!waitingAsyncCallback()) {
             // sleepTime == 0 means we must write to audio hardware
             if (sleepTime == 0) {
+#ifdef SRS_PROCESSING
+                if (mType == MIXER) {
+                    POSTPRO_PATCH_ICS_OUTPROC_MIX_SAMPLES(this, mFormat, mMixBuffer,
+                        mixBufferSize, mSampleRate, mChannelCount);
+                } else if (mType == DUPLICATING) {
+                    POSTPRO_PATCH_ICS_OUTPROC_DUPE_SAMPLES(this, mFormat, mMixBuffer,
+                        mixBufferSize, mSampleRate, mChannelCount);
+                }
+#endif
                 if (mBytesRemaining) {
                     ssize_t ret = threadLoop_write();
                     if (ret < 0) {
@@ -2395,6 +2482,13 @@
         }
     }
 
+#ifdef SRS_PROCESSING
+        if (mType == MIXER) {
+            POSTPRO_PATCH_ICS_OUTPROC_MIX_EXIT(this, gettid());
+        } else if (mType == DUPLICATING) {
+            POSTPRO_PATCH_ICS_OUTPROC_DUPE_EXIT(this, gettid());
+        }
+#endif
     releaseWakeLock();
     mWakeLockUids.clear();
     mActiveTracksGeneration++;
@@ -2636,7 +2730,10 @@
 {
     if (mFastMixer != NULL) {
         MonoPipe *pipe = (MonoPipe *)mPipeSink.get();
-        latency += (pipe->getAvgFrames() * 1000) / mSampleRate;
+        if(mSampleRate)
+            latency += (pipe->getAvgFrames() * 1000) / mSampleRate;
+        else
+            ALOGW("SampleRate is 0");
     }
     return latency;
 }
@@ -2754,11 +2851,13 @@
     int64_t pts;
     status_t status = INVALID_OPERATION;
 
+#ifndef ICS_AUDIO_BLOB
     if (mNormalSink != 0) {
         status = mNormalSink->getNextWriteTimestamp(&pts);
     } else {
         status = mOutputSink->getNextWriteTimestamp(&pts);
     }
+#endif
 
     if (status != NO_ERROR) {
         pts = AudioBufferProvider::kInvalidPTS;
@@ -3024,7 +3123,12 @@
             desiredFrames = mNormalFrameCount;
         } else {
             // +1 for rounding and +1 for additional sample needed for interpolation
-            desiredFrames = (mNormalFrameCount * sr) / mSampleRate + 1 + 1;
+            if (mSampleRate) {
+                desiredFrames = (mNormalFrameCount * sr) / mSampleRate + 1 + 1;
+            } else {
+                desiredFrames = 2;
+                ALOGW("SampleRate is 0");
+            }
             // add frames already consumed but not yet released by the resampler
             // because cblk->framesReady() will include these frames
             desiredFrames += mAudioMixer->getUnreleasedFrames(track->name());
@@ -3350,6 +3454,9 @@
         AudioParameter param = AudioParameter(keyValuePair);
         int value;
 
+#ifdef SRS_PROCESSING
+        POSTPRO_PATCH_ICS_OUTPROC_MIX_ROUTE(this, param, value);
+#endif
         if (param.getInt(String8(AudioParameter::keySamplingRate), value) == NO_ERROR) {
             reconfig = true;
         }
@@ -3655,7 +3762,8 @@
                 size_t audioHALFrames = (latency_l() * mSampleRate) / 1000;
                 size_t framesWritten = mBytesWritten / mFrameSize;
                 if (mStandby || !last ||
-                        track->presentationComplete(framesWritten, audioHALFrames)) {
+                        track->presentationComplete(framesWritten, audioHALFrames) ||
+                        track->isTerminated()) {
                     if (track->isStopped()) {
                         track->reset();
                     }
@@ -3936,7 +4044,8 @@
     :   DirectOutputThread(audioFlinger, output, id, device, OFFLOAD),
         mHwPaused(false),
         mFlushPending(false),
-        mPausedBytesRemaining(0)
+        mPausedBytesRemaining(0),
+        mPreviousTrack(NULL)
 {
     //FIXME: mStandby should be set to true by ThreadBase constructor
     mStandby = true;
@@ -4282,7 +4391,10 @@
 {
     Mutex::Autolock _l(mLock);
     // FIXME explain this formula
-    size_t frameCount = (3 * mNormalFrameCount * mSampleRate) / thread->sampleRate();
+    int sampleRate = thread->sampleRate();
+    size_t frameCount = 0;
+    if (sampleRate)
+        frameCount = (3 * mNormalFrameCount * mSampleRate) / thread->sampleRate();
     OutputTrack *outputTrack = new OutputTrack(thread,
                                             this,
                                             mSampleRate,
@@ -4380,7 +4492,7 @@
     ThreadBase(audioFlinger, id, outDevice, inDevice, RECORD),
     mInput(input), mResampler(NULL), mRsmpOutBuffer(NULL), mRsmpInBuffer(NULL),
     // mRsmpInIndex and mBufferSize set by readInputParameters()
-    mReqChannelCount(popcount(channelMask)),
+    mReqChannelCount(getInputChannelCount(channelMask)),
     mReqSampleRate(sampleRate)
     // mBytesRead is only meaningful while active, and so is cleared in start()
     // (but might be better to also clear here for dump?)
@@ -4529,8 +4641,29 @@
                                 }
                             }
                         }
-                        if (framesOut && mFrameCount == mRsmpInIndex) {
+                        if (framesOut && (mFrameCount == mRsmpInIndex)) {
                             void *readInto;
+#ifdef QCOM_HARDWARE
+                            int InputBytes;
+                            /*Fix me: How does framesOut become 0 in this condition */
+                            if (( framesOut != mFrameCount) &&
+                                ((mFormat != AUDIO_FORMAT_PCM_16_BIT)&&
+                                (!(mActiveTrack->mFlags & TRACK_VOICE_COMMUNICATION)))) {
+                                     readInto = buffer.raw;
+                                     InputBytes = buffer.frameCount * mFrameSize;
+                             } else if (framesOut == mFrameCount &&
+                                       (mChannelCount == mReqChannelCount ||
+                                       ((mFormat != AUDIO_FORMAT_PCM_16_BIT) &&
+                                       (!(mActiveTrack->mFlags & TRACK_VOICE_COMMUNICATION))))) {
+                                     readInto = buffer.raw;
+                                     InputBytes = mBufferSize;
+                                     framesOut = 0;
+                             } else {
+                                     readInto = mRsmpInBuffer;
+                                     mRsmpInIndex = 0;
+                                     InputBytes = mBufferSize;
+                             }
+#else
                             if (framesOut == mFrameCount && mChannelCount == mReqChannelCount) {
                                 readInto = buffer.raw;
                                 framesOut = 0;
@@ -4538,8 +4671,13 @@
                                 readInto = mRsmpInBuffer;
                                 mRsmpInIndex = 0;
                             }
+#endif
                             mBytesRead = mInput->stream->read(mInput->stream, readInto,
+#ifdef QCOM_HARDWARE
+                                    InputBytes);
+#else
                                     mBufferSize);
+#endif
                             if (mBytesRead <= 0) {
                                 if ((mBytesRead < 0) && (mActiveTrack->mState == TrackBase::ACTIVE))
                                 {
@@ -4720,7 +4858,10 @@
         // If you change this calculation, also review the start threshold which is related.
         uint32_t latencyMs = 50; // FIXME mInput->stream->get_latency(mInput->stream);
         size_t mNormalFrameCount = 2048; // FIXME
-        uint32_t minBufCount = latencyMs / ((1000 * mNormalFrameCount) / mSampleRate);
+        uint32_t minBufCount = 0;
+        if (mSampleRate) {
+            minBufCount = latencyMs / ((1000 * mNormalFrameCount) / mSampleRate);
+        }
         if (minBufCount < 2) {
             minBufCount = 2;
         }
@@ -4737,7 +4878,11 @@
         Mutex::Autolock _l(mLock);
 
         track = new RecordTrack(this, client, sampleRate,
+#ifdef QCOM_HARDWARE
+                      format, channelMask, frameCount, *flags, sessionId, uid);
+#else
                       format, channelMask, frameCount, sessionId, uid);
+#endif
 
         if (track->getCblk() == 0) {
             ALOGE("createRecordTrack_l() no control block");
@@ -5078,7 +5223,7 @@
             }
         }
         if (param.getInt(String8(AudioParameter::keyChannels), value) == NO_ERROR) {
-            reqChannelCount = popcount(value);
+            reqChannelCount = getInputChannelCount(value);
             reconfig = true;
         }
         if (param.getInt(String8(AudioParameter::keyFrameCount), value) == NO_ERROR) {
@@ -5142,7 +5287,7 @@
                     reqFormat == AUDIO_FORMAT_PCM_16_BIT &&
                     (mInput->stream->common.get_sample_rate(&mInput->stream->common)
                             <= (2 * reqSamplingRate)) &&
-                    popcount(mInput->stream->common.get_channels(&mInput->stream->common))
+                    getInputChannelCount(mInput->stream->common.get_channels(&mInput->stream->common))
                             <= FCC_2 &&
                     (reqChannelCount <= FCC_2)) {
                     status = NO_ERROR;
@@ -5211,11 +5356,13 @@
 
     mSampleRate = mInput->stream->common.get_sample_rate(&mInput->stream->common);
     mChannelMask = mInput->stream->common.get_channels(&mInput->stream->common);
-    mChannelCount = popcount(mChannelMask);
+    mChannelCount = (uint16_t)getInputChannelCount(mChannelMask);
     mFormat = mInput->stream->common.get_format(&mInput->stream->common);
+#ifndef QCOM_HARDWARE
     if (mFormat != AUDIO_FORMAT_PCM_16_BIT) {
         ALOGE("HAL format %d not supported; must be AUDIO_FORMAT_PCM_16_BIT", mFormat);
     }
+#endif
     mFrameSize = audio_stream_frame_size(&mInput->stream->common);
     mBufferSize = mInput->stream->common.get_buffer_size(&mInput->stream->common);
     mFrameCount = mBufferSize / mFrameSize;
@@ -5335,4 +5482,321 @@
     return 0;
 }
 
+#ifdef QCOM_HARDWARE
+// ----------------------------------------------------------------------------
+
+AudioFlinger::DirectAudioTrack::DirectAudioTrack(const sp<AudioFlinger>& audioFlinger,
+                                                 int output, AudioSessionDescriptor *outputDesc,
+                                                 IDirectTrackClient* client, audio_output_flags_t outflag)
+    : BnDirectTrack(), mIsPaused(false), mAudioFlinger(audioFlinger), mOutput(output), mOutputDesc(outputDesc),
+      mClient(client), mEffectConfigChanged(false), mKillEffectsThread(false), mFlag(outflag),
+      mEffectsThreadScratchBuffer(NULL)
+{
+#ifdef SRS_PROCESSING
+    ALOGD("SRS_Processing - DirectAudioTrack - OutNotify_Init: %p TID %d\n", this, gettid());
+    POSTPRO_PATCH_ICS_OUTPROC_DIRECT_INIT(this, gettid());
+    SRS_Processing::ProcessOutRoute(SRS_Processing::AUTO, this, outputDesc->device);
+#endif
+    if (mFlag & AUDIO_OUTPUT_FLAG_LPA) {
+        ALOGV("create effects thread for LPA");
+        createEffectThread();
+        allocateBufPool();
+#ifdef SRS_PROCESSING
+    } else if (mFlag & AUDIO_OUTPUT_FLAG_TUNNEL) {
+        ALOGV("create effects thread for TUNNEL");
+        createEffectThread();
+#endif
+    }
+    outputDesc->mVolumeScale = 1.0;
+    mDeathRecipient = new PMDeathRecipient(this);
+    acquireWakeLock();
+}
+
+void AudioFlinger::DirectAudioTrack::signalEffect() {
+    if (mFlag & AUDIO_OUTPUT_FLAG_LPA){
+        mEffectConfigChanged = true;
+        mEffectCv.signal();
+    }
+#ifdef SRS_PROCESSING
+    if (mFlag & AUDIO_OUTPUT_FLAG_TUNNEL){
+        mEffectConfigChanged = true;
+        mEffectCv.signal();
+    }
+#endif
+}
+
+AudioFlinger::DirectAudioTrack::~DirectAudioTrack() {
+#ifdef SRS_PROCESSING
+    ALOGD("SRS_Processing - DirectAudioTrack - OutNotify_Init: %p TID %d\n", this, gettid());
+    POSTPRO_PATCH_ICS_OUTPROC_DIRECT_EXIT(this, gettid());
+#endif
+    if (mFlag & AUDIO_OUTPUT_FLAG_LPA) {
+        requestAndWaitForEffectsThreadExit();
+        mAudioFlinger->deleteEffectSession();
+        deallocateBufPool();
+#ifdef SRS_PROCESSING
+    } else if (mFlag & AUDIO_OUTPUT_FLAG_TUNNEL) {
+        requestAndWaitForEffectsThreadExit();
+        mAudioFlinger->deleteEffectSession();
+#endif
+    }
+    AudioSystem::releaseOutput(mOutput);
+    releaseWakeLock();
+
+    {
+        Mutex::Autolock _l(pmLock);
+        if (mPowerManager != 0) {
+            sp<IBinder> binder = mPowerManager->asBinder();
+            binder->unlinkToDeath(mDeathRecipient);
+        }
+    }
+}
+
+status_t AudioFlinger::DirectAudioTrack::start() {
+    AudioSystem::startOutput(mOutput, (audio_stream_type_t)mOutputDesc->mStreamType);
+    if(mIsPaused) {
+        mIsPaused = false;
+        mOutputDesc->stream->start(mOutputDesc->stream);
+    }
+    mOutputDesc->mActive = true;
+    mOutputDesc->stream->set_volume(mOutputDesc->stream,
+                                    mOutputDesc->mVolumeLeft * mOutputDesc->mVolumeScale,
+                                    mOutputDesc->mVolumeRight* mOutputDesc->mVolumeScale);
+    return NO_ERROR;
+}
+
+void AudioFlinger::DirectAudioTrack::stop() {
+    ALOGV("DirectAudioTrack::stop");
+    mOutputDesc->mActive = false;
+    mOutputDesc->stream->stop(mOutputDesc->stream);
+    AudioSystem::stopOutput(mOutput, (audio_stream_type_t)mOutputDesc->mStreamType);
+}
+
+void AudioFlinger::DirectAudioTrack::pause() {
+    if(!mIsPaused) {
+        mIsPaused = true;
+        mOutputDesc->stream->pause(mOutputDesc->stream);
+        mOutputDesc->mActive = false;
+        AudioSystem::stopOutput(mOutput, (audio_stream_type_t)mOutputDesc->mStreamType);
+    }
+}
+
+ssize_t AudioFlinger::DirectAudioTrack::write(const void *buffer, size_t size) {
+    ALOGV("Writing to AudioSessionOut");
+    int isAvail = 0;
+    mOutputDesc->stream->is_buffer_available(mOutputDesc->stream, &isAvail);
+    if (!isAvail) {
+        return 0;
+    }
+
+    if (mFlag & AUDIO_OUTPUT_FLAG_LPA) {
+        mEffectLock.lock();
+        List<BufferInfo>::iterator it = mEffectsPool.begin();
+        BufferInfo buf = *it;
+        mEffectsPool.erase(it);
+        memcpy((char *) buf.localBuf, (char *)buffer, size);
+        buf.bytesToWrite = size;
+        mEffectsPool.push_back(buf);
+        mAudioFlinger->applyEffectsOn(static_cast<void *>(this),
+            (int16_t*)buf.localBuf, (int16_t*)buffer, (int)size, true);
+        mEffectLock.unlock();
+    }
+    ALOGV("out of Writing to AudioSessionOut");
+    return mOutputDesc->stream->write(mOutputDesc->stream, buffer, size);
+}
+
+void AudioFlinger::DirectAudioTrack::flush() {
+    if (mFlag & AUDIO_OUTPUT_FLAG_LPA) {
+        mEffectLock.lock();
+        mEffectsPool.clear();
+        mEffectsPool = mBufPool;
+        mEffectLock.unlock();
+    }
+    mOutputDesc->stream->flush(mOutputDesc->stream);
+}
+
+void AudioFlinger::DirectAudioTrack::mute(bool muted) {
+}
+
+void AudioFlinger::DirectAudioTrack::setVolume(float left, float right) {
+    ALOGV("DirectAudioTrack::setVolume left: %f, right: %f", left, right);
+    if(mOutputDesc) {
+        mOutputDesc->mVolumeLeft = left;
+        mOutputDesc->mVolumeRight = right;
+        if(mOutputDesc->mActive &&  mOutputDesc->stream) {
+            mOutputDesc->stream->set_volume(mOutputDesc->stream,
+                                    left * mOutputDesc->mVolumeScale,
+                                    right* mOutputDesc->mVolumeScale);
+        } else {
+            ALOGD("stream is not active, so cache and send when stream is active");
+        }
+    } else {
+        ALOGD("output descriptor is not valid to set the volume");
+    }
+}
+
+int64_t AudioFlinger::DirectAudioTrack::getTimeStamp() {
+    int64_t time;
+    mOutputDesc->stream->get_next_write_timestamp(mOutputDesc->stream, &time);
+    ALOGV("Timestamp %lld",time);
+    return time;
+}
+
+void AudioFlinger::DirectAudioTrack::postEOS(int64_t delayUs) {
+    if (delayUs == 0 ) {
+       ALOGV("Notify Audio Track of EOS event");
+       mClient->notify(DIRECT_TRACK_EOS);
+    } else {
+       ALOGV("Notify Audio Track of hardware failure event");
+       mClient->notify(DIRECT_TRACK_HW_FAIL);
+    }
+}
+
+void AudioFlinger::DirectAudioTrack::allocateBufPool() {
+    void *dsp_buf = NULL;
+    void *local_buf = NULL;
+
+    //1. get the ion buffer information
+    struct buf_info* buf = NULL;
+    mOutputDesc->stream->get_buffer_info(mOutputDesc->stream, &buf);
+    ALOGV("get buffer info %p",buf);
+    if (!buf) {
+        ALOGV("buffer is NULL");
+        return;
+    }
+    int nSize = buf->bufsize;
+    int bufferCount = buf->nBufs;
+
+    //2. allocate the buffer pool, allocate local buffers
+    for (int i = 0; i < bufferCount; i++) {
+        dsp_buf = (void *)buf->buffers[i];
+        local_buf = malloc(nSize);
+        memset(local_buf, 0, nSize);
+        // Store this information for internal mapping / maintanence
+        BufferInfo buf(local_buf, dsp_buf, nSize);
+        buf.bytesToWrite = 0;
+        mBufPool.push_back(buf);
+        mEffectsPool.push_back(buf);
+
+        ALOGV("The MEM that is allocated buffer is %x, size %d",(unsigned int)dsp_buf,nSize);
+    }
+
+    mEffectsThreadScratchBuffer = malloc(nSize);
+    ALOGV("effectsThreadScratchBuffer = %x",mEffectsThreadScratchBuffer);
+
+    free(buf);
+}
+
+void AudioFlinger::DirectAudioTrack::deallocateBufPool() {
+
+    //1. Deallocate the local memory
+    //2. Remove all the buffers from bufpool
+    mEffectLock.lock();
+    while (!mBufPool.empty())  {
+        List<BufferInfo>::iterator it = mBufPool.begin();
+        BufferInfo &memBuffer = *it;
+        // free the local buffer corresponding to mem buffer
+        if (memBuffer.localBuf) {
+            free(memBuffer.localBuf);
+            memBuffer.localBuf = NULL;
+        }
+        ALOGV("Removing from bufpool");
+        mBufPool.erase(it);
+    }
+    mEffectsPool.clear();
+    mEffectLock.unlock();
+
+    free(mEffectsThreadScratchBuffer);
+    mEffectsThreadScratchBuffer = NULL;
+}
+
+status_t AudioFlinger::DirectAudioTrack::onTransact(
+    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+    return BnDirectTrack::onTransact(code, data, reply, flags);
+}
+
+AudioFlinger::DirectAudioTrack::AudioFlingerDirectTrackClient::AudioFlingerDirectTrackClient(void *obj)
+{
+    ALOGV("AudioFlinger::DirectAudioTrack::AudioFlingerDirectTrackClient");
+    pBaseClass = (DirectAudioTrack*)obj;
+}
+
+void AudioFlinger::DirectAudioTrack::AudioFlingerDirectTrackClient::binderDied(const wp<IBinder>& who) {
+    pBaseClass->mAudioFlinger.clear();
+    ALOGW("AudioFlinger server died!");
+}
+
+void AudioFlinger::DirectAudioTrack::AudioFlingerDirectTrackClient
+     ::ioConfigChanged(int event, audio_io_handle_t ioHandle, const void *param2) {
+    ALOGV("ioConfigChanged() event %d", event);
+    if (event == AudioSystem::EFFECT_CONFIG_CHANGED) {
+        ALOGV("Received notification for change in effect module");
+        // Seek to current media time - flush the decoded buffers with the driver
+        pBaseClass->mEffectConfigChanged = true;
+        // Signal effects thread to re-apply effects
+        ALOGV("Signalling Effects Thread");
+        pBaseClass->mEffectCv.signal();
+
+    }
+    ALOGV("ioConfigChanged Out");
+}
+
+void AudioFlinger::DirectAudioTrack::acquireWakeLock()
+{
+    Mutex::Autolock _l(pmLock);
+
+    if (mPowerManager == 0) {
+        // use checkService() to avoid blocking if power service is not up yet
+        sp<IBinder> binder =
+            defaultServiceManager()->checkService(String16("power"));
+        if (binder == 0) {
+            ALOGW("Thread %s cannot connect to the power manager service", lockName);
+        } else {
+            mPowerManager = interface_cast<IPowerManager>(binder);
+            binder->linkToDeath(mDeathRecipient);
+        }
+    }
+    if (mPowerManager != 0 && mWakeLockToken == 0) {
+        sp<IBinder> binder = new BBinder();
+        status_t status = mPowerManager->acquireWakeLock(POWERMANAGER_PARTIAL_WAKE_LOCK,
+                                                         binder,
+                                                         String16(lockName),
+                                                         String16("media"));
+        if (status == NO_ERROR) {
+            mWakeLockToken = binder;
+        }
+        ALOGV("acquireWakeLock() status %d", status);
+    }
+}
+
+void AudioFlinger::DirectAudioTrack::releaseWakeLock()
+{
+   Mutex::Autolock _l(pmLock);
+
+    if (mWakeLockToken != 0) {
+        ALOGV("releaseWakeLock()");
+        if (mPowerManager != 0) {
+            mPowerManager->releaseWakeLock(mWakeLockToken, 0);
+        }
+        mWakeLockToken.clear();
+    }
+}
+
+void AudioFlinger::DirectAudioTrack::clearPowerManager()
+{
+    releaseWakeLock();
+    Mutex::Autolock _l(pmLock);
+    mPowerManager.clear();
+}
+
+void AudioFlinger::DirectAudioTrack::PMDeathRecipient::binderDied(const wp<IBinder>& who)
+{
+    parentClass->clearPowerManager();
+    ALOGW("power manager service died !!!");
+}
+
+// ----------------------------------------------------------------------------
+#endif
+
 }; // namespace android
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index 207f1eb..8036a28 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -1,5 +1,6 @@
 /*
-**
+** Copyright (c) 2013, The Linux Foundation. All rights reserved.
+** Not a Contribution.
 ** Copyright 2012, The Android Open Source Project
 **
 ** Licensed under the Apache License, Version 2.0 (the "License");
@@ -137,6 +138,9 @@
     virtual     status_t    setParameters(const String8& keyValuePairs);
     virtual     String8     getParameters(const String8& keys) = 0;
     virtual     void        audioConfigChanged_l(int event, int param = 0) = 0;
+#ifdef QCOM_HARDWARE
+                void        effectConfigChanged();
+#endif
                 void        sendIoConfigEvent(int event, int param = 0);
                 void        sendIoConfigEvent_l(int event, int param = 0);
                 void        sendPrioConfigEvent_l(pid_t pid, pid_t tid, int32_t prio);
diff --git a/services/audioflinger/TrackBase.h b/services/audioflinger/TrackBase.h
index cd201d9..ab83955 100644
--- a/services/audioflinger/TrackBase.h
+++ b/services/audioflinger/TrackBase.h
@@ -43,6 +43,9 @@
                                 audio_format_t format,
                                 audio_channel_mask_t channelMask,
                                 size_t frameCount,
+#ifdef QCOM_HARDWARE
+                                uint32_t flags,
+#endif
                                 const sp<IMemory>& sharedBuffer,
                                 int sessionId,
                                 int uid,
@@ -132,7 +135,9 @@
                                     // 8-bit PCM samples are stored as 16-bit
     const size_t        mFrameCount;// size of track buffer given at createTrack() or
                                     // openRecord(), and then adjusted as needed
-
+#ifdef QCOM_HARDWARE
+    uint32_t            mFlags;
+#endif
     const int           mSessionId;
     int                 mUid;
     Vector < sp<SyncEvent> >mSyncEvents;
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index d6b9908..59b611a 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -66,6 +66,9 @@
             audio_format_t format,
             audio_channel_mask_t channelMask,
             size_t frameCount,
+#ifdef QCOM_HARDWARE
+            uint32_t flags,
+#endif
             const sp<IMemory>& sharedBuffer,
             int sessionId,
             int clientUid,
@@ -80,9 +83,17 @@
         mFormat(format),
         mChannelMask(channelMask),
         mChannelCount(popcount(channelMask)),
+#ifdef QCOM_HARDWARE
+        mFrameSize((audio_is_linear_pcm(format) || audio_is_supported_compressed(format)) ?
+        ((flags & IAudioFlinger::TRACK_VOICE_COMMUNICATION)? mChannelCount * sizeof(int16_t) : mChannelCount * audio_bytes_per_sample(format)) : sizeof(int8_t)),
+#else
         mFrameSize(audio_is_linear_pcm(format) ?
                 mChannelCount * audio_bytes_per_sample(format) : sizeof(int8_t)),
+#endif
         mFrameCount(frameCount),
+#ifdef QCOM_HARDWARE
+        mFlags(0),
+#endif
         mSessionId(sessionId),
         mIsOut(isOut),
         mServerProxy(NULL),
@@ -109,7 +120,31 @@
 
     // ALOGD("Creating track with %d buffers @ %d bytes", bufferCount, bufferSize);
     size_t size = sizeof(audio_track_cblk_t);
+#ifdef QCOM_HARDWARE
+    uint8_t channelCount = popcount(channelMask);
+    size_t bufferSize = 0;
+    if (flags & IAudioFlinger::TRACK_VOICE_COMMUNICATION) {
+          bufferSize = roundup(frameCount) * channelCount * mFrameSize;
+    } else {
+       if ( (format == AUDIO_FORMAT_PCM_16_BIT) ||
+            (format == AUDIO_FORMAT_PCM_8_BIT)) {
+          bufferSize = frameCount * channelCount * sizeof(int16_t);
+       } else if (format == AUDIO_FORMAT_AMR_NB) {
+          bufferSize = frameCount * channelCount * AMR_FRAMESIZE;    // full rate frame size
+       } else if (format == AUDIO_FORMAT_EVRC) {
+          bufferSize = frameCount * channelCount * EVRC_FRAMESIZE;   // full rate frame size
+       } else if (format == AUDIO_FORMAT_QCELP) {
+          bufferSize = frameCount * channelCount * QCELP_FRAMESIZE;  // full rate frame size
+       } else if (format == AUDIO_FORMAT_AAC) {
+          bufferSize = frameCount * AAC_FRAMESIZE;                   // full rate frame size
+       } else if (format == AUDIO_FORMAT_AMR_WB) {
+          bufferSize = frameCount * channelCount * AMR_WB_FRAMESIZE; // full rate frame size
+       }
+    }
+#else
     size_t bufferSize = (sharedBuffer == 0 ? roundup(frameCount) : frameCount) * mFrameSize;
+#endif
+
     if (sharedBuffer == 0) {
         size += bufferSize;
     }
@@ -137,7 +172,33 @@
         mCblk->frameCount_ = frameCount;
         if (sharedBuffer == 0) {
             mBuffer = (char*)mCblk + sizeof(audio_track_cblk_t);
+#ifdef QCOM_HARDWARE
+            if (flags & IAudioFlinger::TRACK_VOICE_COMMUNICATION) {
+                memset(mBuffer, 0, bufferSize);
+            } else {
+                if ((format == AUDIO_FORMAT_PCM_16_BIT) ||
+                   (format == AUDIO_FORMAT_PCM_8_BIT)) {
+                    memset(mBuffer, 0, bufferSize);
+                } else if (format == AUDIO_FORMAT_AMR_NB) {
+                    // full rate frame size
+                    memset(mBuffer, 0, frameCount * channelCount * AMR_FRAMESIZE);
+                } else if (format == AUDIO_FORMAT_EVRC) {
+                    // full rate frame size
+                    memset(mBuffer, 0, frameCount * channelCount * EVRC_FRAMESIZE);
+                } else if (format == AUDIO_FORMAT_QCELP) {
+                    // full rate frame size
+                    memset(mBuffer, 0, frameCount * channelCount * QCELP_FRAMESIZE);
+                } else if (format == AUDIO_FORMAT_AAC) {
+                    // full rate frame size
+                    memset(mBuffer, 0, frameCount * AAC_FRAMESIZE);
+                } else if (format == AUDIO_FORMAT_AMR_WB) {
+                    // full rate frame size
+                    memset(mBuffer, 0, frameCount * channelCount * AMR_WB_FRAMESIZE);
+                }
+            }
+#else
             memset(mBuffer, 0, bufferSize);
+#endif
         } else {
             mBuffer = sharedBuffer->pointer();
 #if 0
@@ -328,8 +389,14 @@
             int sessionId,
             int uid,
             IAudioFlinger::track_flags_t flags)
+#ifdef QCOM_HARDWARE
+    :   TrackBase(thread, client, sampleRate, format, channelMask, frameCount,
+     ((audio_stream_type_t)streamType == AUDIO_STREAM_VOICE_CALL)? IAudioFlinger::TRACK_VOICE_COMMUNICATION:0x0,
+     sharedBuffer, sessionId, uid, true /*isOut*/),
+#else
     :   TrackBase(thread, client, sampleRate, format, channelMask, frameCount, sharedBuffer,
             sessionId, uid, true /*isOut*/),
+#endif
     mFillingUpStatus(FS_INVALID),
     // mRetryCount initialized later when needed
     mSharedBuffer(sharedBuffer),
@@ -1756,13 +1823,24 @@
             audio_format_t format,
             audio_channel_mask_t channelMask,
             size_t frameCount,
+#ifdef QCOM_HARDWARE
+            uint32_t flags,
+#endif
             int sessionId,
             int uid)
+#ifdef QCOM_HARDWARE
+    :   TrackBase(thread, client, sampleRate, format, channelMask, frameCount,
+        flags, 0 /*sharedBuffer*/, sessionId, uid, false /*isOut*/),
+#else
     :   TrackBase(thread, client, sampleRate, format,
                   channelMask, frameCount, 0 /*sharedBuffer*/, sessionId, uid, false /*isOut*/),
+#endif
         mOverflow(false)
 {
     ALOGV("RecordTrack constructor");
+#ifdef QCOM_HARDWARE
+    mFlags = flags;
+#endif
     if (mCblk != NULL) {
         mAudioRecordServerProxy = new AudioRecordServerProxy(mCblk, mBuffer, frameCount,
                 mFrameSize);
diff --git a/services/camera/libcameraservice/Android.mk b/services/camera/libcameraservice/Android.mk
index 51ba698..9fc4c40 100644
--- a/services/camera/libcameraservice/Android.mk
+++ b/services/camera/libcameraservice/Android.mk
@@ -58,6 +58,18 @@
 
 LOCAL_CFLAGS += -Wall -Wextra
 
+ifeq ($(BOARD_USES_QCOM_LEGACY_CAM_PARAMS),true)
+    LOCAL_CFLAGS += -DQCOM_LEGACY_CAM_PARAMS
+endif
+
+ifeq ($(BOARD_HAVE_HTC_FFC),true)
+    LOCAL_CFLAGS += -DBOARD_HAVE_HTC_FFC
+endif
+
+ifeq ($(BOARD_HTC_3D_SUPPORT),true)
+    LOCAL_CFLAGS += -DHTC_3D_SUPPORT
+endif
+
 LOCAL_MODULE:= libcameraservice
 
 include $(BUILD_SHARED_LIBRARY)
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index 5957d97..243ff9f 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -21,6 +21,8 @@
 #include <stdio.h>
 #include <sys/types.h>
 #include <pthread.h>
+#include <unistd.h>
+#include <fcntl.h>
 
 #include <binder/AppOpsManager.h>
 #include <binder/IPCThreadState.h>
@@ -37,6 +39,7 @@
 #include <utils/Log.h>
 #include <utils/String16.h>
 
+#include <system/camera.h>
 #include "CameraService.h"
 #include "api1/CameraClient.h"
 #include "api1/Camera2Client.h"
@@ -85,6 +88,24 @@
 
 // ----------------------------------------------------------------------------
 
+#if defined(BOARD_HAVE_HTC_FFC)
+#define HTC_SWITCH_CAMERA_FILE_PATH "/sys/android_camera2/htcwc"
+static void htcCameraSwitch(int cameraId)
+{
+    char buffer[16];
+    int fd;
+
+    if (access(HTC_SWITCH_CAMERA_FILE_PATH, W_OK) == 0) {
+        snprintf(buffer, sizeof(buffer), "%d", cameraId);
+
+        fd = open(HTC_SWITCH_CAMERA_FILE_PATH, O_WRONLY);
+        write(fd, buffer, strlen(buffer));
+        close(fd);
+    }
+}
+#endif
+
+
 // This is ugly and only safe if we never re-create the CameraService, but
 // should be ok for now.
 static CameraService *gCameraService;
@@ -365,6 +386,10 @@
     String8 clientName8(clientPackageName);
     int callingPid = getCallingPid();
 
+#if defined(BOARD_HAVE_HTC_FFC)
+    htcCameraSwitch(cameraId);
+#endif
+
     if (mClient[cameraId] != 0) {
         client = mClient[cameraId].promote();
         if (client != 0) {
@@ -891,8 +916,18 @@
     LOG1("CameraService::loadSound ref=%d", mSoundRef);
     if (mSoundRef++) return;
 
-    mSoundPlayer[SOUND_SHUTTER] = newMediaPlayer("/system/media/audio/ui/camera_click.ogg");
-    mSoundPlayer[SOUND_RECORDING] = newMediaPlayer("/system/media/audio/ui/VideoRecord.ogg");
+    char value[PROPERTY_VALUE_MAX];
+    property_get("persist.camera.shutter.disable", value, "0");
+    int disableSound = atoi(value);
+
+    if(!disableSound) {
+        mSoundPlayer[SOUND_SHUTTER] = newMediaPlayer("/system/media/audio/ui/camera_click.ogg");
+        mSoundPlayer[SOUND_RECORDING] = newMediaPlayer("/system/media/audio/ui/VideoRecord.ogg");
+    }
+    else {
+        mSoundPlayer[SOUND_SHUTTER] = NULL;
+        mSoundPlayer[SOUND_RECORDING] = NULL;
+    }
 }
 
 void CameraService::releaseSound() {
@@ -936,6 +971,7 @@
     LOG1("Client::Client E (pid %d, id %d)", callingPid, cameraId);
 
     mRemoteCallback = cameraClient;
+    mLongshotEnabled = false;
 
     cameraService->setCameraBusy(cameraId);
     cameraService->loadSound();
@@ -970,6 +1006,9 @@
     mServicePid = servicePid;
     mOpsActive = false;
     mDestructionStarted = false;
+#ifdef QCOM_HARDWARE
+    mBurstCnt = 0;
+#endif
 }
 
 CameraService::BasicClient::~BasicClient() {
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index ad6a582..1864fbb 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -35,7 +35,11 @@
 #include <camera/ICameraServiceListener.h>
 
 /* This needs to be increased if we can have more cameras */
+#ifdef OMAP_ENHANCEMENT
+#define MAX_CAMERAS 3
+#else
 #define MAX_CAMERAS 2
+#endif
 
 namespace android {
 
@@ -172,6 +176,9 @@
         pid_t                           mClientPid;
         uid_t                           mClientUid;      // immutable after constructor
         pid_t                           mServicePid;     // immutable after constructor
+#ifdef QCOM_HARDWARE
+        int                             mBurstCnt;
+#endif
 
         // - The app-side Binder interface to receive callbacks from us
         sp<IBinder>                     mRemoteBinder;   // immutable after constructor
@@ -260,11 +267,11 @@
 
         virtual void         notifyError();
 
-        // Initialized in constructor
 
         // - The app-side Binder interface to receive callbacks from us
         sp<ICameraClient>               mRemoteCallback;
 
+        bool                 mLongshotEnabled;
     }; // class Client
 
     class ProClient : public BnProCameraUser, public BasicClient {
diff --git a/services/camera/libcameraservice/api1/CameraClient.cpp b/services/camera/libcameraservice/api1/CameraClient.cpp
index bd6805d..d63eb3c 100644
--- a/services/camera/libcameraservice/api1/CameraClient.cpp
+++ b/services/camera/libcameraservice/api1/CameraClient.cpp
@@ -88,8 +88,14 @@
             (void *)mCameraId);
 
     // Enable zoom, error, focus, and metadata messages by default
-    enableMsgType(CAMERA_MSG_ERROR | CAMERA_MSG_ZOOM | CAMERA_MSG_FOCUS |
-                  CAMERA_MSG_PREVIEW_METADATA | CAMERA_MSG_FOCUS_MOVE);
+    enableMsgType(CAMERA_MSG_ERROR | CAMERA_MSG_ZOOM | CAMERA_MSG_FOCUS
+#ifndef QCOM_HARDWARE
+                  | CAMERA_MSG_PREVIEW_METADATA 
+#endif
+#ifndef OMAP_ICS_CAMERA
+                  | CAMERA_MSG_FOCUS_MOVE
+#endif
+                 );
 
     LOG1("CameraClient::initialize X (pid %d, id %d)", callingPid, mCameraId);
     return OK;
@@ -252,7 +258,9 @@
     if (mPreviewWindow != 0) {
         disconnectWindow(mPreviewWindow);
         mPreviewWindow = 0;
+#ifndef NO_UPDATE_PREVIEW
         mHardware->setPreviewWindow(mPreviewWindow);
+#endif
     }
     mHardware.clear();
 
@@ -350,6 +358,9 @@
 
 // start preview mode
 status_t CameraClient::startPreview() {
+#ifdef QCOM_HARDWARE
+    enableMsgType(CAMERA_MSG_PREVIEW_METADATA);
+#endif
     LOG1("startPreview (pid %d)", getCallingPid());
     return startCameraMode(CAMERA_PREVIEW_MODE);
 }
@@ -400,6 +411,11 @@
         native_window_set_buffers_transform(mPreviewWindow.get(),
                 mOrientation);
     }
+
+#if defined(OMAP_ICS_CAMERA) || defined(OMAP_ENHANCEMENT_BURST_CAPTURE)
+    disableMsgType(CAMERA_MSG_COMPRESSED_BURST_IMAGE);
+#endif
+
     mHardware->setPreviewWindow(mPreviewWindow);
     result = mHardware->startPreview();
 
@@ -436,11 +452,35 @@
 // stop preview mode
 void CameraClient::stopPreview() {
     LOG1("stopPreview (pid %d)", getCallingPid());
+#ifdef QCOM_HARDWARE
+    disableMsgType(CAMERA_MSG_PREVIEW_METADATA);
+#endif
     Mutex::Autolock lock(mLock);
     if (checkPidAndHardware() != NO_ERROR) return;
 
+#ifdef OMAP_ENHANCEMENT
+    // According to framework documentation, preview needs
+    // to be started for image capture. This will make sure
+    // that image capture related messages get disabled if
+    // not done already in their respective handlers.
+    // If these messages come when in the midddle of
+    // stopping preview we will deadlock the system in
+    // lockIfMessageWanted().
+    disableMsgType(CAMERA_MSG_POSTVIEW_FRAME);
+#endif
 
     disableMsgType(CAMERA_MSG_PREVIEW_FRAME);
+#ifdef QCOM_HARDWARE
+    //Disable picture related message types
+    ALOGI("stopPreview: Disable picture related messages");
+    int picMsgType = 0;
+    picMsgType = (CAMERA_MSG_SHUTTER |
+                  CAMERA_MSG_POSTVIEW_FRAME |
+                  CAMERA_MSG_RAW_IMAGE |
+                  CAMERA_MSG_RAW_IMAGE_NOTIFY |
+                  CAMERA_MSG_COMPRESSED_IMAGE);
+    disableMsgType(picMsgType);
+#endif
     mHardware->stopPreview();
 
     mPreviewBuffer.clear();
@@ -453,6 +493,17 @@
     if (checkPidAndHardware() != NO_ERROR) return;
 
     disableMsgType(CAMERA_MSG_VIDEO_FRAME);
+#ifdef QCOM_HARDWARE
+    //Disable picture related message types
+    ALOGI("stopRecording: Disable picture related messages");
+    int picMsgType = 0;
+    picMsgType = (CAMERA_MSG_SHUTTER |
+                  CAMERA_MSG_POSTVIEW_FRAME |
+                  CAMERA_MSG_RAW_IMAGE |
+                  CAMERA_MSG_RAW_IMAGE_NOTIFY |
+                  CAMERA_MSG_COMPRESSED_IMAGE);
+    disableMsgType(picMsgType);
+#endif
     mHardware->stopRecording();
     mCameraService->playSound(CameraService::SOUND_RECORDING);
 
@@ -534,9 +585,24 @@
                            CAMERA_MSG_POSTVIEW_FRAME |
                            CAMERA_MSG_RAW_IMAGE |
                            CAMERA_MSG_RAW_IMAGE_NOTIFY |
+#if defined(OMAP_ICS_CAMERA) || defined(OMAP_ENHANCEMENT_BURST_CAPTURE)
+                           CAMERA_MSG_RAW_BURST |
+#endif
                            CAMERA_MSG_COMPRESSED_IMAGE);
 
+#if defined(OMAP_ICS_CAMERA) || defined(OMAP_ENHANCEMENT_BURST_CAPTURE)
+    picMsgType |= CAMERA_MSG_COMPRESSED_BURST_IMAGE;
+#endif
+#ifdef QCOM_HARDWARE
+    disableMsgType(CAMERA_MSG_PREVIEW_METADATA);
+#endif
     enableMsgType(picMsgType);
+#ifdef QCOM_HARDWARE
+    mBurstCnt = mHardware->getParameters().getInt("num-snaps-per-shutter");
+    if(mBurstCnt <= 0)
+        mBurstCnt = 1;
+    LOG1("mBurstCnt = %d", mBurstCnt);
+#endif
 
     return mHardware->takePicture();
 }
@@ -630,6 +696,22 @@
     } else if (cmd == CAMERA_CMD_PING) {
         // If mHardware is 0, checkPidAndHardware will return error.
         return OK;
+#ifdef QCOM_HARDWARE
+    } else if (cmd == CAMERA_CMD_HISTOGRAM_ON) {
+        enableMsgType(CAMERA_MSG_STATS_DATA);
+    } else if (cmd == CAMERA_CMD_HISTOGRAM_OFF) {
+        disableMsgType(CAMERA_MSG_STATS_DATA);
+    } else if (cmd == CAMERA_CMD_METADATA_ON) {
+        enableMsgType(CAMERA_MSG_META_DATA);
+    } else if (cmd == CAMERA_CMD_METADATA_OFF) {
+        disableMsgType(CAMERA_MSG_META_DATA);
+    } else if ( cmd == CAMERA_CMD_LONGSHOT_ON ) {
+        mLongshotEnabled = true;
+    } else if ( cmd == CAMERA_CMD_LONGSHOT_OFF ) {
+        mLongshotEnabled = false;
+        disableMsgType(CAMERA_MSG_SHUTTER);
+        disableMsgType(CAMERA_MSG_COMPRESSED_IMAGE);
+#endif
     }
 
     return mHardware->sendCommand(cmd, arg1, arg2);
@@ -651,6 +733,14 @@
 bool CameraClient::lockIfMessageWanted(int32_t msgType) {
     int sleepCount = 0;
     while (mMsgEnabled & msgType) {
+#ifdef QCOM_HARDWARE
+        if ((msgType == CAMERA_MSG_PREVIEW_FRAME) &&
+              (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE)) {
+           LOG1("lockIfMessageWanted(%d): Don't try to acquire mlock if "
+                "both Preview and Compressed are enabled", msgType);
+           return false;
+        }
+#endif
         if (mLock.tryLock() == NO_ERROR) {
             if (sleepCount > 0) {
                 LOG1("lockIfMessageWanted(%d): waited for %d ms",
@@ -694,6 +784,12 @@
         int32_t ext2, void* user) {
     LOG2("notifyCallback(%d)", msgType);
 
+    // Ignore CAF_RESTART callbacks from Samsung's camera driver
+    if (msgType == CAMERA_MSG_FOCUS && ext1 == 4) {
+        LOG2("Ignore CAF_RESTART callback");
+        return;
+    }
+
     Mutex* lock = getClientLockFromCookie(user);
     if (lock == NULL) return;
     Mutex::Autolock alock(*lock);
@@ -747,6 +843,11 @@
         case CAMERA_MSG_COMPRESSED_IMAGE:
             client->handleCompressedPicture(dataPtr);
             break;
+#if defined(OMAP_ICS_CAMERA) || defined(OMAP_ENHANCEMENT_BURST_CAPTURE)
+        case CAMERA_MSG_COMPRESSED_BURST_IMAGE:
+            client->handleCompressedBurstPicture(dataPtr);
+            break;
+#endif
         default:
             client->handleGenericData(msgType, dataPtr, metadata);
             break;
@@ -788,7 +889,9 @@
         c->notifyCallback(CAMERA_MSG_SHUTTER, 0, 0);
         if (!lockIfMessageWanted(CAMERA_MSG_SHUTTER)) return;
     }
-    disableMsgType(CAMERA_MSG_SHUTTER);
+    if ( !mLongshotEnabled ) {
+        disableMsgType(CAMERA_MSG_SHUTTER);
+    }
 
     mLock.unlock();
 }
@@ -867,7 +970,17 @@
 
 // picture callback - compressed picture ready
 void CameraClient::handleCompressedPicture(const sp<IMemory>& mem) {
-    disableMsgType(CAMERA_MSG_COMPRESSED_IMAGE);
+#ifdef QCOM_HARDWARE
+    if (mBurstCnt)
+        mBurstCnt--;
+
+    if (!mBurstCnt && !mLongshotEnabled) {
+        LOG1("handleCompressedPicture mBurstCnt = %d", mBurstCnt);
+#endif
+        disableMsgType(CAMERA_MSG_COMPRESSED_IMAGE);
+#ifdef QCOM_HARDWARE
+    }
+#endif
 
     sp<ICameraClient> c = mRemoteCallback;
     mLock.unlock();
@@ -876,6 +989,20 @@
     }
 }
 
+#if defined(OMAP_ICS_CAMERA) || defined(OMAP_ENHANCEMENT_BURST_CAPTURE)
+// burst picture callback - compressed picture ready
+void CameraClient::handleCompressedBurstPicture(const sp<IMemory>& mem) {
+    // Don't disable this message type yet. In this mode takePicture() will
+    // get called only once. When burst finishes this message will get automatically
+    // disabled in the respective call for restarting the preview.
+
+    sp<ICameraClient> c = mCameraClient;
+    mLock.unlock();
+    if (c != 0) {
+        c->dataCallback(CAMERA_MSG_COMPRESSED_IMAGE, mem, NULL);
+    }
+}
+#endif
 
 void CameraClient::handleGenericNotify(int32_t msgType,
     int32_t ext1, int32_t ext2) {
diff --git a/services/camera/libcameraservice/api1/CameraClient.h b/services/camera/libcameraservice/api1/CameraClient.h
index 4b89564..f460763 100644
--- a/services/camera/libcameraservice/api1/CameraClient.h
+++ b/services/camera/libcameraservice/api1/CameraClient.h
@@ -105,6 +105,9 @@
     void                    handlePostview(const sp<IMemory>& mem);
     void                    handleRawPicture(const sp<IMemory>& mem);
     void                    handleCompressedPicture(const sp<IMemory>& mem);
+#if defined(OMAP_ICS_CAMERA) || defined(OMAP_ENHANCEMENT_BURST_CAPTURE)
+    void                    handleCompressedBurstPicture(const sp<IMemory>& mem);
+#endif
     void                    handleGenericNotify(int32_t msgType, int32_t ext1, int32_t ext2);
     void                    handleGenericData(int32_t msgType, const sp<IMemory>& dataPtr,
             camera_frame_metadata_t *metadata);
diff --git a/services/camera/libcameraservice/device1/CameraHardwareInterface.h b/services/camera/libcameraservice/device1/CameraHardwareInterface.h
index 87b2807..2bdf827 100644
--- a/services/camera/libcameraservice/device1/CameraHardwareInterface.h
+++ b/services/camera/libcameraservice/device1/CameraHardwareInterface.h
@@ -451,13 +451,17 @@
         ALOGV("%s", __FUNCTION__);
         CameraHardwareInterface *__this =
                 static_cast<CameraHardwareInterface *>(user);
-        sp<CameraHeapMemory> mem(static_cast<CameraHeapMemory *>(data->handle));
-        if (index >= mem->mNumBufs) {
+        if (data != NULL) {
+          sp<CameraHeapMemory> mem(static_cast<CameraHeapMemory *>(data->handle));
+          if (index >= mem->mNumBufs) {
             ALOGE("%s: invalid buffer index %d, max allowed is %d", __FUNCTION__,
                  index, mem->mNumBufs);
             return;
+          }
+          __this->mDataCb(msg_type, mem->mBuffers[index], metadata, __this->mCbUser);
+        } else {
+          __this->mDataCb(msg_type, NULL, metadata, __this->mCbUser);
         }
-        __this->mDataCb(msg_type, mem->mBuffers[index], metadata, __this->mCbUser);
     }
 
     static void __data_cb_timestamp(nsecs_t timestamp, int32_t msg_type,
@@ -636,6 +640,9 @@
 
     static int __set_usage(struct preview_stream_ops* w, int usage)
     {
+#ifdef HTC_3D_SUPPORT
+        usage |= GRALLOC_USAGE_PRIVATE_0;
+#endif
         ANativeWindow *a = anw(w);
         return native_window_set_usage(a, usage);
     }
@@ -654,6 +661,14 @@
         return a->query(a, NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, count);
     }
 
+#ifdef HTC_3D_SUPPORT
+    static int __set_3d_mode(
+                      const struct preview_stream_ops *w, int r1, int r2, int r3)
+    {
+        return 0;
+    }
+#endif
+
     void initHalPreviewWindow()
     {
         mHalPreviewWindow.nw.cancel_buffer = __cancel_buffer;
@@ -661,6 +676,9 @@
         mHalPreviewWindow.nw.dequeue_buffer = __dequeue_buffer;
         mHalPreviewWindow.nw.enqueue_buffer = __enqueue_buffer;
         mHalPreviewWindow.nw.set_buffer_count = __set_buffer_count;
+#ifdef HTC_3D_SUPPORT
+        mHalPreviewWindow.nw.set_3d_mode = __set_3d_mode;
+#endif
         mHalPreviewWindow.nw.set_buffers_geometry = __set_buffers_geometry;
         mHalPreviewWindow.nw.set_crop = __set_crop;
         mHalPreviewWindow.nw.set_timestamp = __set_timestamp;